提交 a0197f21 编写于 作者: R Rudá Moura

avocado.loader: Introduce multiple tests.

Introduce multiple test methods defined in Avocado Test class.
The tests looks like the one of unittest module.

The test methods are defined when you create test<something> methods,
inside the test class. Each test methods becomes a test case unit
to execute.

Example:

class MyTest(avocado.test.Test):
    def test_eone(self)...
    def test_two(self)...
    def testAnotherone(self)...
Signed-off-by: NRudá Moura <rmoura@redhat.com>
上级 d6abdcd4
......@@ -53,6 +53,19 @@ class TestLoader(object):
job = _DebugJob()
self.job = job
def _is_unittests_like(self, test_class, pattern='test'):
for name, _ in inspect.getmembers(test_class, inspect.ismethod):
if name.startswith(pattern):
return True
return False
def _make_unittests_like(self, test_class, pattern='test'):
test_methods = []
for name, obj in inspect.getmembers(test_class, inspect.ismethod):
if name.startswith(pattern):
test_methods.append((name, obj))
return test_methods
def _make_missing_test(self, test_name, params):
test_class = test.MissingTest
test_parameters = {'name': test_name,
......@@ -77,7 +90,7 @@ class TestLoader(object):
'job': self.job}
return test_class, test_parameters
def _make_test(self, test_name, test_path, params):
def _make_tests(self, test_name, test_path, params):
module_name = os.path.basename(test_path).split('.')[0]
test_module_dir = os.path.dirname(test_path)
sys.path.append(test_module_dir)
......@@ -103,6 +116,16 @@ class TestLoader(object):
if test_class is not None:
# Module is importable and does have an avocado test class
# inside, let's proceed.
if self._is_unittests_like(test_class):
test_factories = []
for test_method in self._make_unittests_like(test_class):
copy_test_parameters_name = test_parameters_name.copy()
copy_test_parameters_name['methodName'] = test_method[0]
class_and_method_name = ':%s.%s' % (test_class.__name__, test_method[0])
copy_test_parameters_name['name'] += class_and_method_name
test_factories.append([test_class, copy_test_parameters_name])
return test_factories
else:
test_parameters = test_parameters_name
else:
if os.access(test_path, os.X_OK):
......@@ -147,27 +170,26 @@ class TestLoader(object):
sys.path.pop(sys.path.index(test_module_dir))
return test_class, test_parameters
return [(test_class, test_parameters)]
def discover_test(self, params):
def discover_tests(self, params):
"""
Try to discover and resolve a test.
Try to discover and resolve tests.
:param params: dictionary with test parameters.
:type params: dict
:return: a test factory (a pair of test class and test parameters)
or `None`.
:return: a list of test factories (a pair of test class and test parameters).
"""
test_name = test_path = params.get('id')
if os.path.exists(test_path):
if os.access(test_path, os.R_OK) is False:
return (AccessDeniedPath,
{'params': {'id': test_path}})
return [(AccessDeniedPath, {'params': {'id': test_path}})]
path_analyzer = path.PathInspector(test_path)
if path_analyzer.is_python():
test_class, test_parameters = self._make_test(test_name,
test_factories = self._make_tests(test_name,
test_path,
params)
return test_factories
else:
if os.access(test_path, os.X_OK):
test_class, test_parameters = self._make_simple_test(test_path,
......@@ -179,21 +201,20 @@ class TestLoader(object):
if os.path.islink(test_path):
try:
if not os.path.isfile(os.readlink(test_path)):
return BrokenSymlink, {'params': {'id': test_path}}
return [(BrokenSymlink, {'params': {'id': test_path}})]
except OSError:
return AccessDeniedPath, {'params': {'id': test_path}}
return [(AccessDeniedPath, {'params': {'id': test_path}})]
# Try to resolve test ID (keep compatibility)
rel_path = '%s.py' % test_name
test_path = os.path.join(data_dir.get_test_dir(), rel_path)
if os.path.exists(test_path):
test_class, test_parameters = self._make_test(rel_path,
test_path,
params)
test_factories = self._make_tests(rel_path, test_path, params)
return test_factories
else:
test_class, test_parameters = self._make_missing_test(
test_name, params)
return test_class, test_parameters
return [(test_class, test_parameters)]
def discover_url(self, url):
"""
......@@ -264,7 +285,8 @@ class TestLoader(object):
"""
test_suite = []
for params in params_list:
test_factory = self.discover_test(params)
test_factories = self.discover_tests(params)
for test_factory in test_factories:
if test_factory is None:
continue
test_class, test_parameters = test_factory
......
......@@ -71,6 +71,17 @@ class MyInheritedTest(MyBaseTest):
pass
"""
AVOCADO_MULTIPLE_TESTS = """from avocado import test
class MultipleMethods(test.Test):
def test_one(self):
pass
def testTwo(self):
pass
def foo(self):
pass
"""
class _DebugJob(object):
logdir = tempfile.mkdtemp()
......@@ -88,7 +99,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
simple_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': simple_test.path}))
self.loader.discover_tests(params={'id': simple_test.path})[0])
self.assertTrue(test_class == test.SimpleTest, test_class)
tc = test_class(**test_parameters)
tc.runTest()
......@@ -100,7 +111,7 @@ class LoaderTest(unittest.TestCase):
mode=0664)
simple_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': simple_test.path}))
self.loader.discover_tests(params={'id': simple_test.path})[0])
self.assertTrue(test_class == test.NotATest, test_class)
tc = test_class(**test_parameters)
self.assertRaises(exceptions.NotATestError, tc.runTest)
......@@ -112,7 +123,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
avocado_pass_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_pass_test.path}))
self.loader.discover_tests(params={'id': avocado_pass_test.path})[0])
self.assertTrue(str(test_class) == "<class 'passtest.PassTest'>",
str(test_class))
self.assertTrue(issubclass(test_class, test.Test))
......@@ -126,7 +137,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
avocado_base_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_base_test.path}))
self.loader.discover_tests(params={'id': avocado_base_test.path})[0])
self.assertTrue(str(test_class) == "<class 'base.MyBaseTest'>",
str(test_class))
......@@ -135,7 +146,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
avocado_inherited_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_inherited_test.path}))
self.loader.discover_tests(params={'id': avocado_inherited_test.path})[0])
self.assertTrue(str(test_class) == "<class 'inherited.MyInheritedTest'>",
str(test_class))
avocado_base_test.remove()
......@@ -147,7 +158,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
avocado_buggy_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_buggy_test.path}))
self.loader.discover_tests(params={'id': avocado_buggy_test.path})[0])
self.assertTrue(test_class == test.SimpleTest, test_class)
tc = test_class(**test_parameters)
self.assertRaises(exceptions.TestFail, tc.runTest)
......@@ -160,7 +171,7 @@ class LoaderTest(unittest.TestCase):
mode=0664)
avocado_buggy_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_buggy_test.path}))
self.loader.discover_tests(params={'id': avocado_buggy_test.path})[0])
self.assertTrue(test_class == test.BuggyTest, test_class)
tc = test_class(**test_parameters)
self.assertRaises(ImportError, tc.runTest)
......@@ -173,7 +184,7 @@ class LoaderTest(unittest.TestCase):
mode=0664)
avocado_not_a_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_not_a_test.path}))
self.loader.discover_tests(params={'id': avocado_not_a_test.path})[0])
self.assertTrue(test_class == test.NotATest, test_class)
tc = test_class(**test_parameters)
self.assertRaises(exceptions.NotATestError, tc.runTest)
......@@ -184,7 +195,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
avocado_not_a_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_not_a_test.path}))
self.loader.discover_tests(params={'id': avocado_not_a_test.path})[0])
self.assertTrue(test_class == test.SimpleTest, test_class)
tc = test_class(**test_parameters)
# The test can't be executed (no shebang), raising an OSError
......@@ -198,7 +209,7 @@ class LoaderTest(unittest.TestCase):
'avocado_loader_unittest')
avocado_simple_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_simple_test.path}))
self.loader.discover_tests(params={'id': avocado_simple_test.path})[0])
self.assertTrue(test_class == test.SimpleTest)
tc = test_class(**test_parameters)
tc.runTest()
......@@ -211,12 +222,22 @@ class LoaderTest(unittest.TestCase):
mode=0664)
avocado_simple_test.save()
test_class, test_parameters = (
self.loader.discover_test(params={'id': avocado_simple_test.path}))
self.loader.discover_tests(params={'id': avocado_simple_test.path})[0])
self.assertTrue(test_class == test.NotATest)
tc = test_class(**test_parameters)
self.assertRaises(exceptions.NotATestError, tc.runTest)
avocado_simple_test.remove()
def test_multiple_methods(self):
avocado_multiple_tests = script.TemporaryScript('multipletests.py',
AVOCADO_MULTIPLE_TESTS,
'avocado_multiple_tests_unittest',
mode=0664)
avocado_multiple_tests.save()
suite = self.loader.discover_tests(params={'id': avocado_multiple_tests.path})
self.assertEqual(len(suite), 2)
avocado_multiple_tests.remove()
def tearDown(self):
if os.path.isdir(self.job.logdir):
shutil.rmtree(self.job.logdir)
......
#!/usr/bin/python
from avocado import test
from avocado import job
class MultipleTests(test.Test):
"""
Following the idea of unittest module,
every test method starts with a 'test' prefix,
so that 'test_foo' and 'testFoo' are test methods,
but 'division_by_zero' and 'action' are not.
"""
def setUp(self):
self.hello = "Hi there!"
def test_hello(self):
self.assertEqual(self.hello, "Hi there!")
def testIdentity(self):
self.assertTrue(1, 1)
def division_by_zero(self):
"This method should never execute"
return 1 / 0
def action(self):
"This method should never execute"
pass
if __name__ == '__main__':
job.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册