diff --git a/oscar/main.cpp b/oscar/main.cpp
index 9c3f67fd..ce3477b0 100644
--- a/oscar/main.cpp
+++ b/oscar/main.cpp
@@ -6,6 +6,10 @@
  * License. See the file COPYING in the main directory of the source code
  * for more details. */
 
+#ifdef UNITTEST_MODE
+#include "tests/AutoTest.h"
+#endif
+
 #include <QApplication>
 #include <QMessageBox>
 #include <QDebug>
@@ -242,6 +246,15 @@ bool migrateFromSH(QString destDir) {
     return success;
 }
 
+#ifdef UNITTEST_MODE
+
+int main(int argc, char* argv[])
+{
+    AutoTest::run(argc, argv);
+}
+
+#else
+
 int main(int argc, char *argv[]) {
 #ifdef Q_WS_X11
     XInitThreads();
@@ -576,3 +589,5 @@ int main(int argc, char *argv[]) {
 
     return a.exec();
 }
+
+#endif // !UNITTEST_MODE
diff --git a/oscar/oscar.pro b/oscar/oscar.pro
index a6e44db3..96bb0ef3 100644
--- a/oscar/oscar.pro
+++ b/oscar/oscar.pro
@@ -432,3 +432,22 @@ DISTFILES += help/default.css \
     help/help_en/OSCAR_Guide_en.qhp \
     help/index.qhcp
 }
+
+# Turn on unit testing by adding "CONFIG+=test" to your qmake command
+test {
+    TARGET = test
+    DEFINES += UNITTEST_MODE
+
+    QT += testlib
+    QT -= gui
+    CONFIG += console
+    CONFIG -= app_bundle
+
+    SOURCES += \
+        tests/prs1tests.cpp
+
+    HEADERS += \
+        tests/AutoTest.h \
+        tests/prs1tests.h
+}
+
diff --git a/oscar/tests/AutoTest.h b/oscar/tests/AutoTest.h
new file mode 100644
index 00000000..8ee352da
--- /dev/null
+++ b/oscar/tests/AutoTest.h
@@ -0,0 +1,80 @@
+// From https://qtcreator.blogspot.com/2009/10/running-multiple-unit-tests.html
+#ifndef AUTOTEST_H
+#define AUTOTEST_H
+
+#include <QTest>
+#include <QList>
+#include <QString>
+#include <QSharedPointer>
+
+namespace AutoTest
+{
+    typedef QList<QObject*> TestList;
+
+    inline TestList& testList()
+    {
+        static TestList list;
+        return list;
+    }
+
+    inline bool findObject(QObject* object)
+    {
+        TestList& list = testList();
+        if (list.contains(object))
+        {
+            return true;
+        }
+        foreach (QObject* test, list)
+        {
+            if (test->objectName() == object->objectName())
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    inline void addTest(QObject* object)
+    {
+        TestList& list = testList();
+        if (!findObject(object))
+        {
+            list.append(object);
+        }
+    }
+
+    inline int run(int argc, char *argv[])
+    {
+        int ret = 0;
+
+        foreach (QObject* test, testList())
+        {
+            ret += QTest::qExec(test, argc, argv);
+        }
+
+        return ret;
+    }
+}
+
+template <class T>
+class Test
+{
+public:
+    QSharedPointer<T> child;
+
+    Test(const QString& name) : child(new T)
+    {
+        child->setObjectName(name);
+        AutoTest::addTest(child.data());
+    }
+};
+
+#define DECLARE_TEST(className) static Test<className> t(#className);
+
+#define TEST_MAIN \
+    int main(int argc, char *argv[]) \
+    { \
+        return AutoTest::run(argc, argv); \
+    }
+
+#endif // AUTOTEST_H
diff --git a/oscar/tests/prs1tests.cpp b/oscar/tests/prs1tests.cpp
new file mode 100644
index 00000000..1de381c8
--- /dev/null
+++ b/oscar/tests/prs1tests.cpp
@@ -0,0 +1,17 @@
+#include "prs1tests.h"
+
+void PRS1Tests::initTestCase(void)
+{
+}
+
+void PRS1Tests::cleanupTestCase(void)
+{
+}
+
+
+void PRS1Tests::test1()
+{
+    // TODO: emit test message to stdout
+    qDebug("First test!");
+}
+
diff --git a/oscar/tests/prs1tests.h b/oscar/tests/prs1tests.h
new file mode 100644
index 00000000..de531643
--- /dev/null
+++ b/oscar/tests/prs1tests.h
@@ -0,0 +1,20 @@
+#ifndef PRS1TESTS_H
+#define PRS1TESTS_H
+
+#include "AutoTest.h"
+
+class PRS1Tests : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void test1();
+ // void test2();
+ void cleanupTestCase();
+};
+
+DECLARE_TEST(PRS1Tests)
+
+#endif // PRS1TESTS_H
+