From 73a723375a333d772540fddf5726214e764d6db2 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 11:07:50 +0200 Subject: [PATCH 01/42] Create common lib --- test/unit/common/__init__.py | 0 test/unit/common/base.py | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 test/unit/common/__init__.py create mode 100644 test/unit/common/base.py diff --git a/test/unit/common/__init__.py b/test/unit/common/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/unit/common/base.py b/test/unit/common/base.py new file mode 100644 index 00000000..b5bb4d16 --- /dev/null +++ b/test/unit/common/base.py @@ -0,0 +1,63 @@ +""" +Unit and functional tests +""" +import logging +import os +import re +import shlex +import subprocess +import unittest + +class TestBase(unittest.TestCase): + """Unittest base abstract class""" + @classmethod + def setUpClass(cls): + """Load module, save environment""" + # Save environment and location + cls.save_env = os.environ + cls.save_cwd = os.getcwd() + # Move to test dir + cls.test_dir = os.path.abspath(os.path.dirname(__file__)) + os.chdir(cls.test_dir) + + @classmethod + def tearDownClass(cls): + """Restore environment""" + os.chdir(cls.save_cwd) + os.environ = cls.save_env + + def setUp(self): + """Before every test""" + logging.debug("\n%s", "-" * 70) + + def check_command(self, cmd, exit_code=0): + """Run shell command and check status""" + logging.debug("Running: %s", cmd) + commands = shlex.split(cmd) + with subprocess.Popen(commands, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) as process: + stdout, stderr = process.communicate() + self.assertEqual( + process.returncode, + exit_code, "\n" + "\n".join([ + f"command: {cmd}", + f"stdout: {stdout.decode('utf-8')}", + f"stderr: {stderr.decode('utf-8')}"])) + return "\n".join([ + f"command: {cmd}", + f"stdout: {stdout.decode('utf-8')}", + f"stderr: {stderr.decode('utf-8')}"]) + + def grep_file(self, filename, regex): + """Grep given filename""" + pattern = re.compile(regex) + logging.debug("RegEx = r'%s'", regex) + with open(filename, "r", encoding="utf-8") as fileobj: + for line in fileobj: + if pattern.search(line): + logging.debug(line) + return line + self.fail(f"Could not find r'{regex}' in '{filename}'") + return "" \ No newline at end of file From 664914f222e0fae12786460d18220d7a5f475f47 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 11:17:51 +0200 Subject: [PATCH 02/42] Make unit a package This is necessary to let other packages in this folder use the common library --- test/unit/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/unit/__init__.py diff --git a/test/unit/__init__.py b/test/unit/__init__.py new file mode 100644 index 00000000..e69de29b From 2d5a75323b47d9bfc4849f329e43dff1f276fee5 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 14:14:54 +0200 Subject: [PATCH 03/42] Remove unnecessary --- test/unit/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/unit/__init__.py diff --git a/test/unit/__init__.py b/test/unit/__init__.py deleted file mode 100644 index e69de29b..00000000 From 209f01aa82fed30bdc16f31f8f7249d21eeb0677 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 14:15:03 +0200 Subject: [PATCH 04/42] Add logging to base class --- test/unit/common/base.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index b5bb4d16..7a288806 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -7,12 +7,18 @@ import shlex import subprocess import unittest +import sys class TestBase(unittest.TestCase): """Unittest base abstract class""" @classmethod def setUpClass(cls): """Load module, save environment""" + # Enable debug logs for tests if "super verbose" flag is provided + if "-vvv" in sys.argv: + logging.basicConfig( + level=logging.DEBUG, + format="[TEST] %(levelname)5s: %(message)s") # Save environment and location cls.save_env = os.environ cls.save_cwd = os.getcwd() @@ -45,10 +51,8 @@ def check_command(self, cmd, exit_code=0): f"command: {cmd}", f"stdout: {stdout.decode('utf-8')}", f"stderr: {stderr.decode('utf-8')}"])) - return "\n".join([ - f"command: {cmd}", - f"stdout: {stdout.decode('utf-8')}", - f"stderr: {stderr.decode('utf-8')}"]) + return f"stdout: {stdout.decode('utf-8')}", \ + f"stderr: {stderr.decode('utf-8')}" def grep_file(self, filename, regex): """Grep given filename""" From d66e804c983bec73e90794c6c52e6da2d8a178d3 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 14:27:41 +0200 Subject: [PATCH 05/42] Edit comment --- test/unit/common/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 7a288806..1841e9d1 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -1,5 +1,5 @@ """ -Unit and functional tests +Base for unit and functional tests """ import logging import os From c3ebf7eb3bb24c6577d4380f227deb33e7c51b09 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 14:55:00 +0200 Subject: [PATCH 06/42] Add readme, how to add tests --- test/README.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 test/README.md diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..7844ff65 --- /dev/null +++ b/test/README.md @@ -0,0 +1,88 @@ +# Tests: + +## Running Tests + +Our projects use both **`pytest`** and **`unittest`** frameworks. You can run tests using either method. The **`-vvv`** flag is used for **verbosity**, which provides more detailed output and is very helpful for debugging. + +#### To run all tests, use one of the following command: +* **Using Pytest:** + ```bash + pytest unit -vvv + ``` + +* **Using Unittest:** + ```bash + python3 -m unittest discover unit -vvv + ``` + +### Running a Subset of Tests +Specify the directory containing your desired tests. For example, to run tests in `my_test_dir`: + +```bash +pytest unit/my_test_dir -vvv +# OR +python3 -m unittest discover unit/my_test_dir -vvv +``` + +## Adding New Unit Tests + +1. **Create a Test Folder** + Inside the `unit` directory, create a folder for your new test. This folder should contain: + - All source/header files needed for the test + - A `BUILD` file + - A python test script + +2. **Creating the Test File** + Your test script must follow the naming convention: + ```text + test_*.py + ``` + +3. **Set Up Python Path** + At the top of your test file, include the following snippet to correctly handle module imports: + ```python + import os + import sys + + # Python path magic, necessary to avoid module errors + sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + from common.base import TestBase + ``` + +4. **Write the Test Class** + Create your test class by extending `TestBase` and implement your test methods. + +**A simple test class would look like this:** +```python +""" +TODO: Describe what this file does +""" +import os +import sys +import unittest +# Python path magic, necessary to avoid module errors +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from common.base import TestBase + +# TODO: fix folder name +BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", + "unit", "my_test_folder") +BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", + "unit", "my_test_folder") + +class TestTemplate(TestBase): + """TODO: Add a description""" + + def setUp(self): + """TODO: Define clean up before every test""" + super().setUp() + self.check_command("bazel clean") + + def test_template(self): + """Test: TODO: describe your test""" + self.fail(f"Test not implemented") + + +if __name__ == "__main__": + unittest.main(buffer=True) +``` \ No newline at end of file From 7f7af80eb50bc28a21af4970078864ae9b2e3a39 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 14:56:22 +0200 Subject: [PATCH 07/42] Fix a couple mistakes --- test/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/README.md b/test/README.md index 7844ff65..5c198b9e 100644 --- a/test/README.md +++ b/test/README.md @@ -2,9 +2,11 @@ ## Running Tests -Our projects use both **`pytest`** and **`unittest`** frameworks. You can run tests using either method. The **`-vvv`** flag is used for **verbosity**, which provides more detailed output and is very helpful for debugging. +Our projects use both **`pytest`** and **`unittest`** frameworks. +You can run tests using either method. +The **`-vvv`** flag is used for **verbosity**, which provides more detailed output and is very helpful for debugging. -#### To run all tests, use one of the following command: +### To run all tests, use one of the following command: * **Using Pytest:** ```bash pytest unit -vvv @@ -31,6 +33,7 @@ python3 -m unittest discover unit/my_test_dir -vvv - All source/header files needed for the test - A `BUILD` file - A python test script + - An `__init__.py` 2. **Creating the Test File** Your test script must follow the naming convention: From 75e6e65877aa6e3880039653c88bde19aa8cd97b Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 15:07:17 +0200 Subject: [PATCH 08/42] Extend readme with BUILD file instructions --- test/README.md | 54 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/test/README.md b/test/README.md index 5c198b9e..bb077338 100644 --- a/test/README.md +++ b/test/README.md @@ -31,31 +31,41 @@ python3 -m unittest discover unit/my_test_dir -vvv 1. **Create a Test Folder** Inside the `unit` directory, create a folder for your new test. This folder should contain: - All source/header files needed for the test - - A `BUILD` file + - `BUILD` - A python test script - - An `__init__.py` + - `__init__.py` + +2. **Creating the BUILD File** + - Make sure that all failing test targets get the `"manual"` tag. For example: + ``` + codechecker_test( + name = "codechecker_fail", + tags = [ + "manual", + ], + targets = [ + "test_fail", + ], + ) + ``` 2. **Creating the Test File** - Your test script must follow the naming convention: - ```text - test_*.py - ``` - -3. **Set Up Python Path** - At the top of your test file, include the following snippet to correctly handle module imports: - ```python - import os - import sys - - # Python path magic, necessary to avoid module errors - sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - from common.base import TestBase - ``` - -4. **Write the Test Class** - Create your test class by extending `TestBase` and implement your test methods. - -**A simple test class would look like this:** + - Your test script must follow the naming convention: + ```text + test_*.py + ``` + - At the top of your test file, include the following snippet to correctly handle module imports: + ```python + import os + import sys + + # Python path magic, necessary to avoid module errors + sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + from common.base import TestBase + ``` + - Create your test class by extending `TestBase` and implement your test methods. + +**A simple test class example:** ```python """ TODO: Describe what this file does From 650265025a00d95baed1d685a6ad305234ff7f46 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 15:31:04 +0200 Subject: [PATCH 09/42] Remove whitespace --- test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index bb077338..e51c271c 100644 --- a/test/README.md +++ b/test/README.md @@ -98,4 +98,4 @@ class TestTemplate(TestBase): if __name__ == "__main__": unittest.main(buffer=True) -``` \ No newline at end of file +``` \ No newline at end of file From 9aa9ab835204cd8949ff2d868a2b62c499d69f8e Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:01:22 +0200 Subject: [PATCH 10/42] Add __init__.py --- test/unit/__init__.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test/unit/__init__.py diff --git a/test/unit/__init__.py b/test/unit/__init__.py new file mode 100644 index 00000000..c1f405f2 --- /dev/null +++ b/test/unit/__init__.py @@ -0,0 +1,9 @@ +""" +Setup module paths and environment variables for the functional tests. +""" + +import os +import sys + +# Setup the required environment variables for the tests. +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)))) From 982ff2311a8e5f8f9eea4fa4b8ef0bbc1640ca3c Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:21:47 +0200 Subject: [PATCH 11/42] Add warnings for execution path --- test/unit/common/base.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 1841e9d1..e6222726 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -37,7 +37,8 @@ def setUp(self): logging.debug("\n%s", "-" * 70) def check_command(self, cmd, exit_code=0): - """Run shell command and check status""" + """Run shell command and check status. + WARNING: Working directory will be in unit/common.""" logging.debug("Running: %s", cmd) commands = shlex.split(cmd) with subprocess.Popen(commands, @@ -55,7 +56,8 @@ def check_command(self, cmd, exit_code=0): f"stderr: {stderr.decode('utf-8')}" def grep_file(self, filename, regex): - """Grep given filename""" + """Grep given filename. + WARNING: Working directory will be in unit/common.""" pattern = re.compile(regex) logging.debug("RegEx = r'%s'", regex) with open(filename, "r", encoding="utf-8") as fileobj: From 6eef54d7f1a212963d40bedb87d58fc4105b9927 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:22:01 +0200 Subject: [PATCH 12/42] Add test template file --- test/README.md | 40 +---------------------------- test/unit/template/test_template.py | 31 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 39 deletions(-) create mode 100644 test/unit/template/test_template.py diff --git a/test/README.md b/test/README.md index e51c271c..4c252bfb 100644 --- a/test/README.md +++ b/test/README.md @@ -56,46 +56,8 @@ python3 -m unittest discover unit/my_test_dir -vvv ``` - At the top of your test file, include the following snippet to correctly handle module imports: ```python - import os - import sys - - # Python path magic, necessary to avoid module errors - sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from common.base import TestBase ``` - Create your test class by extending `TestBase` and implement your test methods. -**A simple test class example:** -```python -""" -TODO: Describe what this file does -""" -import os -import sys -import unittest -# Python path magic, necessary to avoid module errors -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from common.base import TestBase - -# TODO: fix folder name -BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", - "unit", "my_test_folder") -BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", - "unit", "my_test_folder") - -class TestTemplate(TestBase): - """TODO: Add a description""" - - def setUp(self): - """TODO: Define clean up before every test""" - super().setUp() - self.check_command("bazel clean") - - def test_template(self): - """Test: TODO: describe your test""" - self.fail(f"Test not implemented") - - -if __name__ == "__main__": - unittest.main(buffer=True) -``` \ No newline at end of file +**For a test template look into unit/template** diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py new file mode 100644 index 00000000..328285fe --- /dev/null +++ b/test/unit/template/test_template.py @@ -0,0 +1,31 @@ +""" +TODO: Describe what this file does +""" +import os +import sys +import unittest +# Python path magic, necessary to avoid module errors +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from common.base import TestBase + +# TODO: fix folder name +BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", + "unit", "my_test_folder") +BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", + "unit", "my_test_folder") + +class TestTemplate(TestBase): + """TODO: Add a description""" + + def setUp(self): + """TODO: Define clean up before every test""" + super().setUp() + self.check_command("bazel clean") + + def test_template(self): + """Test: TODO: describe your test""" + self.fail("Test not implemented!") + + +if __name__ == "__main__": + unittest.main(buffer=True) \ No newline at end of file From 9ad69c547eaff69e3d95425137ec7f74f1859648 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:24:15 +0200 Subject: [PATCH 13/42] Add param for passing working directory --- test/unit/common/base.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index e6222726..20731a0a 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -36,15 +36,16 @@ def setUp(self): """Before every test""" logging.debug("\n%s", "-" * 70) - def check_command(self, cmd, exit_code=0): + def check_command(self, cmd, exit_code=0, working_dir=None): """Run shell command and check status. - WARNING: Working directory will be in unit/common.""" + WARNING: Working directory by default will be in unit/common.""" logging.debug("Running: %s", cmd) commands = shlex.split(cmd) with subprocess.Popen(commands, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) as process: + stderr=subprocess.PIPE, + cwd=working_dir) as process: stdout, stderr = process.communicate() self.assertEqual( process.returncode, From 92efa456095f521620570dad240130aef9919626 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:32:03 +0200 Subject: [PATCH 14/42] Add warning for current working directory change --- test/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/README.md b/test/README.md index 4c252bfb..051563ca 100644 --- a/test/README.md +++ b/test/README.md @@ -59,5 +59,7 @@ python3 -m unittest discover unit/my_test_dir -vvv from common.base import TestBase ``` - Create your test class by extending `TestBase` and implement your test methods. + > [!WARNING] + > Your current working directory will be `unit/common` for every action! **For a test template look into unit/template** From 6c791e84ccb708dd80fb5a8fec707a9c9984d870 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:32:30 +0200 Subject: [PATCH 15/42] Add current dir const to template --- test/unit/template/test_template.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index 328285fe..bf4c39a1 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -9,6 +9,7 @@ from common.base import TestBase # TODO: fix folder name +WORKING_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", "unit", "my_test_folder") BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", From e4816baaf12dda0479c72001d28f43ce2954254b Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Fri, 15 Aug 2025 16:56:30 +0200 Subject: [PATCH 16/42] Update template to run as test --- test/unit/template/__init__.py | 0 test/unit/template/test_template.py | 5 +---- 2 files changed, 1 insertion(+), 4 deletions(-) create mode 100644 test/unit/template/__init__.py diff --git a/test/unit/template/__init__.py b/test/unit/template/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index bf4c39a1..3dbaaa84 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -2,10 +2,7 @@ TODO: Describe what this file does """ import os -import sys import unittest -# Python path magic, necessary to avoid module errors -sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from common.base import TestBase # TODO: fix folder name @@ -25,7 +22,7 @@ def setUp(self): def test_template(self): """Test: TODO: describe your test""" - self.fail("Test not implemented!") + self.assertTrue(True) if __name__ == "__main__": From 90e3c7498719430014c74fb5ef975ddf715d4e70 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 08:39:22 +0200 Subject: [PATCH 17/42] Fix path problems --- test/unit/common/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 20731a0a..35c75ac3 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -12,7 +12,7 @@ class TestBase(unittest.TestCase): """Unittest base abstract class""" @classmethod - def setUpClass(cls): + def setUpClass(cls, path : str = None): """Load module, save environment""" # Enable debug logs for tests if "super verbose" flag is provided if "-vvv" in sys.argv: @@ -23,7 +23,7 @@ def setUpClass(cls): cls.save_env = os.environ cls.save_cwd = os.getcwd() # Move to test dir - cls.test_dir = os.path.abspath(os.path.dirname(__file__)) + cls.test_dir = path os.chdir(cls.test_dir) @classmethod From 4588e05e2696f24b0c47b0825a4aa0a59762fabb Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 08:39:27 +0200 Subject: [PATCH 18/42] Add linefeed --- test/unit/common/base.py | 2 +- test/unit/template/test_template.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 35c75ac3..32284180 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -67,4 +67,4 @@ def grep_file(self, filename, regex): logging.debug(line) return line self.fail(f"Could not find r'{regex}' in '{filename}'") - return "" \ No newline at end of file + return "" diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index 3dbaaa84..b3a8d355 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -26,4 +26,4 @@ def test_template(self): if __name__ == "__main__": - unittest.main(buffer=True) \ No newline at end of file + unittest.main(buffer=True) From 8397ae589d4226dcf8b928d4b2656c9072c6331a Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:08:07 +0200 Subject: [PATCH 19/42] Add way to pass path to base class, move folder change before environment save --- test/unit/common/base.py | 11 +++++++---- test/unit/template/test_template.py | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 32284180..21473a45 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -11,20 +11,23 @@ class TestBase(unittest.TestCase): """Unittest base abstract class""" + # This variable must be overwritten in each subclass! + __test_path__ : str = os.path.abspath(__file__) + @classmethod - def setUpClass(cls, path : str = None): + def setUpClass(cls): """Load module, save environment""" # Enable debug logs for tests if "super verbose" flag is provided if "-vvv" in sys.argv: logging.basicConfig( level=logging.DEBUG, format="[TEST] %(levelname)5s: %(message)s") + # Move to test dir + cls.test_dir = cls.__test_path__ + os.chdir(cls.test_dir) # Save environment and location cls.save_env = os.environ cls.save_cwd = os.getcwd() - # Move to test dir - cls.test_dir = path - os.chdir(cls.test_dir) @classmethod def tearDownClass(cls): diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index b3a8d355..51b4461e 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -6,7 +6,6 @@ from common.base import TestBase # TODO: fix folder name -WORKING_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", "unit", "my_test_folder") BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", @@ -14,6 +13,8 @@ class TestTemplate(TestBase): """TODO: Add a description""" + # This line is mandatory + __test_path__ = os.path.dirname(os.path.abspath(__file__)) def setUp(self): """TODO: Define clean up before every test""" From 72c23ece85fcc55654ab449674ed840b2dfb647c Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:19:47 +0200 Subject: [PATCH 20/42] Format --- test/unit/common/base.py | 43 ++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 21473a45..f27c1ec0 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -1,6 +1,7 @@ """ Base for unit and functional tests """ + import logging import os import re @@ -9,10 +10,12 @@ import unittest import sys + class TestBase(unittest.TestCase): """Unittest base abstract class""" - # This variable must be overwritten in each subclass! - __test_path__ : str = os.path.abspath(__file__) + + # This variable must be overwritten in each subclass! + __test_path__: str = os.path.abspath(__file__) @classmethod def setUpClass(cls): @@ -20,8 +23,8 @@ def setUpClass(cls): # Enable debug logs for tests if "super verbose" flag is provided if "-vvv" in sys.argv: logging.basicConfig( - level=logging.DEBUG, - format="[TEST] %(levelname)5s: %(message)s") + level=logging.DEBUG, format="[TEST] %(levelname)5s: %(message)s" + ) # Move to test dir cls.test_dir = cls.__test_path__ os.chdir(cls.test_dir) @@ -44,20 +47,30 @@ def check_command(self, cmd, exit_code=0, working_dir=None): WARNING: Working directory by default will be in unit/common.""" logging.debug("Running: %s", cmd) commands = shlex.split(cmd) - with subprocess.Popen(commands, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=working_dir) as process: + with subprocess.Popen( + commands, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=working_dir, + ) as process: stdout, stderr = process.communicate() self.assertEqual( process.returncode, - exit_code, "\n" + "\n".join([ - f"command: {cmd}", - f"stdout: {stdout.decode('utf-8')}", - f"stderr: {stderr.decode('utf-8')}"])) - return f"stdout: {stdout.decode('utf-8')}", \ - f"stderr: {stderr.decode('utf-8')}" + exit_code, + "\n" + + "\n".join( + [ + f"command: {cmd}", + f"stdout: {stdout.decode('utf-8')}", + f"stderr: {stderr.decode('utf-8')}", + ] + ), + ) + return ( + f"stdout: {stdout.decode('utf-8')}", + f"stderr: {stderr.decode('utf-8')}", + ) def grep_file(self, filename, regex): """Grep given filename. From 0444c7b445ed51b2f603d4a7d03820c4f83188d7 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:23:34 +0200 Subject: [PATCH 21/42] Edit to new path setting --- test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index 051563ca..1f752269 100644 --- a/test/README.md +++ b/test/README.md @@ -60,6 +60,6 @@ python3 -m unittest discover unit/my_test_dir -vvv ``` - Create your test class by extending `TestBase` and implement your test methods. > [!WARNING] - > Your current working directory will be `unit/common` for every action! + > You should include this line in your test class, this sets the current working directory: `__test_path__ = os.path.dirname(os.path.abspath(__file__))` **For a test template look into unit/template** From a39b2f874f7975ccc508911768de581a23448d9f Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:25:58 +0200 Subject: [PATCH 22/42] Remove warnings --- test/unit/common/base.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index f27c1ec0..81543e41 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -43,8 +43,7 @@ def setUp(self): logging.debug("\n%s", "-" * 70) def check_command(self, cmd, exit_code=0, working_dir=None): - """Run shell command and check status. - WARNING: Working directory by default will be in unit/common.""" + """Run shell command and check status.""" logging.debug("Running: %s", cmd) commands = shlex.split(cmd) with subprocess.Popen( @@ -73,8 +72,7 @@ def check_command(self, cmd, exit_code=0, working_dir=None): ) def grep_file(self, filename, regex): - """Grep given filename. - WARNING: Working directory will be in unit/common.""" + """Grep given filename.""" pattern = re.compile(regex) logging.debug("RegEx = r'%s'", regex) with open(filename, "r", encoding="utf-8") as fileobj: From 4a4164b0b71d0df2f19626ed419f6687ebc88341 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:28:13 +0200 Subject: [PATCH 23/42] Fix warning --- test/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/README.md b/test/README.md index 1f752269..79034b66 100644 --- a/test/README.md +++ b/test/README.md @@ -59,7 +59,8 @@ python3 -m unittest discover unit/my_test_dir -vvv from common.base import TestBase ``` - Create your test class by extending `TestBase` and implement your test methods. - > [!WARNING] - > You should include this line in your test class, this sets the current working directory: `__test_path__ = os.path.dirname(os.path.abspath(__file__))` +> [!WARNING] +> You should include this line in your test class, this sets the current working directory: +> `__test_path__ = os.path.dirname(os.path.abspath(__file__))` **For a test template look into unit/template** From 66af78f6435b7eb9d2048b283556501dc8473b20 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:54:12 +0200 Subject: [PATCH 24/42] Change comment --- test/unit/template/test_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index 51b4461e..93ec7251 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -13,7 +13,7 @@ class TestTemplate(TestBase): """TODO: Add a description""" - # This line is mandatory + # Set working directory __test_path__ = os.path.dirname(os.path.abspath(__file__)) def setUp(self): From 80674abd9680b4043791e7d333b84654f6448f45 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 09:57:06 +0200 Subject: [PATCH 25/42] Move template into unittest folder --- test/unit/template/__init__.py | 0 test/unit/{template => }/test_template.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/unit/template/__init__.py rename test/unit/{template => }/test_template.py (100%) diff --git a/test/unit/template/__init__.py b/test/unit/template/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/unit/template/test_template.py b/test/unit/test_template.py similarity index 100% rename from test/unit/template/test_template.py rename to test/unit/test_template.py From 9b8778f6da51189c50c91534943f63b5db5e82f3 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 10:11:26 +0200 Subject: [PATCH 26/42] Update README --- test/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index 79034b66..f5092dd2 100644 --- a/test/README.md +++ b/test/README.md @@ -38,6 +38,7 @@ python3 -m unittest discover unit/my_test_dir -vvv 2. **Creating the BUILD File** - Make sure that all failing test targets get the `"manual"` tag. For example: ``` + # This is a test I expect to fail codechecker_test( name = "codechecker_fail", tags = [ @@ -61,6 +62,8 @@ python3 -m unittest discover unit/my_test_dir -vvv - Create your test class by extending `TestBase` and implement your test methods. > [!WARNING] > You should include this line in your test class, this sets the current working directory: -> `__test_path__ = os.path.dirname(os.path.abspath(__file__))` +> ```python +> __test_path__ = os.path.dirname(os.path.abspath(__file__)) +> ``` **For a test template look into unit/template** From 624d466a67c75931481ba6b78ed808e38c6e3e2d Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 10:12:44 +0200 Subject: [PATCH 27/42] Change template place --- test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index f5092dd2..e497ea6e 100644 --- a/test/README.md +++ b/test/README.md @@ -66,4 +66,4 @@ python3 -m unittest discover unit/my_test_dir -vvv > __test_path__ = os.path.dirname(os.path.abspath(__file__)) > ``` -**For a test template look into unit/template** +**A test template can be found in the root of the unit directory From 696f8efe122c4c08851407cec88729252f984951 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 11:13:20 +0200 Subject: [PATCH 28/42] Add license header --- test/unit/__init__.py | 14 ++++++++++++++ test/unit/common/base.py | 14 ++++++++++++++ test/unit/test_template.py | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/test/unit/__init__.py b/test/unit/__init__.py index c1f405f2..cf806d2e 100644 --- a/test/unit/__init__.py +++ b/test/unit/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """ Setup module paths and environment variables for the functional tests. """ diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 81543e41..a945c81c 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -1,3 +1,17 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """ Base for unit and functional tests """ diff --git a/test/unit/test_template.py b/test/unit/test_template.py index 93ec7251..903f6a46 100644 --- a/test/unit/test_template.py +++ b/test/unit/test_template.py @@ -1,3 +1,17 @@ +# Copyright 2023 Ericsson AB +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """ TODO: Describe what this file does """ From 8e98a4c8ab57b323e8300633b9be955d141059ca Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 11:30:38 +0200 Subject: [PATCH 29/42] Add explanation to __init__.py --- test/unit/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/__init__.py b/test/unit/__init__.py index cf806d2e..e6deb66a 100644 --- a/test/unit/__init__.py +++ b/test/unit/__init__.py @@ -19,5 +19,6 @@ import os import sys -# Setup the required environment variables for the tests. +# Allow relative imports within the test project to work as expected +# Without it no module (test) would be able to import the common library sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)))) From 98ef3778b5a8fcaf7dadd6fe7cb75f456b118105 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 14:47:57 +0200 Subject: [PATCH 30/42] Enforce setting __test_path__ BAZEL_BIN_DIR and BAZEL_TESTLOGS_DIR --- test/unit/common/base.py | 22 +++++++++++++++++++++- test/unit/test_template.py | 10 +++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index a945c81c..d23fb0db 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -29,11 +29,31 @@ class TestBase(unittest.TestCase): """Unittest base abstract class""" # This variable must be overwritten in each subclass! - __test_path__: str = os.path.abspath(__file__) + __test_path__: str = None + BAZEL_BIN_DIR: str = None + BAZEL_TESTLOGS_DIR: str = None @classmethod def setUpClass(cls): """Load module, save environment""" + ErrorCollector: list[str] = [] + if cls.__test_path__ == None: + ErrorCollector.append( + "Test path must be overwritten! Use:" + "\n__test_path__ = os.path.dirname(os.path.abspath(__file__))" + ) + if cls.BAZEL_BIN_DIR == None: + ErrorCollector.append( + "Bazel bin directory must be overwritten! Use:" + "../../../bazel-bin/test/unit/my_test_folder" + ) + if cls.BAZEL_TESTLOGS_DIR == None: + ErrorCollector.append( + "Bazel test logs directory must be overwritten! Use:" + "../../../bazel-testlogs/test/unit/my_test_folder" + ) + if ErrorCollector: + raise NotImplementedError("\n".join(ErrorCollector)) # Enable debug logs for tests if "super verbose" flag is provided if "-vvv" in sys.argv: logging.basicConfig( diff --git a/test/unit/test_template.py b/test/unit/test_template.py index 903f6a46..b05df31e 100644 --- a/test/unit/test_template.py +++ b/test/unit/test_template.py @@ -19,16 +19,16 @@ import unittest from common.base import TestBase -# TODO: fix folder name -BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", - "unit", "my_test_folder") -BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", - "unit", "my_test_folder") class TestTemplate(TestBase): """TODO: Add a description""" # Set working directory __test_path__ = os.path.dirname(os.path.abspath(__file__)) + # TODO: fix folder name + BAZEL_BIN_DIR = os.path.join("../../..", "bazel-bin", "test", + "unit", "my_test_folder") + BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", + "unit", "my_test_folder") def setUp(self): """TODO: Define clean up before every test""" From 28bf71b1242aea5a9224c367a8b69eaf841b7473 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 14:55:26 +0200 Subject: [PATCH 31/42] Rewrite check command to act more like run_command --- test/unit/common/base.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index d23fb0db..ef6f621b 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -76,8 +76,14 @@ def setUp(self): """Before every test""" logging.debug("\n%s", "-" * 70) - def check_command(self, cmd, exit_code=0, working_dir=None): - """Run shell command and check status.""" + def run_command(self, cmd, working_dir=None): + """ + Run shell command and check status. + returns: + - exit code : int + - stdout : str + - stderr : str + """ logging.debug("Running: %s", cmd) commands = shlex.split(cmd) with subprocess.Popen( @@ -88,19 +94,8 @@ def check_command(self, cmd, exit_code=0, working_dir=None): cwd=working_dir, ) as process: stdout, stderr = process.communicate() - self.assertEqual( - process.returncode, - exit_code, - "\n" - + "\n".join( - [ - f"command: {cmd}", - f"stdout: {stdout.decode('utf-8')}", - f"stderr: {stderr.decode('utf-8')}", - ] - ), - ) return ( + process.returncode, f"stdout: {stdout.decode('utf-8')}", f"stderr: {stderr.decode('utf-8')}", ) From 2d170dc51e75b4b71fbc25cc3f50ddf9acd1832e Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 18 Aug 2025 14:57:32 +0200 Subject: [PATCH 32/42] Update comment --- test/unit/common/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index ef6f621b..b67bf054 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -78,7 +78,7 @@ def setUp(self): def run_command(self, cmd, working_dir=None): """ - Run shell command and check status. + Run shell command. returns: - exit code : int - stdout : str From 3ae171145680e8361c34da62b423abacdcdd1bc7 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 14:02:15 +0200 Subject: [PATCH 33/42] Revert "Move template into unittest folder" This reverts commit e52a8ed15320c773c0918d7ff5028f5f07351096. --- test/unit/template/__init__.py | 0 test/unit/{ => template}/test_template.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/unit/template/__init__.py rename test/unit/{ => template}/test_template.py (100%) diff --git a/test/unit/template/__init__.py b/test/unit/template/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/unit/test_template.py b/test/unit/template/test_template.py similarity index 100% rename from test/unit/test_template.py rename to test/unit/template/test_template.py From 205466655b90e98a1acea896c549934ae6adf221 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 14:02:18 +0200 Subject: [PATCH 34/42] Revert "Change template place" This reverts commit 33749cc733310afd6e2f8b71466d64bc9687fce5. --- test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index e497ea6e..f5092dd2 100644 --- a/test/README.md +++ b/test/README.md @@ -66,4 +66,4 @@ python3 -m unittest discover unit/my_test_dir -vvv > __test_path__ = os.path.dirname(os.path.abspath(__file__)) > ``` -**A test template can be found in the root of the unit directory +**For a test template look into unit/template** From cee4d667fb6ce3e81e6bfbf655e07c0c7f4971dd Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 14:11:46 +0200 Subject: [PATCH 35/42] Add setup, teardown to subclass --- test/unit/template/test_template.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index b05df31e..d8fd1f38 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -17,6 +17,7 @@ """ import os import unittest +from typing import final from common.base import TestBase @@ -30,10 +31,20 @@ class TestTemplate(TestBase): BAZEL_TESTLOGS_DIR = os.path.join("../../..", "bazel-testlogs", "test", "unit", "my_test_folder") + @final + @classmethod + def setUpClass(cls): + super().setUpClass() + + @final + @classmethod + def tearDownClass(cls): + super().tearDownClass() + def setUp(self): """TODO: Define clean up before every test""" super().setUp() - self.check_command("bazel clean") + self.run_command("bazel clean") def test_template(self): """Test: TODO: describe your test""" From f59eb15d6e4c80f07c2aeef28b0b613e399d923d Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 14:17:41 +0200 Subject: [PATCH 36/42] Add comments, and teardown method --- test/unit/template/test_template.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index d8fd1f38..88c9cf02 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -34,11 +34,13 @@ class TestTemplate(TestBase): @final @classmethod def setUpClass(cls): + """TODO: Define set up before the test suite""" super().setUpClass() @final @classmethod def tearDownClass(cls): + """TODO: Define clean up after the test suite""" super().tearDownClass() def setUp(self): @@ -46,6 +48,10 @@ def setUp(self): super().setUp() self.run_command("bazel clean") + def tearDown(self): + """TODO: Define clean up after every test""" + return super().tearDown() + def test_template(self): """Test: TODO: describe your test""" self.assertTrue(True) From a02e7920764bae170172a67b2d564b3d735c72eb Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 14:36:13 +0200 Subject: [PATCH 37/42] Edit grep to not cause fail --- test/unit/common/base.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index b67bf054..86bb66c6 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -101,13 +101,17 @@ def run_command(self, cmd, working_dir=None): ) def grep_file(self, filename, regex): - """Grep given filename.""" + """ + Grep given filename. + Returns list of matched lines. + Returns empty list if no match is found + """ + results : list[str] = [] pattern = re.compile(regex) logging.debug("RegEx = r'%s'", regex) with open(filename, "r", encoding="utf-8") as fileobj: for line in fileobj: if pattern.search(line): logging.debug(line) - return line - self.fail(f"Could not find r'{regex}' in '{filename}'") - return "" + results.append(line) + return results From b16795037f17c2483f24b2956c48946c805385db Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 14:47:28 +0200 Subject: [PATCH 38/42] Move clean command to only run once per suite --- test/unit/template/test_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/template/test_template.py b/test/unit/template/test_template.py index 88c9cf02..8113cdd2 100644 --- a/test/unit/template/test_template.py +++ b/test/unit/template/test_template.py @@ -36,6 +36,7 @@ class TestTemplate(TestBase): def setUpClass(cls): """TODO: Define set up before the test suite""" super().setUpClass() + cls.run_command("bazel clean") @final @classmethod @@ -46,7 +47,6 @@ def tearDownClass(cls): def setUp(self): """TODO: Define clean up before every test""" super().setUp() - self.run_command("bazel clean") def tearDown(self): """TODO: Define clean up after every test""" From 217dc53c0f7bc3ad7331e1ce43f995bf01f50187 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 19 Aug 2025 15:04:38 +0200 Subject: [PATCH 39/42] Change run command to class method --- test/unit/common/base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 86bb66c6..878b33f3 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -76,6 +76,7 @@ def setUp(self): """Before every test""" logging.debug("\n%s", "-" * 70) + @classmethod def run_command(self, cmd, working_dir=None): """ Run shell command. @@ -100,6 +101,7 @@ def run_command(self, cmd, working_dir=None): f"stderr: {stderr.decode('utf-8')}", ) + @classmethod def grep_file(self, filename, regex): """ Grep given filename. From 468fdd911c7a19013ffaad0ed4e418e1e5e1a37f Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Thu, 21 Aug 2025 11:44:03 +0200 Subject: [PATCH 40/42] Add typing --- test/unit/common/base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 878b33f3..8d2fd5a1 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -77,13 +77,13 @@ def setUp(self): logging.debug("\n%s", "-" * 70) @classmethod - def run_command(self, cmd, working_dir=None): + def run_command(self, cmd: str, working_dir:str=None) -> tuple[int, str, str]: """ Run shell command. returns: - - exit code : int - - stdout : str - - stderr : str + - exit code + - stdout + - stderr """ logging.debug("Running: %s", cmd) commands = shlex.split(cmd) From 8cc0436a025d9a80c10ebdb8a8866064da1fde5b Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Thu, 21 Aug 2025 11:44:32 +0200 Subject: [PATCH 41/42] Create constains_regex_in_files --- test/unit/common/base.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 8d2fd5a1..2e848ec2 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -117,3 +117,15 @@ def grep_file(self, filename, regex): logging.debug(line) results.append(line) return results + + @classmethod + def contains_regex_in_files(self, regex: str, folder_path: str) -> list[str]: + """ + Returns a list of files it found your regex in + """ + result = [] + for file in folder_path: + logging.debug(f"Checking file: {file}") + if self.grep_file(file, regex): + result.append(file) + return result From acf7f545d779980f0272532183aff2a520dccfd0 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Thu, 21 Aug 2025 13:34:29 +0200 Subject: [PATCH 42/42] change it so contains regex works for only one file and gives back boolean --- test/unit/common/base.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/test/unit/common/base.py b/test/unit/common/base.py index 2e848ec2..51766ac6 100644 --- a/test/unit/common/base.py +++ b/test/unit/common/base.py @@ -119,13 +119,8 @@ def grep_file(self, filename, regex): return results @classmethod - def contains_regex_in_files(self, regex: str, folder_path: str) -> list[str]: + def contains_regex_in_file(self, file_path: str, regex: str) -> bool: """ - Returns a list of files it found your regex in + Returns a boolean, whether the specified file contains the regex or not. """ - result = [] - for file in folder_path: - logging.debug(f"Checking file: {file}") - if self.grep_file(file, regex): - result.append(file) - return result + return self.grep_file(file_path, regex) != []