diff --git a/avocado/job.py b/avocado/job.py index 51326dc0d093951aba0e8a375db01f012aacf1a5..1f6f6dc4d15f35b25d9d8225f7f5713dc401a20e 100644 --- a/avocado/job.py +++ b/avocado/job.py @@ -24,6 +24,7 @@ import sys import traceback import tempfile import shutil +import fnmatch from avocado import multiplexer from avocado import result @@ -268,9 +269,23 @@ class Job(object): e_msg = '\n'.join(error_msg_parts) raise exceptions.OptionValidationError(e_msg) + # Filter tests methods with params.filter and methodName + filtered_suite = [] + for test_template in test_suite: + test_factory, test_parameters = test_template + filter_pattern = test_parameters['params'].get('filter', None) + method = test_parameters.get('methodName') + if not filter_pattern: + filtered_suite.append(test_template) + else: + if method and fnmatch.fnmatch(method, filter_pattern): + filtered_suite.append(test_template) + test_suite = filtered_suite + if not test_suite: e_msg = ("No tests found within the specified path(s) " - "(Possible reasons: File ownership, permissions, typos)") + "(Possible reasons: File ownership, permissions, " + "filters, typos)") raise exceptions.OptionValidationError(e_msg) self.args.test_result_total = mux.get_number_of_tests(test_suite) diff --git a/avocado/loader.py b/avocado/loader.py index 820aa8b915f424e1eb5a657c2b064b72c6b4c453..42936d87ccc8474f90dc7eed94a7bb985a5280dc 100644 --- a/avocado/loader.py +++ b/avocado/loader.py @@ -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,7 +116,17 @@ class TestLoader(object): if test_class is not None: # Module is importable and does have an avocado test class # inside, let's proceed. - test_parameters = test_parameters_name + 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): # Module does not have an avocado test class inside but @@ -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_path, - params) + 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): """ @@ -212,6 +233,12 @@ class TestLoader(object): '__main__.py') params_list = [] + # Look for filename:test_method pattern + if ':' in url: + url, filter_pattern = url.split(':', 1) + else: + filter_pattern = None + def onerror(exception): norm_url = os.path.abspath(url) norm_error_filename = os.path.abspath(exception.filename) @@ -221,6 +248,7 @@ class TestLoader(object): omit_non_tests = False params_list.append({'id': exception.filename, + 'filter': filter_pattern, 'omit_non_tests': omit_non_tests}) for dirpath, dirnames, filenames in os.walk(url, onerror=onerror): @@ -264,15 +292,16 @@ class TestLoader(object): """ test_suite = [] for params in params_list: - test_factory = self.discover_test(params) - if test_factory is None: - continue - test_class, test_parameters = test_factory - if test_class in [test.NotATest, BrokenSymlink, AccessDeniedPath]: - if not params.get('omit_non_tests'): + test_factories = self.discover_tests(params) + for test_factory in test_factories: + if test_factory is None: + continue + test_class, test_parameters = test_factory + if test_class in [test.NotATest, BrokenSymlink, AccessDeniedPath]: + if not params.get('omit_non_tests'): + test_suite.append((test_class, test_parameters)) + else: test_suite.append((test_class, test_parameters)) - else: - test_suite.append((test_class, test_parameters)) return test_suite @staticmethod diff --git a/avocado/plugins/runner.py b/avocado/plugins/runner.py index 85ee350122ccc73781b4e3b9e643711f4af6d697..d0e945a136991c5b0076d4dd61505de18c984f1a 100644 --- a/avocado/plugins/runner.py +++ b/avocado/plugins/runner.py @@ -139,7 +139,4 @@ class TestRunner(plugin.Plugin): job_instance = job.Job(args) rc = job_instance.run() - if not args.url: - self.parser.print_help() - return rc diff --git a/avocado/plugins/test_list.py b/avocado/plugins/test_list.py index 61668e6cc4b70691250ab3410e02796ef32efd37..c55804658afc2d9dd0b0f26e384c8573605c66ab 100644 --- a/avocado/plugins/test_list.py +++ b/avocado/plugins/test_list.py @@ -129,6 +129,7 @@ class TestList(plugin.Plugin): else: if issubclass(cls, test.Test): stats['instrumented'] += 1 + id_label = params['name'] type_label = self.term_support.healthy_str('INSTRUMENTED') test_matrix.append((type_label, id_label)) diff --git a/avocado/test.py b/avocado/test.py index 50ea5f51bcd90a757b3f1f0ed79db1ecbbfeb3d3..c119b479297e893312ac2322707dc9fd28da412b 100644 --- a/avocado/test.py +++ b/avocado/test.py @@ -48,7 +48,7 @@ class Test(unittest.TestCase): Base implementation for the test class. You'll inherit from this to write your own tests. Typically you'll want - to implement setup(), action() and cleanup() methods on your own tests. + to implement setUp(), runTest() and tearDown() methods on your own tests. """ default_params = {} @@ -94,8 +94,9 @@ class Test(unittest.TestCase): tmpdir = data_dir.get_tmp_dir() - self.basedir = os.path.dirname(inspect.getfile(self.__class__)) - self.datadir = os.path.join(self.basedir, '%s.data' % basename) + self.filename = inspect.getfile(self.__class__).rstrip('co') + self.basedir = os.path.dirname(self.filename) + self.datadir = utils_path.init_dir(self.filename + '.data') self.expected_stdout_file = os.path.join(self.datadir, 'stdout.expected') @@ -181,7 +182,7 @@ class Test(unittest.TestCase): self.runner_queue = runner_queue self.time_elapsed = None - unittest.TestCase.__init__(self) + unittest.TestCase.__init__(self, methodName=methodName) def __str__(self): return str(self.name) @@ -312,9 +313,9 @@ class Test(unittest.TestCase): return tagged_name - def setup(self): + def setUp(self): """ - Setup stage that the test needs before passing to the actual action. + Setup stage that the test needs before passing to the actual runTest. Must be implemented by tests if they want such an stage. Commonly we'll download/compile test suites, create files needed for a test, among @@ -322,7 +323,7 @@ class Test(unittest.TestCase): """ pass - def action(self): + def runTest(self): """ Actual test payload. Must be implemented by tests. @@ -331,14 +332,13 @@ class Test(unittest.TestCase): operations decide if the test pass (let the test complete) or fail (raise a test related exception). """ - raise NotImplementedError('Test subclasses must implement an action ' - 'method') + pass - def cleanup(self): + def tearDown(self): """ - Cleanup stage after the action is done. + Cleanup stage after the runTest is done. - Examples of cleanup actions are deleting temporary files, restoring + Examples of cleanup runTests are deleting temporary files, restoring firewall configurations or other system settings that were changed in setup. """ @@ -368,31 +368,32 @@ class Test(unittest.TestCase): 'Actual:\n%s\nExpected:\n%s' % (actual, expected)) self.assertEqual(expected, actual, msg) - def runTest(self, result=None): + def run(self, result=None): """ Run test method, for compatibility with unittest.TestCase. :result: Unused param, compatibiltiy with :class:`unittest.TestCase`. """ + testMethod = getattr(self, self._testMethodName) self.start_logging() self.sysinfo_logger.start_test_hook() - action_exception = None + runTest_exception = None cleanup_exception = None stdout_check_exception = None stderr_check_exception = None try: - self.setup() + self.setUp() except Exception, details: stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') raise exceptions.TestSetupFail(details) try: - self.action() + testMethod() except Exception, details: stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') - action_exception = details + runTest_exception = details finally: try: - self.cleanup() + self.tearDown() except Exception, details: stacktrace.log_exc_info(sys.exc_info(), logger='avocado.test') cleanup_exception = details @@ -429,8 +430,8 @@ class Test(unittest.TestCase): self.record_reference_stderr() # pylint: disable=E0702 - if action_exception is not None: - raise action_exception + if runTest_exception is not None: + raise runTest_exception elif cleanup_exception is not None: raise exceptions.TestSetupFail(cleanup_exception) elif stdout_check_exception is not None: @@ -458,14 +459,14 @@ class Test(unittest.TestCase): def run_avocado(self, result=None): """ - Wraps the runTest method, for execution inside the avocado runner. + Wraps the run method, for execution inside the avocado runner. :result: Unused param, compatibility with :class:`unittest.TestCase`. """ self._setup_environment_variables() try: self.tag_start() - self.runTest(result) + self.run(result) except exceptions.TestBaseException, detail: self.status = detail.status self.fail_class = detail.__class__.__name__ @@ -545,7 +546,7 @@ class SimpleTest(Test): self.log.info("Exit status: %s", result.exit_status) self.log.info("Duration: %s", result.duration) - def action(self): + def runTest(self): """ Run the executable, and log its detailed execution. """ @@ -560,8 +561,8 @@ class SimpleTest(Test): self._log_detailed_cmd_info(details.result) raise exceptions.TestFail(details) - def runTest(self, result=None): - super(SimpleTest, self).runTest(result) + def run(self, result=None): + super(SimpleTest, self).run(result) for line in open(self.logfile): if self.re_avocado_log.match(line): raise exceptions.TestWarn("Test passed but there were warnings" @@ -582,7 +583,7 @@ class MissingTest(Test): tag=tag, job=job, runner_queue=runner_queue) - def action(self): + def runTest(self): e_msg = ('Test %s could not be found in the test dir %s ' '(or test path does not exist)' % (self.name, data_dir.get_test_dir())) @@ -606,7 +607,7 @@ class BuggyTest(Test): tag=tag, job=job, runner_queue=runner_queue) - def action(self): + def runTest(self): # pylint: disable=E0702 raise self.params.get('exception') @@ -627,7 +628,7 @@ class NotATest(Test): tag=tag, job=job, runner_queue=runner_queue) - def action(self): + def runTest(self): e_msg = ('File %s is not executable and does not contain an avocado ' 'test class in it ' % self.name) raise exceptions.NotATestError(e_msg) diff --git a/docs/source/DebuggingWithGDB.rst b/docs/source/DebuggingWithGDB.rst index 9b2ee857e34b5258294254119d99bf7756b076ee..1102ef04ba33f4c826cd17c01f8dbde6bc75aed0 100644 --- a/docs/source/DebuggingWithGDB.rst +++ b/docs/source/DebuggingWithGDB.rst @@ -21,7 +21,7 @@ Example Take a look at ``examples/tests/modify_variable.py`` test:: - def action(self): + def runTest(self): """ Execute 'print_variable'. """ @@ -102,7 +102,7 @@ test:: class HelloOutputTest(test.Test): - def action(self): + def runTest(self): result = process.run("/path/to/hello", ignore_status=True) self.assertIn("hello\n", result.stdout) diff --git a/docs/source/WritingTests.rst b/docs/source/WritingTests.rst index 06936310b3285a05f0b11d0a68a1e46d7e878d82..6d0b92d84ab46eefc170d844909e131903ac9ac7 100644 --- a/docs/source/WritingTests.rst +++ b/docs/source/WritingTests.rst @@ -28,7 +28,7 @@ Now that we covered how avocado resolves tests, let's get to business. This section is concerned with writing an avocado test. The process is not hard, all you need to do is to create a test module, which is a python file with a class that inherits from :class:`avocado.test.Test`. This class only -really needs to implement a method called `action`, which represents the actual +really needs to implement a method called `runTest`, which represents the actual sequence of test operations. Simple example @@ -53,7 +53,7 @@ nothing but ``time.sleep([number-seconds])``:: """ default_params = {'sleep_length': 1.0} - def action(self): + def runTest(self): """ Sleep for length seconds. """ @@ -92,7 +92,7 @@ encoded it first (base64 is the obvious choice). Building on the previously demonstrated sleeptest, suppose that you want to save the sleep length to be used by some other script or data analysis tool:: - def action(self): + def runTest(self): """ Sleep for length seconds. """ @@ -189,7 +189,7 @@ Since avocado tests inherit from :class:`unittest.TestCase`, you can use all the :func:`assert` class methods on your tests. Some silly examples:: class RandomExamples(test.Test): - def action(self): + def runTest(self): self.log.debug("Verifying some random math...") four = 2 * 2 four_ = 2 + 2 @@ -242,7 +242,7 @@ Setup and cleanup methods ========================= If you need to perform setup actions before/after your test, you may do so -in the ``setup`` and ``cleanup`` methods, respectively. We'll give examples +in the ``setUp`` and ``tearDown`` methods, respectively. We'll give examples in the following section. Running third party test suites @@ -275,7 +275,7 @@ an example that does that:: 'sync_length': 100, 'sync_loop': 10} - def setup(self): + def setUp(self): """ Set default params and build the synctest suite. """ @@ -286,7 +286,7 @@ an example that does that:: self.srcdir = os.path.join(self.srcdir, 'synctest') build.make(self.srcdir) - def action(self): + def runTest(self): """ Execute synctest with the appropriate params. """ @@ -488,7 +488,7 @@ You may log something into the test logs using the methods in class output_test(test.Test): - def action(self): + def runTest(self): self.log.info('This goes to the log and it is only informational') self.log.warn('Oh, something unexpected, non-critical happened, ' 'but we can continue.') @@ -505,7 +505,7 @@ stderr streams, you can do something like:: class output_test(test.Test): - def action(self): + def runTest(self): self.log.info('This goes to the log and it is only informational') self.stdout_log.info('This goes to the test stdout (will be recorded)') self.stderr_log.info('This goes to the test stderr (will be recorded)') @@ -618,7 +618,7 @@ a timeout of 3 seconds before avocado ends the test forcefully by sending a default_params = {'timeout': 3.0, 'sleep_time': 5.0} - def action(self): + def runTest(self): """ This should throw a TestTimeoutError. """ diff --git a/examples/tests/abort.py b/examples/tests/abort.py index 5699ca85fb5aaed658c281c9a7f173a6047a8967..b73b24690fbacbd0582706bc8d1e68d77a50ac70 100644 --- a/examples/tests/abort.py +++ b/examples/tests/abort.py @@ -13,7 +13,7 @@ class AbortTest(test.Test): """ default_params = {'timeout': 2.0} - def action(self): + def runTest(self): os.abort() diff --git a/examples/tests/cabort.py b/examples/tests/cabort.py index 3808b28a0677cce75e6eec9133d89ab91afe6a7c..48d2783160f16e4c5e1805086a41a594bba7c07e 100755 --- a/examples/tests/cabort.py +++ b/examples/tests/cabort.py @@ -17,7 +17,7 @@ class CAbort(test.Test): default_params = {'source': 'abort.c'} - def setup(self): + def setUp(self): """ Build 'abort'. """ @@ -29,7 +29,7 @@ class CAbort(test.Test): env={'CFLAGS': '-g -O0'}, extra_args='abort') - def action(self): + def runTest(self): """ Execute 'abort'. """ diff --git a/examples/tests/datadir.py b/examples/tests/datadir.py index 285fae598cd75163f63b6fdff3e93fd63b2f24b0..df53e3cc955b71e60415cc61bca24a15ef3d39f6 100644 --- a/examples/tests/datadir.py +++ b/examples/tests/datadir.py @@ -17,7 +17,7 @@ class DataDirTest(test.Test): default_params = {'source': 'datadir.c'} - def setup(self): + def setUp(self): """ Build 'datadir'. """ @@ -29,7 +29,7 @@ class DataDirTest(test.Test): env={'CFLAGS': '-g -O0'}, extra_args='datadir') - def action(self): + def runTest(self): """ Execute 'datadir'. """ diff --git a/examples/tests/doublefail.py b/examples/tests/doublefail.py index 6fd57cf0df46a2320000150ed14082b314ecd337..5fd16b2328a3898162400f3b4132f8f1cc1382cd 100755 --- a/examples/tests/doublefail.py +++ b/examples/tests/doublefail.py @@ -11,17 +11,17 @@ class DoubleFail(test.Test): Functional test for avocado. Straight up fail the test. """ - def action(self): + def runTest(self): """ Should fail. """ raise exceptions.TestFail('This test is supposed to fail') - def cleanup(self): + def tearDown(self): """ Should also fail. """ - raise exceptions.TestError('Failing during cleanup. Yay!') + raise exceptions.TestError('Failing during tearDown. Yay!') if __name__ == "__main__": diff --git a/examples/tests/doublefree.py b/examples/tests/doublefree.py index a9889bbe97408847068d2e81eb255fd17c128502..af1882a57676f5a926f5756e4ea9f5bacc4133b2 100755 --- a/examples/tests/doublefree.py +++ b/examples/tests/doublefree.py @@ -18,7 +18,7 @@ class DoubleFreeTest(test.Test): default_params = {'source': 'doublefree.c'} - def setup(self): + def setUp(self): """ Build 'doublefree'. """ @@ -30,7 +30,7 @@ class DoubleFreeTest(test.Test): env={'CFLAGS': '-g -O0'}, extra_args='doublefree') - def action(self): + def runTest(self): """ Execute 'doublefree'. """ diff --git a/examples/tests/doublefree_nasty.py b/examples/tests/doublefree_nasty.py index 25c8655c49f4e642494a4ee8f9c2a3c9d8333371..d4e224fd843e7a4c6ce176fd933e0b97599521c9 100755 --- a/examples/tests/doublefree_nasty.py +++ b/examples/tests/doublefree_nasty.py @@ -18,7 +18,7 @@ class DoubleFreeTest(test.Test): default_params = {'source': 'doublefree.c'} __binary = None # filename of the compiled program - def setup(self): + def setUp(self): """ Build 'doublefree'. """ @@ -29,7 +29,7 @@ class DoubleFreeTest(test.Test): env={'CFLAGS': '-g -O0'}, extra_args=self.__binary) - def action(self): + def runTest(self): """ Execute 'doublefree'. """ diff --git a/examples/tests/errortest.py b/examples/tests/errortest.py index bf029ea3b7b6da6e254a0792ce120d1468800c9b..2726b5af0952765468e4bed9a7647c5c3de13a01 100755 --- a/examples/tests/errortest.py +++ b/examples/tests/errortest.py @@ -11,7 +11,7 @@ class ErrorTest(test.Test): Functional test for avocado. Throw a TestError. """ - def action(self): + def runTest(self): """ This should throw a TestError. """ diff --git a/examples/tests/failtest.py b/examples/tests/failtest.py index db32edc0aca8b29bf5d84291a55928b55357aed8..d943183f8c8fdd04571231e86865f0430593c8f7 100755 --- a/examples/tests/failtest.py +++ b/examples/tests/failtest.py @@ -11,7 +11,7 @@ class FailTest(test.Test): Functional test for avocado. Straight up fail the test. """ - def action(self): + def runTest(self): """ Should fail. """ diff --git a/examples/tests/failtest_nasty.py b/examples/tests/failtest_nasty.py index b9ca90873bd7b723360e93fcde4c526faebcd15f..cb097d381a87531fd71d95ddb846be4aaeeeb332 100755 --- a/examples/tests/failtest_nasty.py +++ b/examples/tests/failtest_nasty.py @@ -21,7 +21,7 @@ class FailTest(test.Test): Very nasty exception test """ - def action(self): + def runTest(self): """ Should fail not-that-badly """ diff --git a/examples/tests/failtest_nasty2.py b/examples/tests/failtest_nasty2.py index 71dac05b04a983362694df839183ffd3a2271031..c92f5302ef2b4025cdc8e647388085fb977aba9e 100755 --- a/examples/tests/failtest_nasty2.py +++ b/examples/tests/failtest_nasty2.py @@ -21,7 +21,7 @@ class FailTest(test.Test): Very nasty exception test """ - def action(self): + def runTest(self): """ Should fail. """ diff --git a/examples/tests/fiotest.py b/examples/tests/fiotest.py index 4c0733d9afff80c62554c89c9a51fe414fac712a..88e17d3bf5423d1a8275de0ae8a24d5ced0c61c5 100755 --- a/examples/tests/fiotest.py +++ b/examples/tests/fiotest.py @@ -21,7 +21,7 @@ class FioTest(test.Test): default_params = {'fio_tarball': 'fio-2.1.10.tar.bz2', 'fio_job': 'fio-mixed.job'} - def setup(self): + def setUp(self): """ Build 'fio'. """ @@ -31,7 +31,7 @@ class FioTest(test.Test): self.srcdir = os.path.join(self.srcdir, fio_version) build.make(self.srcdir) - def action(self): + def runTest(self): """ Execute 'fio' with appropriate parameters. """ diff --git a/examples/tests/gdbtest.py b/examples/tests/gdbtest.py index 9e8afdbf793d29caec05d0007e58f700c9348a6d..a264ef32e1f775b32995bc84074dc0a6b55d304e 100755 --- a/examples/tests/gdbtest.py +++ b/examples/tests/gdbtest.py @@ -26,7 +26,7 @@ class GdbTest(test.Test): "-find-me-the-bug", "-auto-debug-it"] - def setup(self): + def setUp(self): self.return99_binary_path = os.path.join(self.outputdir, 'return99') return99_source_path = self.get_data_path('return99.c') process.system('gcc -O0 -g %s -o %s' % (return99_source_path, @@ -407,32 +407,6 @@ class GdbTest(test.Test): r.cmd("qfThreadInfo") s.exit() - def action(self): - """ - Execute tests - """ - self.test_start_exit() - self.test_existing_commands_raw() - self.test_existing_commands() - self.test_load_set_breakpoint_run_exit_raw() - self.test_load_set_breakpoint_run_exit() - self.test_generate_core() - self.test_set_multiple_break() - self.test_disconnect_raw() - self.test_disconnect() - self.test_remote_exec() - self.test_stream_messages() - self.test_connect_multiple_clients() - self.test_server_exit() - self.test_multiple_servers() - self.test_interactive() - self.test_interactive_args() - self.test_exit_status() - self.test_server_stderr() - self.test_server_stderr_redirected() - self.test_server_stdout() - self.test_interactive_stdout() - self.test_remote() if __name__ == '__main__': job.main() diff --git a/examples/tests/gendata.py b/examples/tests/gendata.py index 672f9a2636df0932944ca46f3afb61fe6902ce03..6f743355f8bec63f44ad805c25c53e62cfcd4426 100755 --- a/examples/tests/gendata.py +++ b/examples/tests/gendata.py @@ -41,7 +41,7 @@ class GenDataTest(test.Test): "outputdir": self.outputdir} json.dump(output, open(output_path, "w")) - def action(self): + def runTest(self): self.generate_bsod() self.generate_json() diff --git a/examples/tests/linuxbuild.py b/examples/tests/linuxbuild.py index 7edc2fd0c31301995bd55f5c5633a2639f923520..52e59c09c042a27076131ba62a6841bbfd8b5dc6 100755 --- a/examples/tests/linuxbuild.py +++ b/examples/tests/linuxbuild.py @@ -13,7 +13,7 @@ class LinuxBuildTest(test.Test): default_params = {'linux_version': '3.14.5', 'linux_config': 'config'} - def setup(self): + def setUp(self): kernel_version = self.params.linux_version config_path = self.get_data_path('config') self.linux_build = kernel_build.KernelBuild(kernel_version, @@ -23,7 +23,7 @@ class LinuxBuildTest(test.Test): self.linux_build.uncompress() self.linux_build.configure() - def action(self): + def runTest(self): self.linux_build.build() diff --git a/examples/tests/modify_variable.py b/examples/tests/modify_variable.py index b41e9cb10ac53388eb221c9e5924cf20f4c02b2e..b4d2619096070f26980db4804e43ddd1c49a26eb 100755 --- a/examples/tests/modify_variable.py +++ b/examples/tests/modify_variable.py @@ -21,7 +21,7 @@ class PrintVariableTest(test.Test): default_params = {'source': 'print_variable.c'} __binary = None # filename of the compiled program - def setup(self): + def setUp(self): """ Build 'print_variable'. """ @@ -32,7 +32,7 @@ class PrintVariableTest(test.Test): env={'CFLAGS': '-g -O0'}, extra_args=self.__binary) - def action(self): + def runTest(self): """ Execute 'print_variable'. """ diff --git a/examples/tests/multiplextest.py b/examples/tests/multiplextest.py index 00965c5b2e4e56a5ae3585a55c27c84232f1c6ca..74c5fc049454d86b2d6717425665628fe5e66434 100755 --- a/examples/tests/multiplextest.py +++ b/examples/tests/multiplextest.py @@ -22,7 +22,7 @@ class MultiplexTest(test.Test): 'ping_timeout': 10, 'ping_tries': 5} - def setup(self): + def setUp(self): self.compile_code() self.set_hugepages() self.set_numa_balance() @@ -57,7 +57,7 @@ class MultiplexTest(test.Test): if self.params.enable_msx_vectors == 'yes': self.log.info('Enabling msx vectors') - def action(self): + def runTest(self): self.log.info('Executing synctest...') self.log.info('synctest --timeout %s --tries %s', self.params.sync_timeout, diff --git a/examples/tests/passtest.py b/examples/tests/passtest.py index a1fd21b02f5ebb27609311c2b6ebd2ed2f0e7d25..ecdbed3df0657c94b8e600b40dd8819ba3298fd6 100755 --- a/examples/tests/passtest.py +++ b/examples/tests/passtest.py @@ -10,7 +10,7 @@ class PassTest(test.Test): Example test that passes. """ - def action(self): + def runTest(self): """ A test simply doesn't have to fail in order to pass """ diff --git a/examples/tests/raise.py b/examples/tests/raise.py index db6f6d8e809bfe93ef061a16724346245a63aefa..e99faf8bac434867f773ed782961be9faa8cdf79 100755 --- a/examples/tests/raise.py +++ b/examples/tests/raise.py @@ -18,7 +18,7 @@ class Raise(test.Test): default_params = {'source': 'raise.c', 'signal_number': 15} - def setup(self): + def setUp(self): """ Build 'raise'. """ @@ -30,7 +30,7 @@ class Raise(test.Test): env={'CFLAGS': '-g -O0'}, extra_args='raise') - def action(self): + def runTest(self): """ Execute 'raise'. """ diff --git a/examples/tests/skiptest.py b/examples/tests/skiptest.py index cc44921b25b910547f56d2c5f56bb3cb37c46163..c995553736a95b9151a4d3f0910a0031583a0fae 100755 --- a/examples/tests/skiptest.py +++ b/examples/tests/skiptest.py @@ -11,7 +11,7 @@ class SkipTest(test.Test): Functional test for avocado. Throw a TestNAError (skips the test). """ - def action(self): + def runTest(self): """ This should throw a TestNAError (skips the test). """ diff --git a/examples/tests/sleeptenmin.py b/examples/tests/sleeptenmin.py index 4954408a0cd2813849f8fcf67723870c73a251e4..0534e48a0fae116696dab9afa6e8c61c52745174 100755 --- a/examples/tests/sleeptenmin.py +++ b/examples/tests/sleeptenmin.py @@ -16,7 +16,7 @@ class SleepTenMin(test.Test): 'sleep_cycles': 1, 'sleep_method': 'builtin'} - def action(self): + def runTest(self): """ Sleep for length seconds. """ diff --git a/examples/tests/sleeptest.py b/examples/tests/sleeptest.py index 26547e53a51cc3bb79052699f11667c53de545e3..93c70e6facf6108f9ba1cb7c94fe7a844c22f79e 100755 --- a/examples/tests/sleeptest.py +++ b/examples/tests/sleeptest.py @@ -13,7 +13,7 @@ class SleepTest(test.Test): """ default_params = {'sleep_length': 1.0} - def action(self): + def runTest(self): """ Sleep for length seconds. """ diff --git a/examples/tests/synctest.py b/examples/tests/synctest.py index 7846cc1cc751e839e4e265ef28093899b4869f81..d6dc27052de62d1f78a345492daa5935067c8a15 100755 --- a/examples/tests/synctest.py +++ b/examples/tests/synctest.py @@ -19,7 +19,7 @@ class SyncTest(test.Test): 'sync_loop': 10, 'debug_symbols': True} - def setup(self): + def setUp(self): """ Build the synctest suite. """ @@ -34,7 +34,7 @@ class SyncTest(test.Test): else: build.make(self.srcdir) - def action(self): + def runTest(self): """ Execute synctest with the appropriate params. """ diff --git a/examples/tests/timeouttest.py b/examples/tests/timeouttest.py index 2b6df428777d7e8e96ecc7612e40ab90ebbdea3f..fef4eab577b42581b6b1e15b52eaed0bdca03d25 100755 --- a/examples/tests/timeouttest.py +++ b/examples/tests/timeouttest.py @@ -14,7 +14,7 @@ class TimeoutTest(test.Test): default_params = {'timeout': 3.0, 'sleep_time': 5.0} - def action(self): + def runTest(self): """ This should throw a TestTimeoutError. """ diff --git a/examples/tests/trinity.py b/examples/tests/trinity.py index 3c3079462a5675928118d9d25d4d664b6be4e700..4e9cd334f43d1fbd4d2300851696f019f8cdfc8a 100755 --- a/examples/tests/trinity.py +++ b/examples/tests/trinity.py @@ -27,7 +27,7 @@ class TrinityTest(test.Test): 'victims_path': None, 'stress': None} - def setup(self): + def setUp(self): """ Build trinity. """ @@ -39,7 +39,7 @@ class TrinityTest(test.Test): build.make(self.srcdir) self.victims_path = data_factory.make_dir_and_populate(self.workdir) - def action(self): + def runTest(self): """ Execute the trinity syscall fuzzer with the appropriate params. """ diff --git a/examples/tests/warntest.py b/examples/tests/warntest.py index 9d65e48818df95d0c0023b99b665f6adcfb230fe..b6ceb4c90570258c8d2aab7c4965e7d294395280 100755 --- a/examples/tests/warntest.py +++ b/examples/tests/warntest.py @@ -11,7 +11,7 @@ class WarnTest(test.Test): Functional test for avocado. Throw a TestWarn. """ - def action(self): + def runTest(self): """ This should throw a TestWarn. """ diff --git a/examples/tests/whiteboard.py b/examples/tests/whiteboard.py index 99fa07236b1ab1d0e0556b8f180926d16b7d80ac..26188a79154056e35bd661b43e8e9b01c0ada9f3 100755 --- a/examples/tests/whiteboard.py +++ b/examples/tests/whiteboard.py @@ -16,7 +16,7 @@ class WhiteBoard(test.Test): 'whiteboard_data_size': '10', 'whiteboard_writes': '1'} - def action(self): + def runTest(self): if self.params.whiteboard_data_file: self.log.info('Writing data to whiteboard from file: %s', self.params.whiteboard_data_file) diff --git a/selftests/all/functional/avocado/basic_tests.py b/selftests/all/functional/avocado/basic_tests.py index 6a36b53a7eeb3c4b770e71b6d7fe8e72fef90cc1..c6e755c2469db1a94ea60587bf47e5a89d72ad53 100644 --- a/selftests/all/functional/avocado/basic_tests.py +++ b/selftests/all/functional/avocado/basic_tests.py @@ -104,7 +104,7 @@ class RunnerOperationTest(unittest.TestCase): "Avocado crashed (rc %d):\n%s" % (unexpected_rc, result)) self.assertEqual(result.exit_status, expected_rc, "Avocado did not return rc %d:\n%s" % (expected_rc, result)) - self.assertIn("TestError: Failing during cleanup. Yay!", output, + self.assertIn("TestError: Failing during tearDown. Yay!", output, "Cleanup exception not printed to log output") self.assertIn("TestFail: This test is supposed to fail", output, diff --git a/selftests/all/functional/avocado/loader_tests.py b/selftests/all/functional/avocado/loader_tests.py index 0bdfad27eaf190e3e43d8ac0f96c34675f23abc9..999ced770e5be4b3014afc98a54f0df9eaa49151 100644 --- a/selftests/all/functional/avocado/loader_tests.py +++ b/selftests/all/functional/avocado/loader_tests.py @@ -20,7 +20,7 @@ from avocado import job from avocado import test class PassTest(test.Test): - def action(self): + def runTest(self): pass if __name__ == "__main__": @@ -33,7 +33,7 @@ from avocado import test import adsh class PassTest(test.Test): - def action(self): + def runTest(self): pass if __name__ == "__main__": diff --git a/selftests/all/unit/avocado/loader_unittest.py b/selftests/all/unit/avocado/loader_unittest.py old mode 100755 new mode 100644 index 36ada3e338d962cd5864165f12504f9bdfc3e9b9..a6b47cc21cad0de586b68831e8973bf5fdc9dbc4 --- a/selftests/all/unit/avocado/loader_unittest.py +++ b/selftests/all/unit/avocado/loader_unittest.py @@ -22,7 +22,7 @@ from avocado import job from avocado import test class PassTest(test.Test): - def action(self): + def runTest(self): pass if __name__ == "__main__": @@ -35,7 +35,7 @@ from avocado import test import adsh class PassTest(test.Test): - def action(self): + def runTest(self): pass if __name__ == "__main__": @@ -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,10 +99,10 @@ 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.action() + tc.runTest() simple_test.remove() def test_load_simple_not_exec(self): @@ -100,10 +111,10 @@ 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.action) + self.assertRaises(exceptions.NotATestError, tc.runTest) simple_test.remove() def test_load_pass(self): @@ -112,12 +123,12 @@ 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) == "", str(test_class)) self.assertTrue(issubclass(test_class, test.Test)) tc = test_class(**test_parameters) - tc.action() + tc.runTest() avocado_pass_test.remove() def test_load_inherited(self): @@ -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) == "", 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) == "", str(test_class)) avocado_base_test.remove() @@ -147,10 +158,10 @@ 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.action) + self.assertRaises(exceptions.TestFail, tc.runTest) avocado_buggy_test.remove() def test_load_buggy_not_exec(self): @@ -160,10 +171,10 @@ 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.action) + self.assertRaises(ImportError, tc.runTest) avocado_buggy_test.remove() def test_load_not_a_test(self): @@ -173,10 +184,10 @@ 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.action) + self.assertRaises(exceptions.NotATestError, tc.runTest) avocado_not_a_test.remove() def test_load_not_a_test_exec(self): @@ -184,12 +195,12 @@ 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 # (OSError: [Errno 8] Exec format error) - self.assertRaises(OSError, tc.action) + self.assertRaises(OSError, tc.runTest) avocado_not_a_test.remove() def test_py_simple_test(self): @@ -198,10 +209,10 @@ 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.action() + tc.runTest() avocado_simple_test.remove() def test_py_simple_test_notexec(self): @@ -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.action) + 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) diff --git a/selftests/all/unit/avocado/multiples_tests.py b/selftests/all/unit/avocado/multiples_tests.py new file mode 100644 index 0000000000000000000000000000000000000000..c9a333a9ba759d2add290882e6ab567a992dcc4a --- /dev/null +++ b/selftests/all/unit/avocado/multiples_tests.py @@ -0,0 +1,35 @@ +#!/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() diff --git a/selftests/all/unit/avocado/test_unittest.py b/selftests/all/unit/avocado/test_unittest.py index e450f214cb4bacb1086c6ee6284e0572776c0e9d..1df398ce10bf3cdc724abca488b71afe3ef5e875 100644 --- a/selftests/all/unit/avocado/test_unittest.py +++ b/selftests/all/unit/avocado/test_unittest.py @@ -21,17 +21,17 @@ from avocado.utils import script @unittest.skip("This class should not be tested per se") class AvocadoPass(test.Test): - def action(self): + def runTest(self): variable = True self.assertTrue(variable) self.whiteboard = 'foo' @unittest.skip("This class should not be tested per se") -class AvocadoFailNoAction(test.Test): +class EmptyTest(test.Test): """ - I don't have an action() method defined! + I don't have runTest() defined! """ pass @@ -51,19 +51,14 @@ class TestClassTest(unittest.TestCase): self.tst_instance_pass = AvocadoPass(base_logdir=self.base_logdir) self.tst_instance_pass.run_avocado() - def testFailNoActionRunTest(self): - tst_instance = AvocadoFailNoAction() - try: - tst_instance.action() - raise AssertionError("Test instance did not raise NotImplementedError") - except NotImplementedError: - pass - - def testFailNoActionRunAvocado(self): - tst_instance = AvocadoFailNoAction() - tst_instance.run_avocado() - self.assertEqual(tst_instance.status, 'FAIL') - self.assertEqual(tst_instance.fail_class, 'NotImplementedError') + def testRunTest(self): + tst = EmptyTest() + self.assertEqual(tst.runTest(), None) + + def testRunAvocado(self): + tst = EmptyTest() + tst.run_avocado() + self.assertEqual(tst.status, 'PASS') def testClassAttributesName(self): self.assertEqual(self.tst_instance_pass.name, 'AvocadoPass')