Migrating to Python v3

 - support for Python v3.8.x
 - support for Python v3.5.x
 - new tag, 2019.2.8
 - updates class generation and iterators
 - unittests updated with coverage >75%
 - new coverage routines
 - unittests profiling
 - full fake data for unittests
 - unittest testrun is ~1.5 seconds long

Bugfixes
 - 34834, proper use of 'sudo' option
 - multiple proper iterator use
 - 37919, show warning when installed and candidate versions
   are newer comparing to release version

Change-Id: Idd6b889f7ce94ae0c832e2f0a0346e4fdc3264a3
Related-PROD: PROD-34834 PROD-34664 PROD-34919
diff --git a/runtests.py b/runtests.py
new file mode 100644
index 0000000..3da567f
--- /dev/null
+++ b/runtests.py
@@ -0,0 +1,55 @@
+import os
+import shutil
+import unittest
+
+from unittest import TextTestResult, TextTestRunner
+from tests.test_base import tests_dir
+from tests.test_packages import _res_dir
+
+
+class MyTestResult(TextTestResult):
+    def getDescription(self, test):
+        # return super().getDescription(test)
+        doc_first_line = test.shortDescription()
+        if self.descriptions and doc_first_line:
+            return '\n'.join((str(test), doc_first_line))
+        else:
+            # return str(test)
+            return "{}.{}.{}".format(
+                test.__class__.__module__,
+                test.__class__.__name__,
+                test._testMethodName
+            )
+
+
+class MyTestRunner(TextTestRunner):
+    resultclass = MyTestResult
+
+
+def _cleanup():
+    _fpath = [
+        "repo.info.tgz",
+        "repo.versions.tgz",
+        "pkg.descriptions.tgz"
+    ]
+    for _p in _fpath:
+        _fp = os.path.join(_res_dir, _p)
+        if os.path.exists(_fp):
+            os.remove(_fp)
+
+    _ferr = os.path.join(_res_dir, "fakeerrors")
+    if os.path.exists(_ferr):
+        shutil.rmtree(_ferr)
+
+
+if __name__ == '__main__':
+    # remove old files if exists
+    _cleanup()
+
+    # start tests
+    suite = unittest.TestLoader().discover(tests_dir, "test_*", tests_dir)
+    runner = MyTestRunner(verbosity=3)
+    runner.run(suite)
+
+    # cleanup after testrun
+    _cleanup()