From ba8184dd650a624014a63591596f39d4ab4faca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Tue, 23 May 2023 17:39:07 +0200 Subject: [PATCH] [test][NFC] Change from nose to pytest (analyzer library) -> Motivation, why pytest Nose is no longer supported, it is not compatible with python3.9, and will never be: https://github.com/nose-devs/nose/issues/1099#issuecomment-562394879 As python3.10 is the oldest python version available from Ubuntu22.04's package manager by default, it is time to migrate. We never really relied on many nose features (as far as I can tell, we never actually import anything from the nose package), this change isn't particularly painful (don't let the size of the change fool you, its pretty much just moving code around!). Pytest seems to be the industry standard framework lately, and supports most nose constructs out of the box. The aim of this change that from the make target side, nothing changed -- you still analyzer tests with 'make analyzer', a specific test file with (having 'functional/skip' as the example): 'TEST=tests/functional/skip make test_analyzer_feature' This is basically how granular nose could get. If you wanted to run a specific test case in a test file, you couldn't do that, but you can with pytest: pytest analyzer/tests/functional/skip -v -k test_analyze_header_with_file_option Mind that there are many environmental variables that needs to be set in addition to the above command, so we need to write new make targets to make this user-friendly, but nevertheless, it is possible. -> What changed Broadly speaking, the change can be divided into 4 parts: 1. Replacing nose with pytest in the makefiles 2. Replacing nose config files with pytest files 3. Replace `setup_package`/`teardown_package` with `setup_class`/`teardown_class`, and `setup`/`teardown` to `setup_method` and `teardown_method`. 4. Fix up individual test environments under `analyzer/tools`. For the Makefile and config changes, I hope they are self explanatory. Pytest is a rather painless drop-in replacement on the invocation side. On the conversion, there is a page that discusses how one can convert nose to pytest: https://docs.pytest.org/en/7.1.x/how-to/nose.html It is stated (and is true) that pytest supports most, but not quite all features in nose. `{setup, teardown}_package` is not supported, but it turns out that we dedicate a package to every test class, so simply switching to `{setup, teardown}_class` was sufficient. That accounts for the vast majority of the code change. That is the only meaningful structural change -- `setup`->`setup_method` and the teardown variant was really just a simple rename. At last, you can notice that some `__init__.py` files are copied over from `analyzer/test/__init__.py`. Frankly, I'm not sure how the tests worked previously without these files setting up these variables properly, but this skeleton fell out of the closet now. --- analyzer/.noserc | 13 -- analyzer/pytest.ini | 13 ++ analyzer/requirements_py/dev/requirements.txt | 2 +- analyzer/tests/Makefile | 14 +-- analyzer/tests/functional/analyze/__init__.py | 37 +----- .../tests/functional/analyze/test_analyze.py | 29 +++-- .../functional/analyze_and_parse/__init__.py | 31 +---- .../test_analyze_and_parse.py | 16 ++- analyzer/tests/functional/cmdline/__init__.py | 34 +---- .../tests/functional/cmdline/test_cmdline.py | 21 +++- analyzer/tests/functional/config/__init__.py | 34 +---- .../tests/functional/config/test_config.py | 21 +++- analyzer/tests/functional/ctu/__init__.py | 33 +---- analyzer/tests/functional/ctu/test_ctu.py | 29 ++++- .../tests/functional/ctu_failure/__init__.py | 33 +---- .../ctu_failure/test_ctu_failure.py | 23 +++- analyzer/tests/functional/fixit/__init__.py | 37 +----- analyzer/tests/functional/fixit/test_fixit.py | 25 +++- .../tests/functional/host_check/__init__.py | 9 +- analyzer/tests/functional/skip/__init__.py | 37 +----- analyzer/tests/functional/skip/test_skip.py | 24 +++- .../tests/functional/suppress/__init__.py | 119 +----------------- .../functional/suppress/test_suppress.py | 108 +++++++++++++++- analyzer/tests/functional/z3/__init__.py | 83 +----------- analyzer/tests/functional/z3/test_z3.py | 70 ++++++++++- analyzer/tests/unit/__init__.py | 1 + analyzer/tests/unit/test_buildcmd_escaping.py | 2 +- analyzer/tests/unit/test_result_handler.py | 2 +- analyzer/tools/build-logger/.noserc | 13 -- analyzer/tools/build-logger/pytest.ini | 13 ++ .../requirements_py/dev/requirements.txt | 4 +- analyzer/tools/build-logger/tests/Makefile | 6 +- .../tools/merge_clang_extdef_mappings/.noserc | 13 -- .../merge_clang_extdef_mappings/pytest.ini | 13 ++ .../requirements_py/dev/requirements.txt | 2 +- .../tests/Makefile | 6 +- .../tests/unit/__init__.py | 14 +++ .../merge_clang_extdef_mappings/__init__.py | 47 +------ ...py => test_merge_clang_extdef_mappings.py} | 43 ++++++- analyzer/tools/statistics_collector/.noserc | 13 -- .../tools/statistics_collector/pytest.ini | 13 ++ .../requirements_py/dev/requirements.txt | 2 +- .../tools/statistics_collector/tests/Makefile | 6 +- .../tests/unit/__init__.py | 14 +++ 44 files changed, 509 insertions(+), 613 deletions(-) delete mode 100644 analyzer/.noserc create mode 100644 analyzer/pytest.ini delete mode 100644 analyzer/tools/build-logger/.noserc create mode 100644 analyzer/tools/build-logger/pytest.ini delete mode 100644 analyzer/tools/merge_clang_extdef_mappings/.noserc create mode 100644 analyzer/tools/merge_clang_extdef_mappings/pytest.ini rename analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/{merge_clang_extdef_mappings.py => test_merge_clang_extdef_mappings.py} (66%) delete mode 100644 analyzer/tools/statistics_collector/.noserc create mode 100644 analyzer/tools/statistics_collector/pytest.ini diff --git a/analyzer/.noserc b/analyzer/.noserc deleted file mode 100644 index 4f6b377e17..0000000000 --- a/analyzer/.noserc +++ /dev/null @@ -1,13 +0,0 @@ -[nosetests] - -# increase verbosity level -verbosity=3 - -# more detailed error messages on failed asserts -detailed-errors=1 - -# stop running tests on first error -stop=1 - -# do not capture stdout -nocapture=1 diff --git a/analyzer/pytest.ini b/analyzer/pytest.ini new file mode 100644 index 0000000000..7ee6b8962d --- /dev/null +++ b/analyzer/pytest.ini @@ -0,0 +1,13 @@ +[pytest] + +addopts = +# increase verbosity level + --verbose + +# stop running tests on first error +# FIXME: Pretty please comment this horrible setting out, I hate it with a +# passion +# --maxfail=1 + +# do not capture stdout + --capture=sys diff --git a/analyzer/requirements_py/dev/requirements.txt b/analyzer/requirements_py/dev/requirements.txt index 15b7b9a815..7e69c431d9 100644 --- a/analyzer/requirements_py/dev/requirements.txt +++ b/analyzer/requirements_py/dev/requirements.txt @@ -1,5 +1,5 @@ lxml==4.9.2 -nose==1.3.7 +pytest==7.3.1 pycodestyle==2.7.0 psutil==5.8.0 portalocker==2.2.1 diff --git a/analyzer/tests/Makefile b/analyzer/tests/Makefile index 21ed55ef5a..24200461e3 100644 --- a/analyzer/tests/Makefile +++ b/analyzer/tests/Makefile @@ -6,8 +6,8 @@ PYTHON_BIN ?= python3 REPO_ROOT ?= REPO_ROOT=$(ROOT) -# Nose test runner configuration options. -NOSECFG = --config .noserc +# pytest test runner configuration options. +PYTESTCFG = -c pytest.ini test_in_env: pycodestyle_in_env pylint_in_env test_unit_in_env test_functional_in_env test_build_logger test_tu_collector_in_env @@ -33,14 +33,14 @@ pylint_in_env: venv_dev run_test: $(REPO_ROOT) $(TEST_PROJECT) \ - nosetests $(NOSECFG) ${TEST} || exit 1 + pytest $(PYTESTCFG) ${TEST} || exit 1 run_test_in_env: venv_dev $(ACTIVATE_DEV_VENV) && $(REPO_ROOT) $(TEST_PROJECT) \ - nosetests $(NOSECFG) ${TEST} || exit 1 + pytest $(PYTESTCFG) ${TEST} || exit 1 -UNIT_TEST_CMD = $(REPO_ROOT) nosetests $(NOSECFG) tests/unit -UNIT_TEST_COV_CMD = $(REPO_ROOT) coverage run -m nose $(NOSECFG) tests/unit && coverage report && coverage html +UNIT_TEST_CMD = $(REPO_ROOT) pytest $(PYTESTCFG) tests/unit +UNIT_TEST_COV_CMD = $(REPO_ROOT) coverage run -m pytest $(PYTESTCFG) tests/unit && coverage report && coverage html test_unit: $(UNIT_TEST_CMD) @@ -55,7 +55,7 @@ test_unit_cov_in_env: venv_dev $(ACTIVATE_DEV_VENV) && $(UNIT_TEST_COV_CMD) FUNCTIONAL_TEST_CMD = $(REPO_ROOT) $(TEST_PROJECT) \ - nosetests $(NOSECFG) tests/functional || exit 1 + pytest $(PYTESTCFG) tests/functional || exit 1 test_functional: ${PYTHON_BIN} $(ROOT)/scripts/test/check_clang.py || exit 1; diff --git a/analyzer/tests/functional/analyze/__init__.py b/analyzer/tests/functional/analyze/__init__.py index c33e08c325..0b0114f7e4 100644 --- a/analyzer/tests/functional/analyze/__init__.py +++ b/analyzer/tests/functional/analyze/__init__.py @@ -7,38 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the test package analyze. -""" - - -import os -import shutil - -from libtest import env - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('analyze') - - report_dir = os.path.join(TEST_WORKSPACE, 'reports') - os.makedirs(report_dir) - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete the workspace associated with this test""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/analyze/test_analyze.py b/analyzer/tests/functional/analyze/test_analyze.py index c2431d8903..0f19ac8659 100644 --- a/analyzer/tests/functional/analyze/test_analyze.py +++ b/analyzer/tests/functional/analyze/test_analyze.py @@ -29,9 +29,26 @@ class TestAnalyze(unittest.TestCase): _ccClient = None - def setUp(self): + def setup_class(self): + """Setup the environment for the tests.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('analyze') + + report_dir = os.path.join(TEST_WORKSPACE, 'reports') + os.makedirs(report_dir) + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete the workspace associated with this test""" + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): + """Setup the environment for the tests.""" - # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] test_class = self.__class__.__name__ @@ -51,7 +68,7 @@ def setUp(self): self.disabling_modeling_checker_regex = re.compile( r"analyzer-disable-checker=.*unix.cstring.CStringModeling.*") - def tearDown(self): + def teardown_method(self, method): """Restore environment after tests have ran.""" os.chdir(self.__old_pwd) if os.path.isdir(self.report_dir): @@ -1105,11 +1122,9 @@ def test_analyzer_and_checker_config(self): # It's printed as a found report and in the checker statistics. # Note: If this test case fails, its pretty sure that something totally - # unrelated to the analysis broke in CodeChecker. Comment out the line - # starting with 'nocapture' in 'analyzer/.noserc', and print both the + # unrelated to the analysis broke in CodeChecker. Print both the # stdout and stderr streams from the above communicate() call (the - # latter of which is ignored with _ above) - # Put a + if the above instructions saved you: + + # latter of which is ignored with _ above). self.assertEqual(out.count('hicpp-use-nullptr'), 2) analyze_cmd = [self._codechecker_cmd, "check", "-l", build_json, diff --git a/analyzer/tests/functional/analyze_and_parse/__init__.py b/analyzer/tests/functional/analyze_and_parse/__init__.py index 5931487568..0b0114f7e4 100644 --- a/analyzer/tests/functional/analyze_and_parse/__init__.py +++ b/analyzer/tests/functional/analyze_and_parse/__init__.py @@ -7,32 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the test package 'analyze' and 'parse'.""" - - -import os -import shutil - -from libtest import env - -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('analyze_and_parse') - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete the workspace associated with this test""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py b/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py index e8a06efa5d..3ad7890b2b 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py +++ b/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py @@ -30,6 +30,7 @@ class AnalyzeParseTestCaseMeta(type): + def __new__(mcs, name, bases, test_dict): def gen_test(path, mode): @@ -64,7 +65,11 @@ class AnalyzeParseTestCase( def setup_class(cls): """Setup the class.""" - # TEST_WORKSPACE is automatically set by test package __init__.py + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('analyze_and_parse') + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + test_workspace = os.environ['TEST_WORKSPACE'] cls.test_workspaces = {'NORMAL': os.path.join(test_workspace, 'NORMAL'), @@ -108,7 +113,14 @@ def teardown_class(cls): """Restore environment after tests have ran.""" os.chdir(cls.__old_pwd) - def tearDown(self): + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def teardown_method(self, method): """Restore environment after a particular test has run.""" output_dir = AnalyzeParseTestCase.test_workspaces['OUTPUT'] if os.path.isdir(output_dir): diff --git a/analyzer/tests/functional/cmdline/__init__.py b/analyzer/tests/functional/cmdline/__init__.py index 4d7ca0c381..0b0114f7e4 100644 --- a/analyzer/tests/functional/cmdline/__init__.py +++ b/analyzer/tests/functional/cmdline/__init__.py @@ -7,35 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the test package analyze. -""" - - -import os -import shutil - -from libtest import env - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('cmdline') - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete the workspace associated with this test""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/cmdline/test_cmdline.py b/analyzer/tests/functional/cmdline/test_cmdline.py index ad944835a3..a3408dd131 100644 --- a/analyzer/tests/functional/cmdline/test_cmdline.py +++ b/analyzer/tests/functional/cmdline/test_cmdline.py @@ -12,6 +12,7 @@ import json import os +import shutil import subprocess import unittest @@ -38,7 +39,25 @@ class TestCmdline(unittest.TestCase): Simple tests to check CodeChecker command line. """ - def setUp(self): + def setup_class(self): + """Setup the environment for the tests.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('cmdline') + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete the workspace associated with this test""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] diff --git a/analyzer/tests/functional/config/__init__.py b/analyzer/tests/functional/config/__init__.py index 365c4c6ffc..0b0114f7e4 100644 --- a/analyzer/tests/functional/config/__init__.py +++ b/analyzer/tests/functional/config/__init__.py @@ -7,35 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the config test for the analyze command. -""" - - -import os -import shutil - -from libtest import env - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('config') - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete the workspace associated with this test""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/config/test_config.py b/analyzer/tests/functional/config/test_config.py index b353f6536c..9bd9feac35 100644 --- a/analyzer/tests/functional/config/test_config.py +++ b/analyzer/tests/functional/config/test_config.py @@ -14,6 +14,7 @@ import json import os +import shutil import subprocess import unittest @@ -23,7 +24,25 @@ class TestConfig(unittest.TestCase): _ccClient = None - def setUp(self): + def setup_class(self): + """Setup the environment for the tests.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('config') + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete the workspace associated with this test""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] diff --git a/analyzer/tests/functional/ctu/__init__.py b/analyzer/tests/functional/ctu/__init__.py index 01ffe6dbef..0b0114f7e4 100644 --- a/analyzer/tests/functional/ctu/__init__.py +++ b/analyzer/tests/functional/ctu/__init__.py @@ -7,34 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the test package ctu.""" - - -import os -import shutil - -from libtest import env - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for testing ctu.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('ctu') - - # Set the TEST_WORKSPACE used by the tests. - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete workspace.""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print('Removing: ' + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/ctu/test_ctu.py b/analyzer/tests/functional/ctu/test_ctu.py index 89c6eef24e..cfd2d44479 100644 --- a/analyzer/tests/functional/ctu/test_ctu.py +++ b/analyzer/tests/functional/ctu/test_ctu.py @@ -35,14 +35,33 @@ class TestCtu(unittest.TestCase): """ Test CTU functionality. """ - def setUp(self): + def setup_class(self): + """Setup the environment for testing ctu.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('ctu') + + # Set the TEST_WORKSPACE used by the tests. + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete workspace.""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print('Removing: ' + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): """ Set up workspace.""" self.setUpWith('test_files_c', 'buildlog.json', 'reports_c') def setUpWith(self, input_dir, buildlog_json, report_dir): """ Set up workspace with a given parameters. If called multiple times, - tearDown() must be called before this function. + teardown_method() must be called before this function. """ # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] @@ -78,7 +97,7 @@ def setUpWith(self, input_dir, buildlog_json, report_dir): self.__old_pwd = os.getcwd() os.chdir(self.test_workspace) - def tearDown(self): + def teardown_method(self, method): """ Tear down workspace.""" shutil.rmtree(self.report_dir, ignore_errors=True) @@ -201,7 +220,7 @@ def __test_ctu_analyze(self, on_demand=False): def __test_ctu_analyze_cpp(self, on_demand=False): """ Test CTU analyze phase. """ - self.tearDown() + self.teardown_method(self.__test_ctu_analyze_cpp) self.setUpWith('test_files_cpp', 'buildlog.json', 'reports_cpp') self.__do_ctu_collect(on_demand=on_demand) @@ -366,7 +385,7 @@ def test_ctu_ondemand_yaml_format(self): The YAML file should not contain newlines in individual entries in the generated textual format. """ - self.tearDown() + self.teardown_method(self.test_ctu_ondemand_yaml_format) self.setUpWith('test_files_c', 'complex_buildlog.json', 'reports_c') # Copy test files to a directory which file path will be longer than diff --git a/analyzer/tests/functional/ctu_failure/__init__.py b/analyzer/tests/functional/ctu_failure/__init__.py index b3c1c4bf36..0b0114f7e4 100644 --- a/analyzer/tests/functional/ctu_failure/__init__.py +++ b/analyzer/tests/functional/ctu_failure/__init__.py @@ -7,34 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the test package ctu.""" - - -import os -import shutil - -from libtest import env - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for testing ctu.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('ctu_failure') - - # Set the TEST_WORKSPACE used by the tests. - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete workspace.""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print('Removing: ' + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/ctu_failure/test_ctu_failure.py b/analyzer/tests/functional/ctu_failure/test_ctu_failure.py index 542ca2785d..98a5a13a35 100644 --- a/analyzer/tests/functional/ctu_failure/test_ctu_failure.py +++ b/analyzer/tests/functional/ctu_failure/test_ctu_failure.py @@ -36,7 +36,26 @@ class TestCtuFailure(unittest.TestCase): """ Test CTU functionality. """ - def setUp(self): + def setup_class(self): + """Setup the environment for testing ctu.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('ctu_failure') + + # Set the TEST_WORKSPACE used by the tests. + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete workspace.""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print('Removing: ' + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): """ Set up workspace.""" # TEST_WORKSPACE is automatically set by test package __init__.py . @@ -91,7 +110,7 @@ def __set_up_test_dir(self, project_path): encoding="utf-8", errors="ignore") as log_file: json.dump(build_json, log_file) - def tearDown(self): + def teardown_method(self, method): """ Tear down workspace.""" shutil.rmtree(self.report_dir, ignore_errors=True) diff --git a/analyzer/tests/functional/fixit/__init__.py b/analyzer/tests/functional/fixit/__init__.py index 93c2d9edbc..0b0114f7e4 100644 --- a/analyzer/tests/functional/fixit/__init__.py +++ b/analyzer/tests/functional/fixit/__init__.py @@ -7,38 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the test package fixit. -""" - - -import os -import shutil - -from libtest import env - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('fixit') - - report_dir = os.path.join(TEST_WORKSPACE, 'reports') - os.makedirs(report_dir) - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete the workspace associated with this test""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/fixit/test_fixit.py b/analyzer/tests/functional/fixit/test_fixit.py index 8e71951ed7..b98e0ff2c9 100644 --- a/analyzer/tests/functional/fixit/test_fixit.py +++ b/analyzer/tests/functional/fixit/test_fixit.py @@ -29,7 +29,28 @@ class TestFixit(unittest.TestCase): _ccClient = None - def setUp(self): + def setup_class(self): + """Setup the environment for the tests.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('fixit') + + report_dir = os.path.join(TEST_WORKSPACE, 'reports') + os.makedirs(report_dir) + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete the workspace associated with this test""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] @@ -43,7 +64,7 @@ def setUp(self): # Change working dir to testfile dir so CodeChecker can be run easily. self.__old_pwd = os.getcwd() - def tearDown(self): + def teardown_method(self, method): """Restore environment after tests have run.""" os.chdir(self.__old_pwd) if os.path.isdir(self.report_dir): diff --git a/analyzer/tests/functional/host_check/__init__.py b/analyzer/tests/functional/host_check/__init__.py index c24b816e8b..0b0114f7e4 100644 --- a/analyzer/tests/functional/host_check/__init__.py +++ b/analyzer/tests/functional/host_check/__init__.py @@ -7,10 +7,5 @@ # # ------------------------------------------------------------------------- - -def setup_package(): - pass - - -def teardown_package(): - pass +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/skip/__init__.py b/analyzer/tests/functional/skip/__init__.py index 074d4e00af..0b0114f7e4 100644 --- a/analyzer/tests/functional/skip/__init__.py +++ b/analyzer/tests/functional/skip/__init__.py @@ -7,38 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the skip test for the analyze command. -""" - - -import os -import shutil - -from libtest import env - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('skip') - - report_dir = os.path.join(TEST_WORKSPACE, 'reports') - os.makedirs(report_dir) - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """Delete the workspace associated with this test""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/skip/test_skip.py b/analyzer/tests/functional/skip/test_skip.py index 7f41848ce5..48dc777cd6 100644 --- a/analyzer/tests/functional/skip/test_skip.py +++ b/analyzer/tests/functional/skip/test_skip.py @@ -17,6 +17,7 @@ import os import plistlib import shlex +import shutil import subprocess import tempfile import unittest @@ -27,7 +28,28 @@ class TestSkip(unittest.TestCase): _ccClient = None - def setUp(self): + def setup_class(self): + """Setup the environment for the tests.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('skip') + + report_dir = os.path.join(TEST_WORKSPACE, 'reports') + os.makedirs(report_dir) + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """Delete the workspace associated with this test""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): # TEST_WORKSPACE is automatically set by test package __init__.py . self.test_workspace = os.environ['TEST_WORKSPACE'] diff --git a/analyzer/tests/functional/suppress/__init__.py b/analyzer/tests/functional/suppress/__init__.py index 0d8e496291..0b0114f7e4 100644 --- a/analyzer/tests/functional/suppress/__init__.py +++ b/analyzer/tests/functional/suppress/__init__.py @@ -7,120 +7,5 @@ # # ------------------------------------------------------------------------- -"""Setup for the package tests.""" - - -import os -import shutil -import sys - -from libtest import codechecker -from libtest import env -from libtest import project - -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for the tests.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('suppress') - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - test_project = 'suppress' - - test_config = {} - - project_info = project.get_info(test_project) - - test_proj_path = os.path.join(TEST_WORKSPACE, "test_proj") - shutil.copytree(project.path(test_project), test_proj_path) - - project_info['project_path'] = test_proj_path - - test_config['test_project'] = project_info - - # Generate a suppress file for the tests. - suppress_file = os.path.join(TEST_WORKSPACE, 'suppress_file') - if os.path.isfile(suppress_file): - os.remove(suppress_file) - _generate_suppress_file(suppress_file) - - test_env = env.test_env(TEST_WORKSPACE) - - codechecker_cfg = { - 'suppress_file': None, - 'skip_list_file': None, - 'check_env': test_env, - 'workspace': TEST_WORKSPACE, - 'checkers': [] - } - - ret = project.clean(test_project, test_env) - if ret: - sys.exit(ret) - - output_dir = codechecker_cfg['reportdir'] \ - if 'reportdir' in codechecker_cfg \ - else os.path.join(codechecker_cfg['workspace'], 'reports') - - codechecker_cfg['reportdir'] = output_dir - - ret = codechecker.log_and_analyze(codechecker_cfg, - project.path(test_project)) - - if ret: - sys.exit(1) - print("Analyzing the test project was successful.") - - test_config['codechecker_cfg'] = codechecker_cfg - - env.export_test_cfg(TEST_WORKSPACE, test_config) - - -def teardown_package(): - """Clean up after the test.""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) - - -def _generate_suppress_file(suppress_file): - """ - Create a dummy suppress file just to check if the old and the new - suppress format can be processed. - """ - print("Generating suppress file: " + suppress_file) - - import calendar - import hashlib - import random - import time - - hash_version = '1' - suppress_stuff = [] - for _ in range(10): - curr_time = calendar.timegm(time.gmtime()) - random_integer = random.randint(1, 9999999) - suppress_line = str(curr_time) + str(random_integer) - suppress_stuff.append( - hashlib.md5(suppress_line.encode("utf-8")).hexdigest() + - '#' + hash_version) - - s_file = open(suppress_file, 'w', encoding='utf-8', errors='ignore') - for k in suppress_stuff: - s_file.write(k + '||' + 'idziei éléáálk ~!@#$#%^&*() \n') - s_file.write( - k + '||' + 'test_~!@#$%^&*.cpp' + - '||' + 'idziei éléáálk ~!@#$%^&*(\n') - s_file.write( - hashlib.md5(suppress_line.encode("utf-8")).hexdigest() + '||' + - 'test_~!@#$%^&*.cpp' + '||' + 'idziei éléáálk ~!@#$%^&*(\n') - - s_file.close() +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/suppress/test_suppress.py b/analyzer/tests/functional/suppress/test_suppress.py index 0cf04c889d..b227c8d8b2 100644 --- a/analyzer/tests/functional/suppress/test_suppress.py +++ b/analyzer/tests/functional/suppress/test_suppress.py @@ -12,17 +12,121 @@ import os import inspect +import shutil +import sys import unittest -from libtest import env, codechecker +from libtest import env, codechecker, project + + +def _generate_suppress_file(suppress_file): + """ + Create a dummy suppress file just to check if the old and the new + suppress format can be processed. + """ + print("Generating suppress file: " + suppress_file) + + import calendar + import hashlib + import random + import time + + hash_version = '1' + suppress_stuff = [] + for _ in range(10): + curr_time = calendar.timegm(time.gmtime()) + random_integer = random.randint(1, 9999999) + suppress_line = str(curr_time) + str(random_integer) + suppress_stuff.append( + hashlib.md5(suppress_line.encode("utf-8")).hexdigest() + + '#' + hash_version) + + s_file = open(suppress_file, 'w', encoding='utf-8', errors='ignore') + for k in suppress_stuff: + s_file.write(k + '||' + 'idziei éléáálk ~!@#$#%^&*() \n') + s_file.write( + k + '||' + 'test_~!@#$%^&*.cpp' + + '||' + 'idziei éléáálk ~!@#$%^&*(\n') + s_file.write( + hashlib.md5(suppress_line.encode("utf-8")).hexdigest() + '||' + + 'test_~!@#$%^&*.cpp' + '||' + 'idziei éléáálk ~!@#$%^&*(\n') + + s_file.close() class TestSuppress(unittest.TestCase): """ Test source-code level suppression data writing to suppress file. """ + def setup_class(self): + """Setup the environment for the tests.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('suppress') + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + test_project = 'suppress' + + test_config = {} + + project_info = project.get_info(test_project) + + test_proj_path = os.path.join(TEST_WORKSPACE, "test_proj") + shutil.copytree(project.path(test_project), test_proj_path) + + project_info['project_path'] = test_proj_path + + test_config['test_project'] = project_info + + # Generate a suppress file for the tests. + suppress_file = os.path.join(TEST_WORKSPACE, 'suppress_file') + if os.path.isfile(suppress_file): + os.remove(suppress_file) + _generate_suppress_file(suppress_file) + + test_env = env.test_env(TEST_WORKSPACE) + + codechecker_cfg = { + 'suppress_file': None, + 'skip_list_file': None, + 'check_env': test_env, + 'workspace': TEST_WORKSPACE, + 'checkers': [] + } + + ret = project.clean(test_project, test_env) + if ret: + sys.exit(ret) + + output_dir = codechecker_cfg['reportdir'] \ + if 'reportdir' in codechecker_cfg \ + else os.path.join(codechecker_cfg['workspace'], 'reports') + + codechecker_cfg['reportdir'] = output_dir + + ret = codechecker.log_and_analyze(codechecker_cfg, + project.path(test_project)) + + if ret: + sys.exit(1) + print("Analyzing the test project was successful.") + + test_config['codechecker_cfg'] = codechecker_cfg + + env.export_test_cfg(TEST_WORKSPACE, test_config) + + def teardown_class(self): + """Clean up after the test.""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) - def setUp(self): + def setup_method(self, method): self._test_workspace = os.environ['TEST_WORKSPACE'] self._testproject_data = env.setup_test_proj_cfg(self._test_workspace) diff --git a/analyzer/tests/functional/z3/__init__.py b/analyzer/tests/functional/z3/__init__.py index 550340a2ec..0b0114f7e4 100644 --- a/analyzer/tests/functional/z3/__init__.py +++ b/analyzer/tests/functional/z3/__init__.py @@ -7,84 +7,5 @@ # # ------------------------------------------------------------------------- -""" Setup for the test package z3 capability. """ - - -import os -import shutil -import sys -import uuid - -from libtest import codechecker -from libtest import env -from libtest import project - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """Setup the environment for testing z3.""" - - global TEST_WORKSPACE - TEST_WORKSPACE = env.get_workspace('z3') - - # Set the TEST_WORKSPACE used by the tests. - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - test_config = {} - - test_project = 'suppress' - - project_info = project.get_info(test_project) - - # Copy the test project to the workspace. The tests should - # work only on this test project. - test_proj_path = os.path.join(TEST_WORKSPACE, "test_proj") - shutil.copytree(project.path(test_project), test_proj_path) - - project_info['project_path'] = test_proj_path - - test_config['test_project'] = project_info - - # Suppress file should be set here if needed by the tests. - suppress_file = None - - # Skip list file should be set here if needed by the tests. - skip_list_file = None - - # Get an environment which should be used by the tests. - test_env = env.test_env(TEST_WORKSPACE) - - # Create a basic CodeChecker config for the tests, this should - # be imported by the tests and they should only depend on these - # configuration options. - codechecker_cfg = { - 'suppress_file': suppress_file, - 'skip_list_file': skip_list_file, - 'check_env': test_env, - 'workspace': TEST_WORKSPACE, - 'checkers': [] - } - - # Clean the test project, if needed by the tests. - ret = project.clean(test_project) - if ret: - sys.exit(ret) - - test_config['codechecker_cfg'] = codechecker_cfg - - # Export the test configuration to the workspace. - env.export_test_cfg(TEST_WORKSPACE, test_config) - - -def teardown_package(): - """Clean up after the test.""" - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE, ignore_errors=True) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tests/functional/z3/test_z3.py b/analyzer/tests/functional/z3/test_z3.py index 53c05f8dc3..75e0c0ffcb 100644 --- a/analyzer/tests/functional/z3/test_z3.py +++ b/analyzer/tests/functional/z3/test_z3.py @@ -12,10 +12,12 @@ from distutils import util import os +import shutil import unittest import shlex +import sys -from libtest import env +from libtest import env, project from libtest.codechecker import call_command NO_Z3_MESSAGE = "Z3 is not supported" @@ -25,7 +27,71 @@ class TestSkeleton(unittest.TestCase): _ccClient = None - def setUp(self): + def setup_class(self): + """Setup the environment for testing z3.""" + + global TEST_WORKSPACE + TEST_WORKSPACE = env.get_workspace('z3') + + # Set the TEST_WORKSPACE used by the tests. + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + test_config = {} + + test_project = 'suppress' + + project_info = project.get_info(test_project) + + # Copy the test project to the workspace. The tests should + # work only on this test project. + test_proj_path = os.path.join(TEST_WORKSPACE, "test_proj") + shutil.copytree(project.path(test_project), test_proj_path) + + project_info['project_path'] = test_proj_path + + test_config['test_project'] = project_info + + # Suppress file should be set here if needed by the tests. + suppress_file = None + + # Skip list file should be set here if needed by the tests. + skip_list_file = None + + # Get an environment which should be used by the tests. + test_env = env.test_env(TEST_WORKSPACE) + + # Create a basic CodeChecker config for the tests, this should + # be imported by the tests and they should only depend on these + # configuration options. + codechecker_cfg = { + 'suppress_file': suppress_file, + 'skip_list_file': skip_list_file, + 'check_env': test_env, + 'workspace': TEST_WORKSPACE, + 'checkers': [] + } + + # Clean the test project, if needed by the tests. + ret = project.clean(test_project) + if ret: + sys.exit(ret) + + test_config['codechecker_cfg'] = codechecker_cfg + + # Export the test configuration to the workspace. + env.export_test_cfg(TEST_WORKSPACE, test_config) + + def teardown_class(self): + """Clean up after the test.""" + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE, ignore_errors=True) + + def setup_method(self, method): # TEST_WORKSPACE is automatically set by test package __init__.py . test_workspace = os.environ['TEST_WORKSPACE'] diff --git a/analyzer/tests/unit/__init__.py b/analyzer/tests/unit/__init__.py index 8e35e46afb..6f7442b714 100644 --- a/analyzer/tests/unit/__init__.py +++ b/analyzer/tests/unit/__init__.py @@ -22,3 +22,4 @@ sys.path.append(os.path.join( REPO_ROOT, 'analyzer', 'tools', 'statistics_collector')) sys.path.append(os.path.join(REPO_ROOT, 'tools', 'report-converter')) +sys.path.append(os.path.join(PKG_ROOT, 'lib', 'python3')) diff --git a/analyzer/tests/unit/test_buildcmd_escaping.py b/analyzer/tests/unit/test_buildcmd_escaping.py index c414e9d29b..9819f8e816 100644 --- a/analyzer/tests/unit/test_buildcmd_escaping.py +++ b/analyzer/tests/unit/test_buildcmd_escaping.py @@ -19,7 +19,7 @@ from codechecker_analyzer.buildlog import log_parser -class BuildCmdTestNose(unittest.TestCase): +class BuildCmdTest(unittest.TestCase): """ Test the build command escaping and execution. """ diff --git a/analyzer/tests/unit/test_result_handler.py b/analyzer/tests/unit/test_result_handler.py index ffbd6898c8..c36385cff7 100644 --- a/analyzer/tests/unit/test_result_handler.py +++ b/analyzer/tests/unit/test_result_handler.py @@ -19,7 +19,7 @@ class BuildAction: original_command = None -class ResultHandlerTestNose(unittest.TestCase): +class ResultHandlerTest(unittest.TestCase): """ Test some functions of ResultHandler base class. """ diff --git a/analyzer/tools/build-logger/.noserc b/analyzer/tools/build-logger/.noserc deleted file mode 100644 index 512f4e1a08..0000000000 --- a/analyzer/tools/build-logger/.noserc +++ /dev/null @@ -1,13 +0,0 @@ -[nosetests] - -# increase verbosity level -verbosity=3 - -# more detailed error messages on failed asserts -detailed-errors=1 - -# stop running tests on first error -stop=1 - -# do not capture stdout -#nocapture=1 diff --git a/analyzer/tools/build-logger/pytest.ini b/analyzer/tools/build-logger/pytest.ini new file mode 100644 index 0000000000..7ee6b8962d --- /dev/null +++ b/analyzer/tools/build-logger/pytest.ini @@ -0,0 +1,13 @@ +[pytest] + +addopts = +# increase verbosity level + --verbose + +# stop running tests on first error +# FIXME: Pretty please comment this horrible setting out, I hate it with a +# passion +# --maxfail=1 + +# do not capture stdout + --capture=sys diff --git a/analyzer/tools/build-logger/requirements_py/dev/requirements.txt b/analyzer/tools/build-logger/requirements_py/dev/requirements.txt index 14d0a89bcd..dea2d59c92 100644 --- a/analyzer/tools/build-logger/requirements_py/dev/requirements.txt +++ b/analyzer/tools/build-logger/requirements_py/dev/requirements.txt @@ -1,3 +1,3 @@ -nose==1.3.7 +pytest==7.3.1 pycodestyle==2.4.0 -pylint==2.8.2 \ No newline at end of file +pylint==2.8.2 diff --git a/analyzer/tools/build-logger/tests/Makefile b/analyzer/tools/build-logger/tests/Makefile index e9e8ac5580..332146eb7b 100644 --- a/analyzer/tools/build-logger/tests/Makefile +++ b/analyzer/tools/build-logger/tests/Makefile @@ -2,8 +2,8 @@ REPO_ROOT ?= REPO_ROOT=$(ROOT) -# Nose test runner configuration options. -NOSECFG = --config .noserc +# pytest test runner configuration options. +PYTESTCFG = -c pytest.ini test: pycodestyle pylint test_unit @@ -27,7 +27,7 @@ pylint_in_env: venv $(ACTIVATE_DEV_VENV) && $(PYLINT_TEST_CMD) UNIT_TEST_CMD = $(REPO_ROOT) \ - nosetests $(NOSECFG) tests/unit + pytest $(PYTESTCFG) tests/unit test_unit: $(UNIT_TEST_CMD) diff --git a/analyzer/tools/merge_clang_extdef_mappings/.noserc b/analyzer/tools/merge_clang_extdef_mappings/.noserc deleted file mode 100644 index 512f4e1a08..0000000000 --- a/analyzer/tools/merge_clang_extdef_mappings/.noserc +++ /dev/null @@ -1,13 +0,0 @@ -[nosetests] - -# increase verbosity level -verbosity=3 - -# more detailed error messages on failed asserts -detailed-errors=1 - -# stop running tests on first error -stop=1 - -# do not capture stdout -#nocapture=1 diff --git a/analyzer/tools/merge_clang_extdef_mappings/pytest.ini b/analyzer/tools/merge_clang_extdef_mappings/pytest.ini new file mode 100644 index 0000000000..7ee6b8962d --- /dev/null +++ b/analyzer/tools/merge_clang_extdef_mappings/pytest.ini @@ -0,0 +1,13 @@ +[pytest] + +addopts = +# increase verbosity level + --verbose + +# stop running tests on first error +# FIXME: Pretty please comment this horrible setting out, I hate it with a +# passion +# --maxfail=1 + +# do not capture stdout + --capture=sys diff --git a/analyzer/tools/merge_clang_extdef_mappings/requirements_py/dev/requirements.txt b/analyzer/tools/merge_clang_extdef_mappings/requirements_py/dev/requirements.txt index 7ac0c0aa2e..dea2d59c92 100644 --- a/analyzer/tools/merge_clang_extdef_mappings/requirements_py/dev/requirements.txt +++ b/analyzer/tools/merge_clang_extdef_mappings/requirements_py/dev/requirements.txt @@ -1,3 +1,3 @@ -nose==1.3.7 +pytest==7.3.1 pycodestyle==2.4.0 pylint==2.8.2 diff --git a/analyzer/tools/merge_clang_extdef_mappings/tests/Makefile b/analyzer/tools/merge_clang_extdef_mappings/tests/Makefile index bf4abc5b56..66930290ab 100644 --- a/analyzer/tools/merge_clang_extdef_mappings/tests/Makefile +++ b/analyzer/tools/merge_clang_extdef_mappings/tests/Makefile @@ -2,8 +2,8 @@ REPO_ROOT ?= REPO_ROOT=$(ROOT) -# Nose test runner configuration options. -NOSECFG = --config .noserc +# pytest test runner configuration options. +PYTESTCFG = -c pytest.ini test: pycodestyle pylint test_unit @@ -27,7 +27,7 @@ pylint_in_env: venv $(ACTIVATE_DEV_VENV) && $(PYLINT_TEST_CMD) UNIT_TEST_CMD = $(REPO_ROOT) \ - nosetests $(NOSECFG) tests/unit + pytest $(PYTESTCFG) tests/unit test_unit: $(UNIT_TEST_CMD) diff --git a/analyzer/tools/merge_clang_extdef_mappings/tests/unit/__init__.py b/analyzer/tools/merge_clang_extdef_mappings/tests/unit/__init__.py index 4259749345..c765d8fae4 100644 --- a/analyzer/tools/merge_clang_extdef_mappings/tests/unit/__init__.py +++ b/analyzer/tools/merge_clang_extdef_mappings/tests/unit/__init__.py @@ -5,3 +5,17 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # ------------------------------------------------------------------------- + +import os +import sys + +REPO_ROOT = os.path.abspath(os.environ['REPO_ROOT']) +PKG_ROOT = os.path.join(REPO_ROOT, 'build', 'CodeChecker') + +os.environ["CC_DATA_FILES_DIR"] = PKG_ROOT + +sys.path.append(REPO_ROOT) +sys.path.append(os.path.join( + REPO_ROOT, 'analyzer', 'tools', 'statistics_collector')) +sys.path.append(os.path.join(REPO_ROOT, 'tools', 'report-converter')) +sys.path.append(os.path.join(PKG_ROOT, 'lib', 'python3')) diff --git a/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/__init__.py b/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/__init__.py index b3a2aa1f9d..0b0114f7e4 100644 --- a/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/__init__.py +++ b/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/__init__.py @@ -6,49 +6,6 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # ------------------------------------------------------------------------- -""" Setup for the test package analyze. """ -import os -import shutil -import tempfile - - -def get_workspace(test_id='test'): - """ Return a temporary workspace for the tests. """ - workspace_root = os.environ.get("MERGE_CTU_FUNC_MAPS_TEST_WORKSPACE_ROOT") - if not workspace_root: - # if no external workspace is set create under the build dir - workspace_root = os.path.join(os.environ['REPO_ROOT'], 'build', - 'workspace') - - if not os.path.exists(workspace_root): - os.makedirs(workspace_root) - - if test_id: - return tempfile.mkdtemp(prefix=test_id + "-", dir=workspace_root) - else: - return workspace_root - - -# Test workspace should be initialized in this module. -TEST_WORKSPACE = None - - -def setup_package(): - """ Setup the environment for the tests. """ - - global TEST_WORKSPACE - TEST_WORKSPACE = get_workspace('merge_clang_extdef_mappings') - - os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE - - -def teardown_package(): - """ Delete the workspace associated with this test. """ - - # TODO: If environment variable is set keep the workspace - # and print out the path. - global TEST_WORKSPACE - - print("Removing: " + TEST_WORKSPACE) - shutil.rmtree(TEST_WORKSPACE) +# This file is empty, and is only present so that this directory will form a +# package. diff --git a/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/merge_clang_extdef_mappings.py b/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/test_merge_clang_extdef_mappings.py similarity index 66% rename from analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/merge_clang_extdef_mappings.py rename to analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/test_merge_clang_extdef_mappings.py index dd0fc9ddd2..a788cc76ba 100644 --- a/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/merge_clang_extdef_mappings.py +++ b/analyzer/tools/merge_clang_extdef_mappings/tests/unit/merge_clang_extdef_mappings/test_merge_clang_extdef_mappings.py @@ -8,13 +8,50 @@ import os import unittest +import shutil +import tempfile from codechecker_merge_clang_extdef_mappings import merge_clang_extdef_mappings -class MergeClangExtdefMappingsTest(unittest.TestCase): - @classmethod - def setUpClass(self): +def get_workspace(test_id='test'): + """ Return a temporary workspace for the tests. """ + workspace_root = os.environ.get("MERGE_CTU_FUNC_MAPS_TEST_WORKSPACE_ROOT") + if not workspace_root: + # if no external workspace is set create under the build dir + workspace_root = os.path.join(os.environ['REPO_ROOT'], 'build', + 'workspace') + + if not os.path.exists(workspace_root): + os.makedirs(workspace_root) + + if test_id: + return tempfile.mkdtemp(prefix=test_id + "-", dir=workspace_root) + else: + return workspace_root + + +class TestMergeClangExtdefMappingsTest(unittest.TestCase): + + def setup_class(self): + """ Setup the environment for the tests. """ + + global TEST_WORKSPACE + TEST_WORKSPACE = get_workspace('merge_clang_extdef_mappings') + + os.environ['TEST_WORKSPACE'] = TEST_WORKSPACE + + def teardown_class(self): + """ Delete the workspace associated with this test. """ + + # TODO: If environment variable is set keep the workspace + # and print out the path. + global TEST_WORKSPACE + + print("Removing: " + TEST_WORKSPACE) + shutil.rmtree(TEST_WORKSPACE) + + def setup_method(self, method): """ Initialize test files. """ self.test_workspace = os.environ['TEST_WORKSPACE'] diff --git a/analyzer/tools/statistics_collector/.noserc b/analyzer/tools/statistics_collector/.noserc deleted file mode 100644 index 512f4e1a08..0000000000 --- a/analyzer/tools/statistics_collector/.noserc +++ /dev/null @@ -1,13 +0,0 @@ -[nosetests] - -# increase verbosity level -verbosity=3 - -# more detailed error messages on failed asserts -detailed-errors=1 - -# stop running tests on first error -stop=1 - -# do not capture stdout -#nocapture=1 diff --git a/analyzer/tools/statistics_collector/pytest.ini b/analyzer/tools/statistics_collector/pytest.ini new file mode 100644 index 0000000000..7ee6b8962d --- /dev/null +++ b/analyzer/tools/statistics_collector/pytest.ini @@ -0,0 +1,13 @@ +[pytest] + +addopts = +# increase verbosity level + --verbose + +# stop running tests on first error +# FIXME: Pretty please comment this horrible setting out, I hate it with a +# passion +# --maxfail=1 + +# do not capture stdout + --capture=sys diff --git a/analyzer/tools/statistics_collector/requirements_py/dev/requirements.txt b/analyzer/tools/statistics_collector/requirements_py/dev/requirements.txt index 7ac0c0aa2e..dea2d59c92 100644 --- a/analyzer/tools/statistics_collector/requirements_py/dev/requirements.txt +++ b/analyzer/tools/statistics_collector/requirements_py/dev/requirements.txt @@ -1,3 +1,3 @@ -nose==1.3.7 +pytest==7.3.1 pycodestyle==2.4.0 pylint==2.8.2 diff --git a/analyzer/tools/statistics_collector/tests/Makefile b/analyzer/tools/statistics_collector/tests/Makefile index af15b8f8ab..b1d49dbdbb 100644 --- a/analyzer/tools/statistics_collector/tests/Makefile +++ b/analyzer/tools/statistics_collector/tests/Makefile @@ -2,8 +2,8 @@ REPO_ROOT ?= REPO_ROOT=$(ROOT) -# Nose test runner configuration options. -NOSECFG = --config .noserc +# pytest test runner configuration options. +PYTESTCFG = -c pytest.ini test: pycodestyle pylint test_unit @@ -27,7 +27,7 @@ pylint_in_env: venv $(ACTIVATE_DEV_VENV) && $(PYLINT_TEST_CMD) UNIT_TEST_CMD = $(REPO_ROOT) \ - nosetests $(NOSECFG) tests/unit + pytest $(PYTESTCFG) tests/unit test_unit: $(UNIT_TEST_CMD) diff --git a/analyzer/tools/statistics_collector/tests/unit/__init__.py b/analyzer/tools/statistics_collector/tests/unit/__init__.py index 4259749345..c765d8fae4 100644 --- a/analyzer/tools/statistics_collector/tests/unit/__init__.py +++ b/analyzer/tools/statistics_collector/tests/unit/__init__.py @@ -5,3 +5,17 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # ------------------------------------------------------------------------- + +import os +import sys + +REPO_ROOT = os.path.abspath(os.environ['REPO_ROOT']) +PKG_ROOT = os.path.join(REPO_ROOT, 'build', 'CodeChecker') + +os.environ["CC_DATA_FILES_DIR"] = PKG_ROOT + +sys.path.append(REPO_ROOT) +sys.path.append(os.path.join( + REPO_ROOT, 'analyzer', 'tools', 'statistics_collector')) +sys.path.append(os.path.join(REPO_ROOT, 'tools', 'report-converter')) +sys.path.append(os.path.join(PKG_ROOT, 'lib', 'python3'))