From 2133eb154594cb470ab6693c2a0232896481645b Mon Sep 17 00:00:00 2001 From: Philip Daniel Keicher Date: Tue, 30 Jan 2024 12:28:08 +0100 Subject: [PATCH 1/6] first version of unit tests for campaigns --- tests/test_campaigns.py | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/test_campaigns.py diff --git a/tests/test_campaigns.py b/tests/test_campaigns.py new file mode 100644 index 00000000..429985d0 --- /dev/null +++ b/tests/test_campaigns.py @@ -0,0 +1,43 @@ +# test_module.py +import os +import unittest +import sys +from glob import glob +import importlib as imp + + +class TestCampaign(unittest.TestCase): + @classmethod + def setUpClass(cls): + modpath = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) + if modpath not in sys.path: + sys.path.append(modpath) + mod = os.environ["TESTMODULE"] + to_import = os.path.relpath(mod, modpath).replace("/", ".") + # Load the module to test + cls.module = imp.import_module(to_import) + + # get all submodules + all_objects = getattr(cls.module, "__all__", None) + cls.submodules = list() + if not isinstance(all_objects, list): + basename = cls.module.__name__.split(".")[-1] + object_name = f"campaign_{basename}" + cls.submodules = {object_name: getattr(cls.module, object_name)} + else: + cls.submodules = {x: getattr(cls.module, x) for x in all_objects} + + def test_campaign_properties(self): + for name, submodule in self.submodules.items(): + with self.subTest(f"testing object {name}"): + self.assertTrue(hasattr(submodule, "name")) + self.assertTrue(hasattr(submodule, "id")) + self.assertTrue(hasattr(submodule, "ecm")) + self.assertTrue(hasattr(submodule, "bx")) + + +if __name__ == "__main__": + # Remove command line arguments before running unittest.main() + # to prevent unittest from trying to interpret them + # if cmsdb is not path of the sys path, add it + unittest.main() From ae610fdaff22cb80f117e5f4b6e7b7cb1d61ab1d Mon Sep 17 00:00:00 2001 From: Philip Daniel Keicher Date: Tue, 30 Jan 2024 13:07:53 +0100 Subject: [PATCH 2/6] added tests to check datasets of campaigns --- tests/test_campaigns.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/test_campaigns.py b/tests/test_campaigns.py index 429985d0..57893779 100644 --- a/tests/test_campaigns.py +++ b/tests/test_campaigns.py @@ -7,6 +7,15 @@ class TestCampaign(unittest.TestCase): + @unittest.skipIf("TESTMODULE" not in os.environ, "TESTMODULE not set") + @unittest.skipIf( + os.environ["TESTMODULE"].strip("/").endswith("run2_2016_nano_v9"), + "Tests for module 'run2_2016_nano_v9' are not implemented yet.", + ) + @unittest.skipIf( + os.environ["TESTMODULE"].strip("/").endswith("__pycache__"), + "'__pycache__' is not a valid module.", + ) @classmethod def setUpClass(cls): modpath = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) @@ -28,13 +37,36 @@ def setUpClass(cls): cls.submodules = {x: getattr(cls.module, x) for x in all_objects} def test_campaign_properties(self): + # loop through the different campaign objects in the current module for name, submodule in self.submodules.items(): + # run the test for each submodule with self.subTest(f"testing object {name}"): + # make sure the campaign defines a basic set of properties self.assertTrue(hasattr(submodule, "name")) self.assertTrue(hasattr(submodule, "id")) self.assertTrue(hasattr(submodule, "ecm")) self.assertTrue(hasattr(submodule, "bx")) + def test_campaign_datasets(self): + # loop through the different campaign objects in the current module + for campaign_name, submodule in self.submodules.items(): + # run the test for each submodule + with self.subTest(f"testing dataset of object '{campaign_name}'"): + # make sure the campaign defines datasets in the first place + self.assertTrue(hasattr(submodule, "datasets")) + datasets = submodule.datasets + # loop through the datasets and test their properties + for dataset_name, _, dataset in datasets.items(): + with self.subTest(f"testing dataset {campaign_name}/{dataset_name}"): + # might want to implement naming conventions here, + # e.g. the name of the dataset is the process name + suffix + self.assertTrue(hasattr(dataset, "name")) + self.assertTrue(hasattr(dataset, "id")) + self.assertTrue(hasattr(dataset, "processes")) + self.assertTrue(hasattr(dataset, "keys")) + self.assertTrue(hasattr(dataset, "n_files")) + self.assertTrue(hasattr(dataset, "n_events")) + if __name__ == "__main__": # Remove command line arguments before running unittest.main() From 1581b1224809e05b08e8198b623b86a871ae2096 Mon Sep 17 00:00:00 2001 From: Philip Daniel Keicher Date: Tue, 30 Jan 2024 13:09:14 +0100 Subject: [PATCH 3/6] script to run campaign tests locally --- tests/run_tests_locally.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 tests/run_tests_locally.sh diff --git a/tests/run_tests_locally.sh b/tests/run_tests_locally.sh new file mode 100755 index 00000000..36807f23 --- /dev/null +++ b/tests/run_tests_locally.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +SCRIPT_DIR=$( cd -- "$( dirname -- "$0" )" &> /dev/null && pwd ) +# Script that runs coverage tests. + +# loop through all modules if no input arguments are given +for mod in ${@}; do + echo "testing ${mod} ..." + TESTMODULE=${mod} python -m unittest ${SCRIPT_DIR}/test_campaigns.py +done From 01b6cb22ea541c1cf2e3e85ca9b661b7f0f2b9d3 Mon Sep 17 00:00:00 2001 From: Philip Daniel Keicher Date: Tue, 30 Jan 2024 13:10:36 +0100 Subject: [PATCH 4/6] chose better name for local script --- tests/{run_tests_locally.sh => run_campaign_tests_locally.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{run_tests_locally.sh => run_campaign_tests_locally.sh} (100%) diff --git a/tests/run_tests_locally.sh b/tests/run_campaign_tests_locally.sh similarity index 100% rename from tests/run_tests_locally.sh rename to tests/run_campaign_tests_locally.sh From e4f04289a66d25bbbe8565e719296f5bc0ebca66 Mon Sep 17 00:00:00 2001 From: Philip Daniel Keicher Date: Tue, 30 Jan 2024 13:45:41 +0100 Subject: [PATCH 5/6] modify workflow to test all campaigns simultaneously --- .github/workflows/lint_and_test.yaml | 29 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/.github/workflows/lint_and_test.yaml b/.github/workflows/lint_and_test.yaml index 45eaae4d..97ad71a1 100644 --- a/.github/workflows/lint_and_test.yaml +++ b/.github/workflows/lint_and_test.yaml @@ -29,8 +29,22 @@ jobs: run: | flake8 cmsdb scripts + collect_dirs: + runs-on: ubuntu-latest + outputs: + dirs: ${{ steps.dirs.outputs.dirs }} + steps: + - uses: actions/checkout@v2 + - id: dirs + run: echo "dirs=$(ls -d cmsdb/campaigns/*/ | jq --raw-input --slurp --compact-output 'split("\n")[:-1]')" >> ${GITHUB_OUTPUT} + + test: + needs: collect_dirs runs-on: ubuntu-latest + strategy: + matrix: + dir: ${{ fromJson(needs.collect_dirs.outputs.dirs) }} steps: - name: Checkout ⬇️ uses: actions/checkout@master @@ -48,14 +62,7 @@ jobs: pip install -U pip pip install -r requirements_dev.txt - - name: Test 🚦 - run: | - python -c "from cmsdb.campaigns.run2_2016_nano_v9 import *" - python -c "from cmsdb.campaigns.run2_2017_nano_v9 import *" - python -c "from cmsdb.campaigns.run2_2018_nano_v9 import *" - python -c "from cmsdb.campaigns.run2_2017_nano_uhh_v11 import *" - python -c "from cmsdb.campaigns.run2_2018_nano_uhh_v11 import *" - python -c "from cmsdb.campaigns.run2_2017_JMEnano_v9 import *" - python -c "from cmsdb.campaigns.run2_2018_JMEnano_v9 import *" - python -c "from cmsdb.campaigns.run3_2022_preEE_nano_v11 import *" - python -c "from cmsdb.campaigns.run3_2022_postEE_nano_v11 import *" + - name: Test Campaigns 🚦 + run: python -m unittest tests/test_campaigns.py + env: + TESTMODULE: ${{ matrix.dir }} \ No newline at end of file From e99bb83775a43d7253bc015b05ab674b8457912e Mon Sep 17 00:00:00 2001 From: Philip Keicher <26219567+pkausw@users.noreply.github.com> Date: Thu, 22 Feb 2024 17:02:31 +0100 Subject: [PATCH 6/6] Implement additional check for processes --- tests/test_campaigns.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_campaigns.py b/tests/test_campaigns.py index 57893779..c5655378 100644 --- a/tests/test_campaigns.py +++ b/tests/test_campaigns.py @@ -63,6 +63,7 @@ def test_campaign_datasets(self): self.assertTrue(hasattr(dataset, "name")) self.assertTrue(hasattr(dataset, "id")) self.assertTrue(hasattr(dataset, "processes")) + self.assertTrue(len(dataset.processes) > 0) self.assertTrue(hasattr(dataset, "keys")) self.assertTrue(hasattr(dataset, "n_files")) self.assertTrue(hasattr(dataset, "n_events"))