diff --git a/avocado/core/data_dir.py b/avocado/core/data_dir.py index 0aa4f2fbea6a897c6f7a6d83f5843d92000595cc..f0822df06e1f046c32e5012bcd0fb991df054fcf 100755 --- a/avocado/core/data_dir.py +++ b/avocado/core/data_dir.py @@ -210,6 +210,14 @@ class _TmpDirTracker(Borg): "you're trying to provide will have no effect.") return self.tmp_dir + def unittest_refresh_dir_tracker(self): + """ + This force-removes the tmpdir and refreshes the tracker to create new + """ + if not hasattr(self, "tmp_dir"): + return + shutil.rmtree(self.__dict__.pop("tmp_dir")) + def __del__(self): tmp_dir = getattr(self, 'tmp_dir', None) diff --git a/avocado/plugins/teststmpdir.py b/avocado/plugins/teststmpdir.py index 7626e40dd68ce4158b52acc6eaf1417294238a29..1f91fdcfceb4b28ddcdc48b8304f8f3d5ee7a457 100644 --- a/avocado/plugins/teststmpdir.py +++ b/avocado/plugins/teststmpdir.py @@ -45,7 +45,3 @@ class TestsTmpDir(JobPre, JobPost): del os.environ[self._varname] except: pass - - def __del__(self): - # Make sure we will cleanup if something bad happens - self.post(None) diff --git a/docs/source/ReferenceGuide.rst b/docs/source/ReferenceGuide.rst index f72caa4d72991b24e766fb733a611f82bc061fb0..374c8ebdc95038ec7b629fd1e0f720646a4a7548 100644 --- a/docs/source/ReferenceGuide.rst +++ b/docs/source/ReferenceGuide.rst @@ -363,8 +363,27 @@ The instances should have: .. [#f1] Avocado plugins can introduce additional test types. -Job Pre and Post Scripts -======================== +Pre and post tests plugins +========================== + +Avocado supports plug-ins which are (guaranteed to be) executed before the +first test and after all tests finished. The interfaces are +:class:`avocado.core.plugin_interfaces.JobPre`, resp. +:class:`avocado.core.plugin_interfaces.JobPost`. + +Note the ``pre_tests`` might not be executed due to earlier failure which +prevents the tests from being executed. + +The same applies for ``post_tests``, but it is possible to have ``post_tests`` +executed even when ``pre_tests`` were not. Additionally the ``post_tests`` +are (obviously) not executed on ``SIGKILL``. On the other hand they are +executed on ``SIGTERM`` and ``KeyboardInterrupt`` while running +the tests, but once the ``post_tests`` are executed the ``KeyboardInterrupt`` +or ``SystemExit`` interrupts their processing (to avoid hangs) and remaining +plug-ins will **NOT** be executed. + +Jobscripts plugin +----------------- Avocado ships with a plugin (installed by default) that allows running scripts before and after the actual execution of Jobs. A user can be @@ -373,7 +392,7 @@ been run, and when the "post" scripts are run, all the tests in a given job have already finished running. Configuration -------------- +^^^^^^^^^^^^^ By default, the script directory location is:: @@ -410,7 +429,7 @@ section: pre or post) exits with non-zero status Script Execution Environment ----------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ All scripts are run in separate process with some environment variables set. These can be used in your scripts in any way you wish: diff --git a/selftests/check_tmp_dirs b/selftests/check_tmp_dirs index 1816005225260270f4b412612ed9951fc2f4e2b9..8b16240bacc8c18d105e7250ff45add821d4c9b0 100755 --- a/selftests/check_tmp_dirs +++ b/selftests/check_tmp_dirs @@ -24,7 +24,7 @@ def check_tmp_dirs(): dir_to_check) except AssertionError: print('There are temporary avocado dirs lying around after test: %s', - avocado_tmp_dirs) + [os.path.join(dir_to_check, _) for _ in avocado_tmp_dirs]) fail = True if fail: sys.exit(1) diff --git a/selftests/functional/test_teststmpdir.py b/selftests/functional/test_teststmpdir.py index 4b2e90e6c3c58f42adf5bf420fb6c789b59cbfac..0aaf30fd23e1fc6d5aada3fcaf84690ec9dce818 100644 --- a/selftests/functional/test_teststmpdir.py +++ b/selftests/functional/test_teststmpdir.py @@ -94,6 +94,8 @@ class TestsTmpDirTests(unittest.TestCase): % (len(content), content)) def tearDown(self): + self.instrumented_test.remove() + self.simple_test.remove() shutil.rmtree(self.tmpdir) diff --git a/selftests/functional/test_unittest_compat.py b/selftests/functional/test_unittest_compat.py index a42a32d3647e9c365a87b9b6f5c142ca683b25e5..fac0bee8f40b67322d65b375d307d464f117f735 100644 --- a/selftests/functional/test_unittest_compat.py +++ b/selftests/functional/test_unittest_compat.py @@ -110,6 +110,9 @@ class UnittestCompat(unittest.TestCase): self.assertIn('FAILED (errors=1)', result.stderr) def tearDown(self): + self.unittest_script_error.remove() + self.unittest_script_fail.remove() + self.unittest_script_good.remove() shutil.rmtree(self.tmpdir) diff --git a/selftests/run b/selftests/run index 7bd62373ce857bc400a868fb7b5202c394b5559d..aebb0547fc1ba1b7db5d2daaa6079be9cc1e27e4 100755 --- a/selftests/run +++ b/selftests/run @@ -8,7 +8,12 @@ import sys import logging import unittest +from avocado.core import data_dir + + logger = logging.getLogger(__name__) +CHECK_TMP_DIRS = os.path.abspath(os.path.join(os.path.dirname(__file__), + "check_tmp_dirs")) def test_suite(): @@ -22,8 +27,17 @@ def test_suite(): return suite +class MyResult(unittest.TextTestResult): + def startTest(self, test): + # Destroy the data_dir.get_tmpdir + data_dir._tmp_tracker.unittest_refresh_dir_tracker() + assert os.system(CHECK_TMP_DIRS) == 0, "Previous test left some dirs behind" + return super(MyResult, self).startTest(test) + + if __name__ == '__main__': - runner = unittest.TextTestRunner(failfast=not os.environ.get("SELF_CHECK_CONTINUOUS")) + runner = unittest.TextTestRunner(failfast=not os.environ.get("SELF_CHECK_CONTINUOUS"), + verbosity=2, resultclass=MyResult) result = runner.run(test_suite()) if result.failures or result.errors: sys.exit(1) diff --git a/selftests/unit/test_job.py b/selftests/unit/test_job.py index bd6d22f3cf4b2b670c4cc8302f1f3035127d684a..ed0263f2039eb0b75bde6ce0e6b2603446b8ffa6 100644 --- a/selftests/unit/test_job.py +++ b/selftests/unit/test_job.py @@ -70,7 +70,10 @@ class JobTest(unittest.TestCase): logdir=self.tmpdir) myjob = JobFilterTime(args) myjob.create_test_suite() - myjob.pre_tests() + try: + myjob.pre_tests() + finally: + myjob.post_tests() self.assertLessEqual(len(myjob.test_suite), 1) def test_job_run_tests(self): @@ -93,9 +96,11 @@ class JobTest(unittest.TestCase): logdir=self.tmpdir) myjob = JobLogPost(args) myjob.create_test_suite() - myjob.pre_tests() - myjob.run_tests() - myjob.post_tests() + try: + myjob.pre_tests() + myjob.run_tests() + finally: + myjob.post_tests() self.assertEqual(myjob.unique_id[::-1], open(os.path.join(myjob.logdir, "reversed_id")).read())