From 506e1c287ffde837151ffe5d5a2dd73cebcb2a75 Mon Sep 17 00:00:00 2001 From: Yingtong Li Date: Mon, 25 Sep 2017 11:56:10 +1000 Subject: [PATCH] Implement dynamic test discovery and running --- eos/base/tests.py | 4 +-- eos/core/tests.py | 16 ++++++++---- eos/tests.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++ test.sh | 2 +- 4 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 eos/tests.py diff --git a/eos/base/tests.py b/eos/base/tests.py index c8fab26..1220e2d 100644 --- a/eos/base/tests.py +++ b/eos/base/tests.py @@ -14,13 +14,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from unittest import TestCase +from eos.core.tests import EosTestCase from eos.base.election import * from eos.base.workflow import * from eos.core.objects import * -class ElectionPyTestCase(TestCase): +class ElectionTestCase(EosTestCase): @classmethod def setUpClass(cls): client.drop_database('test') diff --git a/eos/core/tests.py b/eos/core/tests.py index 9a68707..28ff546 100644 --- a/eos/core/tests.py +++ b/eos/core/tests.py @@ -14,13 +14,19 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from unittest import TestCase - from eos.core.bigint import * from eos.core.bitstring import * from eos.core.objects import * -class ObjectPyTestCase(TestCase): +class EosTestCase: + @classmethod + def setUpClass(cls): + pass + + def assertEqual(self, a, b): + self.impl.assertEqual(a, b) + +class ObjectTestCase(EosTestCase): @classmethod def setUpClass(cls): class Person(TopLevelObject): @@ -43,7 +49,7 @@ class ObjectPyTestCase(TestCase): def test_serialise(self): person1 = self.Person(name='John', address='Address 1') expect1 = {'_ver': '0.1', 'name': 'John', 'address': 'Address 1'} - expect1a = {'type': 'eos.core.tests.ObjectPyTestCase.setUpClass..Person', 'value': expect1} + expect1a = {'type': 'eos.core.tests.ObjectTestCase.setUpClass..Person', 'value': expect1} self.assertEqual(person1.serialise(), expect1) self.assertEqual(EosObject.serialise_and_wrap(person1, self.Person), expect1) @@ -52,7 +58,7 @@ class ObjectPyTestCase(TestCase): #self.assertEqual(EosObject.deserialise_and_unwrap(expect1a), person1) self.assertEqual(EosObject.deserialise_and_unwrap(expect1a).serialise(), person1.serialise()) -class BigIntPyTestCase(TestCase): +class BigIntTestCase(EosTestCase): def test_basic(self): bigint1 = BigInt(5) bigint2 = BigInt('A', 16) diff --git a/eos/tests.py b/eos/tests.py new file mode 100644 index 0000000..3f71b8e --- /dev/null +++ b/eos/tests.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# Eos - Verifiable elections +# Copyright © 2017 RunasSudo (Yingtong Li) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from unittest import * + +from eos.core.bigint import * +from eos.core.bitstring import * +from eos.core.objects import * + +import importlib +import os +import types + +test_suite = TestSuite() + +# All the TestCase's we dynamically generate inherit from this class +class BaseTestCase(TestCase): + @classmethod + def setUpClass(cls): + cls.impl.setUpClass() + + @classmethod + def add_method(cls, method): + def call_method(self, *args): + cls.impl.impl = self + func = getattr(cls.impl, method) + return func(*args) + setattr(cls, method, call_method) + +# Test discovery +import eos.core.tests +for dirpath, dirnames, filenames in os.walk('eos'): + if dirpath == 'eos': + # Skip this file + continue + if 'tests.py' in filenames: + module = importlib.import_module(dirpath.replace('/', '.') + '.tests') + for name in dir(module): + obj = getattr(module, name) + if isinstance(obj, type): + if issubclass(obj, eos.core.tests.EosTestCase): + cls = type(name + 'Impl', (BaseTestCase,), {'impl': obj()}) + for method in dir(cls.impl): + if isinstance(getattr(cls.impl, method), types.MethodType) and not hasattr(cls, method): + cls.add_method(method) + if method.startswith('test_'): + test_case = cls(method) + test_suite.addTest(test_case) + +TextTestRunner(verbosity=3).run(test_suite) diff --git a/test.sh b/test.sh index f3ef02c..3073999 100755 --- a/test.sh +++ b/test.sh @@ -1,3 +1,3 @@ #!/bin/bash -coverage run --source=eos --omit='*/js.py','*/tests.py' -m unittest discover . -vvv || exit 1 +coverage run --source=eos --omit='*/js.py','eos/js_tests.py','*/tests.py' -m eos.tests || exit 1 coverage html