-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CI pipeline #28
base: master
Are you sure you want to change the base?
Add CI pipeline #28
Changes from all commits
607ef69
d66dff0
ea48cb3
4bafcbf
9bdf505
05452f9
e567529
38bd679
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
name: Test NeuralForceField package | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
# python-version: ["pypy3.10", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] | ||
python-version: ["3.10"] | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
- name: Display Python version | ||
run: python -c "import sys; print(sys.version)" | ||
- name: Install basics | ||
run: python -m pip install --upgrade pip setuptools wheel | ||
- name: Install package | ||
run: python -m pip install . | ||
# - name: Install linters | ||
# run: python -m pip install flake8 mypy pylint | ||
# - name: Install documentation requirements | ||
# run: python -m pip install -r docs/requirements.txt | ||
# - name: Test with flake8 | ||
# run: flake8 polymethod | ||
# - name: Test with mypy | ||
# run: mypy polymethod | ||
# - name: Test with pylint | ||
# run: pylint polymethod | ||
- name: Test with pytest | ||
run: | | ||
pip install pytest pytest-cov | ||
pytest nff/tests --doctest-modules --junitxml=junit/test-results-${{ matrix.python-version }}.xml --cov=nff --cov-report=xml --cov-report=html | ||
- name: Upload pytest test results | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: pytest-results-${{ matrix.python-version }} | ||
path: junit/test-results-${{ matrix.python-version }}.xml | ||
if: ${{ always() }} | ||
# - name: Test documentation | ||
# run: sphinx-build docs/source docs/build |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
import os | ||
import pytest | ||
import torch | ||
|
||
torch.set_num_threads(int(os.getenv("OMP_NUM_THREADS", 1))) | ||
|
||
|
||
def pytest_addoption(parser): | ||
parser.addoption("--device", action="store", default="cpu", help="Whether to use the CPU or GPU for the tests") | ||
|
||
|
||
@pytest.fixture | ||
def device(request): | ||
return request.config.getoption("--device") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,8 @@ | |
import numpy as np | ||
from ase import Atoms | ||
|
||
import pytest | ||
|
||
Comment on lines
+8
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be a bit out of touch, but is there an advantage to using pytest over unittest? I normally just use unittest. While I know that pytest serves a similar function and I've heard of it, I'm unfamiliar with formatting and syntax differences between the two and which integrates better with GitHub CI/CD. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I never looked into it too much, because it "just works" and pytest is the most commonly used testing system, but to my understanding the advantages are:
|
||
from nff.io.ase import AtomsBatch | ||
|
||
|
||
|
@@ -19,6 +21,8 @@ def compare_dicts(d1: dict, d2: dict): | |
for key, value in d1.items(): | ||
if isinstance(value, dict): | ||
compare_dicts(value, d2[key]) | ||
elif isinstance(value, str): | ||
assert value == d2[key] | ||
elif isinstance(value, Iterable): | ||
assert np.allclose(value, d2[key]) | ||
else: | ||
|
@@ -47,10 +51,17 @@ def get_ethanol(): | |
return Atoms(nxyz[:, 0].astype(int), positions=nxyz[:, 1:]) | ||
|
||
|
||
# @ut.skip("skip this for now") | ||
@pytest.mark.usefixtures("device") # Ensure the fixture is accessible | ||
class TestAtomsBatch(ut.TestCase): | ||
def setUp(self): | ||
self.ethanol = get_ethanol() | ||
# Access the device value from the pytest fixture | ||
self.device = self._test_fixture_device | ||
|
||
@pytest.fixture(autouse=True) | ||
def inject_device(self, device): | ||
# Automatically set the fixture value to an attribute | ||
self._test_fixture_device = device | ||
|
||
@ut.skip("skip this for now") | ||
def test_AtomsBatch(self): | ||
|
@@ -111,7 +122,7 @@ def test_AtomsBatch(self): | |
] | ||
) | ||
|
||
atoms_batch = AtomsBatch(self.ethanol, cutoff=2.5) | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=2.5, device=self.device) | ||
atoms_batch.update_nbr_list() | ||
|
||
G1 = nx.from_edgelist(expected_nbrlist_cutoff_2dot5) | ||
|
@@ -120,21 +131,21 @@ def test_AtomsBatch(self): | |
assert nx.is_isomorphic(G1, G2) | ||
|
||
def test_get_batch(self): | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=5) | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=5, device=self.device) | ||
batch = atoms_batch.get_batch() | ||
|
||
assert "nxyz" in batch | ||
|
||
def test_from_atoms(self): | ||
atoms_batch = AtomsBatch.from_atoms(self.ethanol, cutoff=2.5) | ||
atoms_batch = AtomsBatch.from_atoms(self.ethanol, cutoff=2.5, device=self.device) | ||
|
||
# ensure atomic numbers, positions, and cell are the same | ||
assert np.allclose(atoms_batch.get_atomic_numbers(), self.ethanol.get_atomic_numbers()) | ||
assert np.allclose(atoms_batch.get_positions(), self.ethanol.get_positions()) | ||
assert np.allclose(atoms_batch.get_cell(), self.ethanol.get_cell()) | ||
|
||
def test_copy(self): | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=2.5) | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=2.5, device=self.device) | ||
atoms_batch.get_batch() # update props | ||
atoms_batch_copy = atoms_batch.copy() | ||
|
||
|
@@ -154,7 +165,7 @@ def test_copy(self): | |
assert atoms_batch.requires_large_offsets == atoms_batch_copy.requires_large_offsets | ||
|
||
def test_fromdict(self): | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=2.5) | ||
atoms_batch = AtomsBatch(self.ethanol, cutoff=2.5, device=self.device) | ||
ab_dict = atoms_batch.todict(update_props=True) | ||
ab_from_dict = AtomsBatch.fromdict(ab_dict) | ||
|
||
|
@@ -183,6 +194,7 @@ def test_fromdict(self): | |
compare_dicts(ab_dict_props, ab_dict_again_props) | ||
|
||
|
||
@pytest.mark.usefixtures("device") # Ensure the fixture is loaded | ||
class TestPeriodic(ut.TestCase): | ||
def setUp(self): | ||
nxyz = np.array( | ||
|
@@ -205,9 +217,15 @@ def setUp(self): | |
[0.0, 0.0, 5.51891759], | ||
] | ||
) | ||
self.quartz = AtomsBatch(nxyz[:, 0].astype(int), positions=nxyz[:, 1:], cell=lattice, pbc=True) | ||
|
||
def test_ase(self): | ||
self.quartz = AtomsBatch(nxyz[:, 0].astype(int), positions=nxyz[:, 1:], cell=lattice, pbc=True, | ||
device=self._test_fixture_device) | ||
|
||
@pytest.fixture(autouse=True) | ||
def inject_device(self, device): | ||
# Automatically set the fixture value to an attribute | ||
self._test_fixture_device = device | ||
|
||
def test_print(self): | ||
print(self.quartz) | ||
|
||
def test_nbrlist(self): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure that we want to make this change... I believe the
_ax
files are modified versions from a former student (Simon Axelrod) and they may be out-of-date.This duplicate code is one of many issues in NFF... I remember at one point that Simon suggested doing away with those versions entirely or integrating them with the main files, but they work for chemistry I'm less familiar with (excited states) and Simon didn't have time to migrate and update the code himself. I think I will open a specific issue and see if I can recruit him to check changes that we make.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspected something like we have already discussed concerning deprecated code might be going on with these
_ax
files. I anyway changed the import here, becauseIf this test ever makes any issues, because the
_ax
files make some problems or we remove them, I would say we can look into removing this test or adapting it to the current code base?