diff run-tests @ 71:88adf10be709 draft

Add tests.
author David Barts <n5jrn@me.com>
date Mon, 15 Jul 2019 13:16:31 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/run-tests	Mon Jul 15 13:16:31 2019 -0700
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+# Run our tests. Basically, these use the python unittest framework, but
+# are organized into a directory tree containing test code and the server
+# files to run the tests against. The tests are done by creating a local
+# server on the specified port (default 8080) and issuing requests to it.
+#
+# Note that some of the test suites we run require the requests and/or
+# Beautiful Soup libraries (these are not needed for running TInCan, only
+# for testing it.)
+
+# I m p o r t s
+
+import os, sys
+import importlib
+import logging
+import unittest
+from argparse import ArgumentParser
+
+# V a r i a b l e s
+
+MYNAME = os.path.basename(sys.argv[0])
+TESTDIR = "tests"
+FPREFIX = "suite_"
+FILESDIR = "files"
+FILESVAR = "files"
+PORTVAR = "port"
+
+# F u n c t i o n s
+
+def is_test(d):
+    if not d.startswith(FPREFIX):
+        return False
+    return os.path.isdir(os.path.join(TESTDIR, d)) and os.path.isdir(os.path.join(TESTDIR, d, FILESDIR))
+
+def is_subclass(a, b):
+    try:
+        return issubclass(a, b)
+    except TypeError:
+        return False
+
+# M a i n   P r o g r a m
+
+# Parse arguments
+parser = ArgumentParser(prog=sys.argv[0], usage="%(prog)s [options]")
+parser.add_argument("-p", "--port", default=8080, help="port to use (default: 8080)")
+args = parser.parse_args(sys.argv[1:])
+
+# Reject attempts to run out of directory
+if not os.path.isdir(TESTDIR):
+    sys.stderr.write("{0}: {1!r} - no such directory\n".format(MYNAME, TESTDIR))
+    sys.exit(2)
+
+# Get the log file name and ensure the log file is cleared
+from tests import LOGNAME, LOGGERNAME
+open(LOGNAME, "w").close()
+
+# Make a logger object for ServerFixture to use
+mylog = logging.getLogger(LOGGERNAME)
+handler = logging.FileHandler(LOGNAME)
+handler.setFormatter(
+    logging.Formatter(fmt="%(asctime)s - %(levelname)s: %(message)s"))
+mylog.addHandler(handler)
+mylog.setLevel(logging.INFO)
+
+# Locate all fixtures and operate on them
+failures = 0
+fixtures = sorted(filter(is_test, os.listdir(TESTDIR)))
+if not fixtures:
+    sys.stderr.write("{0}: warning - no fixtures found\n".format(MYNAME))
+for fixture in fixtures:
+    name = "{0}.{1}".format(TESTDIR, fixture)
+    sys.stderr.write("{0}: running {1} ...\n".format(MYNAME, name))
+    module = importlib.import_module(name)
+    directory = os.path.join(TESTDIR, fixture, FILESDIR)
+    for i in dir(module):
+        v = getattr(module, i)
+        if is_subclass(v, unittest.TestCase):
+            setattr(v, FILESVAR, directory)
+            setattr(v, PORTVAR, args.port)
+    suite = unittest.defaultTestLoader.loadTestsFromModule(module)
+    result = unittest.TextTestRunner(verbosity=1).run(suite)
+    if result.wasSuccessful():
+        sys.stderr.write("{0}: {1} passed\n".format(MYNAME, name))
+    else:
+        sys.stderr.write("{0}: {1} failed\n".format(MYNAME, name))
+        failures += 1
+
+# AMF...
+if failures:
+    sys.stderr.write("{0}: {1} suite{2} failed\n".format(
+        MYNAME,
+        failures,
+        "" if failures == 1 else "s"))
+
+sys.stdout.write("Note: server log output is in {0!r}.\n".format(LOGNAME))
+sys.exit(1 if failures else 0)