From 092114bc3f5f614dbe9d77ef12e1773a037b7614 Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 12:15:35 -0700 Subject: [PATCH 1/7] use tests.BaseDatasetTest class for testing (note: still written in Python 2.7-compatible manner) --- src/alchemtest/tests/__init__.py | 32 ++++++++++++++++++++++++++++++++ src/alchemtest/tests/test_gmx.py | 28 ++++------------------------ 2 files changed, 36 insertions(+), 24 deletions(-) create mode 100644 src/alchemtest/tests/__init__.py diff --git a/src/alchemtest/tests/__init__.py b/src/alchemtest/tests/__init__.py new file mode 100644 index 0000000..d6a4d7f --- /dev/null +++ b/src/alchemtest/tests/__init__.py @@ -0,0 +1,32 @@ +import os + +class BaseDatasetTest(object): + # @pytest.fixture(scope="class", + # params = [(load_tyr2ala, ('forward', 'backward'), (1, 1)), + # ]) + # def dataset(self, reques): + # return super().dataset(request) + + def dataset(self, request): + '''The input dataset is specified as: + load_method: The method for loading the dataset. + keys: The keys to the corresponding dataset. + value_length: The expected number of file for each key. + ''' + load_method, keys, value_length = request.param + return load_method, keys, value_length + + def test_num_files(self, dataset): + '''Test if the number of files matches with the expected number of + files.''' + load_method, keys, value_length = dataset + for index, key in enumerate(keys): + assert len(load_method().data[key]) == value_length[index] + + def test_file_exist(self, dataset): + '''Test if files do exist.''' + load_method, keys, value_length = dataset + for key in keys: + for file in load_method().data[key]: + if not os.path.isfile(file): + raise AssertionError('Missing file in data set: {}'.format(file)) diff --git a/src/alchemtest/tests/test_gmx.py b/src/alchemtest/tests/test_gmx.py index bad725e..6365faa 100644 --- a/src/alchemtest/tests/test_gmx.py +++ b/src/alchemtest/tests/test_gmx.py @@ -1,33 +1,13 @@ '''Tests for all the gromacs dataset''' -import os import pytest from alchemtest.gmx import load_benzene -class TestBenzene: +from . import BaseDatasetTest + +class TestBenzene(BaseDatasetTest): @pytest.fixture(scope="class", params = [(load_benzene, ('Coulomb', 'VDW'), (5, 16)), ]) def dataset(self, request): - '''The input dataset is specified as: - load_method: The method for loading the dataset. - keys: The keys to the corresponding dataset. - value_length: The expected number of file for each key. - ''' - load_method, keys, value_length = request.param - return load_method, keys, value_length - - def test_num_files(self, dataset): - '''Test if the number of files matches with the expected number of - files.''' - load_method, keys, value_length = dataset - for index, key in enumerate(keys): - assert len(load_method().data[key]) == value_length[index] - - def test_file_exist(self, dataset): - '''Test if files do exist.''' - load_method, keys, value_length = dataset - for key in keys: - for file in load_method().data[key]: - if not os.path.isfile(file): - raise AssertionError('Missing file in data set: {}'.format(file)) + return super().dataset(request) From 2f2798df218f0c303887389253c891cf64fff72c Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 12:19:24 -0700 Subject: [PATCH 2/7] NAMD tyr2ala and IDWS tests fix #50 --- src/alchemtest/tests/test_namd.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/alchemtest/tests/test_namd.py diff --git a/src/alchemtest/tests/test_namd.py b/src/alchemtest/tests/test_namd.py new file mode 100644 index 0000000..2249eb1 --- /dev/null +++ b/src/alchemtest/tests/test_namd.py @@ -0,0 +1,15 @@ +'''Tests for all the NAMD datasets''' +import pytest + +from alchemtest.namd import load_tyr2ala, load_idws + +from . import BaseDatasetTest + + +class TestNAMD(BaseDatasetTest): + @pytest.fixture(scope="class", + params = [(load_tyr2ala, ('forward', 'backward'), (1, 1)), + (load_idws, ('forward', ), (2,)), + ]) + def dataset(self, request): + return super(TestNAMD, self).dataset(request) From b66f52b8cb1bbd848cf1e193b848e4e6b89eeb9a Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 13:00:32 -0700 Subject: [PATCH 3/7] test GOMC dataset fix #52 --- src/alchemtest/tests/test_gomc.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/alchemtest/tests/test_gomc.py diff --git a/src/alchemtest/tests/test_gomc.py b/src/alchemtest/tests/test_gomc.py new file mode 100644 index 0000000..670ba89 --- /dev/null +++ b/src/alchemtest/tests/test_gomc.py @@ -0,0 +1,15 @@ +'''Tests for all the GOMC dataset''' +import pytest + +from alchemtest.gomc import load_benzene + +from . import BaseDatasetTest + +class TestGOMC(BaseDatasetTest): + # note that the GOMC data does not use a dict for data but directly returns + # a list; we can work around this peculiarity by using a slice instead of a key + @pytest.fixture(scope="class", + params = [(load_benzene, (slice(None),), (23,)), + ]) + def dataset(self, request): + return super(TestGOMC, self).dataset(request) From 746a33f757b67fc05324bc2fa9e1a9af8535f414 Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 12:51:47 -0700 Subject: [PATCH 4/7] test all GMX datasets close #51 --- src/alchemtest/tests/test_gmx.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/alchemtest/tests/test_gmx.py b/src/alchemtest/tests/test_gmx.py index 6365faa..9b2798d 100644 --- a/src/alchemtest/tests/test_gmx.py +++ b/src/alchemtest/tests/test_gmx.py @@ -1,13 +1,30 @@ '''Tests for all the gromacs dataset''' import pytest -from alchemtest.gmx import load_benzene +from alchemtest.gmx import (load_benzene, load_ABFE, + load_expanded_ensemble_case_1, + load_expanded_ensemble_case_2, + load_expanded_ensemble_case_3, + load_water_particle_without_energy, + load_water_particle_with_potential_energy, + load_water_particle_with_total_energy, + ) from . import BaseDatasetTest -class TestBenzene(BaseDatasetTest): + +class TestGROMACS(BaseDatasetTest): @pytest.fixture(scope="class", params = [(load_benzene, ('Coulomb', 'VDW'), (5, 16)), + (load_ABFE, ('complex', 'ligand'), (30, 20)), + (load_expanded_ensemble_case_1, ('AllStates', ), (1,)), + (load_expanded_ensemble_case_2, ('AllStates', ), (2,)), + (load_expanded_ensemble_case_3, ('AllStates', ), (32,)), + (load_water_particle_without_energy, ('AllStates', ), (38,)), + (load_water_particle_with_potential_energy, ('AllStates', ), (38,)), + (load_water_particle_with_total_energy, ('AllStates', ), (38,)), ]) def dataset(self, request): - return super().dataset(request) + return super(TestGROMACS, self).dataset(request) + + From 1b27606119ee337c79b5cfaf7829d1b372e122e0 Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 13:33:13 -0700 Subject: [PATCH 5/7] partial AMBER tests The current BaseDatasetTest is not flexible enough to handle two of the AMBER datasets. --- src/alchemtest/tests/test_amber.py | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/alchemtest/tests/test_amber.py diff --git a/src/alchemtest/tests/test_amber.py b/src/alchemtest/tests/test_amber.py new file mode 100644 index 0000000..8718188 --- /dev/null +++ b/src/alchemtest/tests/test_amber.py @@ -0,0 +1,38 @@ +'''Tests for all the AMBER datasets''' +import pytest + +from alchemtest.amber import (load_bace_improper, load_bace_example, + load_simplesolvated, load_invalidfiles, ) + + + +from . import BaseDatasetTest + +class TestAMBER(BaseDatasetTest): + @pytest.fixture(scope="class", + params = [(load_bace_improper, ('vdw',), (12,)), + (load_simplesolvated, ('charge', 'vdw'), (5, 12)), + ]) + def dataset(self, request): + return super(TestAMBER, self).dataset(request) + + +# difficult -- has sub dicts under 'complex'/'solvated' -> 'decharge', 'recharge', 'vdw' +# class TestBACEexample(BaseDatasetTest): +# @pytest.fixture(scope="class", +# params = [(load_bace_example, ('complex',), (12,)), +# ]) +# def dataset(self, request): +# return super().dataset(request) + + +# class TestInvalidFiles(BaseDatasetTest): +# # can't get the list of list in data +# @pytest.fixture(scope="class", +# params = [(load_invalidfiles, (slice(None),), (6,)), +# ]) +# def dataset(self, request): +# return super().dataset(request) + + + From 12c777c825236cc4a1075c95b64a303a0bec5b93 Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 14:20:47 -0700 Subject: [PATCH 6/7] rewrite GitHub actions CI workflow for speed - speed up CI by excluding some macOS jobs - change CI to not use conda - removed conda from CI workflow to speed it up - use standard setup-python action - alchemtest has no dependencies so this should speed up CI - mark worflow FAIL if coverage errors --- .github/workflows/CI.yaml | 49 ++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 181bfeb..17b78f8 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -13,6 +13,10 @@ on: # (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule) - cron: "0 0 * * *" +concurrency: + group: "${{ github.ref }}-${{ github.head_ref }}" + cancel-in-progress: true + jobs: test: name: Test on ${{ matrix.os }}, Python ${{ matrix.python-version }} @@ -21,9 +25,24 @@ jobs: matrix: os: [macOS-latest, ubuntu-latest, windows-latest] python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] + exclude: + - os: macOS-latest + python-version: 3.6 + - os: macOS-latest + python-version: 3.7 + - os: macOS-latest + python-version: 3.8 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Display Python version + run: python -c "import sys; print(sys.version)" - name: Additional info about the build shell: bash @@ -32,28 +51,14 @@ jobs: df -h ulimit -a - - # More info on options: https://github.com/conda-incubator/setup-miniconda - - uses: conda-incubator/setup-miniconda@v2 - with: - python-version: ${{ matrix.python-version }} - environment-file: devtools/conda-envs/test_env.yaml - - channels: conda-forge,defaults - - activate-environment: test - auto-update-conda: false - auto-activate-base: false - show-channel-urls: true + - name: Install pytest, pytest plugins + run: | + python -m pip install wheel + python -m pip install pytest pytest-cov pytest-pep8 - name: Install package - - # conda setup requires this special shell - shell: bash -l {0} run: | - python -m pip install . --no-deps - conda list - + python -m pip install . - name: Run tests @@ -66,6 +71,8 @@ jobs: - name: CodeCov uses: codecov/codecov-action@v1 with: + name: codecov-${{ matrix.os }}-py${{ matrix.python-version }} file: ./coverage.xml flags: unittests - name: codecov-${{ matrix.os }}-py${{ matrix.python-version }} + fail_ci_if_error: true + From fd5ca13b18050bafecdb59b8cead05bcc2a10c10 Mon Sep 17 00:00:00 2001 From: Oliver Beckstein Date: Thu, 29 Jul 2021 12:28:50 -0700 Subject: [PATCH 7/7] configure coverage --- .coveragerc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..349ec12 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,21 @@ +[run] +branch = True +omit = + # omit all tests + src/alchemtest/tests/* + # omit the versioneer-installed _version.py + src/alchemtest/_version.py + +[report] +exclude_lines = + # omit lines marked with: # pragma: no cover + pragma: no cover + + # Don't complain about missing debug-only code: + def __unicode__ + def __repr__ + + # Don't complain if tests don't hit defensive assertion code: + raise AssertionError + raise NotImplementedError +