Skip to content

Commit

Permalink
Use pytest 8 in CI (#1822)
Browse files Browse the repository at this point in the history
* Use bundled package in deployment tests

* Skip version check

* Remove some legacy fixtures

* Update deployment test environments

* Turn on CI

* Clean up

* Clean up

* Clean up

* Update docexample

* Run all doctests

* Update doctests

* Use 7.4 in deployment tests

* Cleanup

* Update config

* Fix call

* Revert changes to "conda" tests

* Ensure pytest 8 is used

* Update release history
  • Loading branch information
mattwthompson authored Jan 21, 2025
1 parent 9b1ab19 commit 74cfe94
Show file tree
Hide file tree
Showing 17 changed files with 69 additions and 113 deletions.
10 changes: 2 additions & 8 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@ on:
push:
branches:
- "main"
- "maintenance/.*"
pull_request:
branches:
- "main"
- "maintenance/.*"
schedule:
# Nightly tests run on main by default:
# Scheduled workflows run on the latest commit on the default or base branch.
# (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule)
- cron: "21 0 * * *"

defaults:
Expand Down Expand Up @@ -41,7 +36,6 @@ jobs:

env:
OE_LICENSE: ${{ github.workspace }}/oe_license.txt
PACKAGE: openff
PYTEST_ARGS: -r fE --tb=short -nauto
COV: --cov=openff/toolkit --cov-append --cov-report=xml

Expand Down Expand Up @@ -149,7 +143,7 @@ jobs:
PYTEST_ARGS+=" --ignore=openff/toolkit/_tests/test_examples.py"
PYTEST_ARGS+=" --ignore=openff/toolkit/_tests/test_links.py"
if [[ "$GITHUB_EVENT_NAME" == "schedule" ]]; then
PYTEST_ARGS+=" --runslow"
PYTEST_ARGS+=" -m 'slow or not slow'"
fi
python -m pytest --durations=20 $PYTEST_ARGS $COV
Expand All @@ -160,7 +154,7 @@ jobs:

- name: Run notebooks in docs
if: ${{ matrix.rdkit == true && matrix.openeye == true }}
run: pytest -v --no-cov --nbval --ignore docs/_build/ docs/
run: python -m pytest -v --no-cov --nbval-lax docs/

- name: Run examples in docstrings
if: ${{ matrix.rdkit == true && matrix.openeye == true }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/beta_rc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
run: |
PYTEST_ARGS+=" --ignore=openff/toolkit/_tests/test_examples.py"
PYTEST_ARGS+=" --ignore=openff/toolkit/_tests/test_links.py"
PYTEST_ARGS+=" --runslow"
PYTEST_ARGS+=" -m 'slow or not slow'"
pytest $PYTEST_ARGS
- name: Run code snippets in docs
Expand Down
24 changes: 3 additions & 21 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
name: Examples

on:
push:
branches:
- "main"
- "maintenance/.+"
pull_request:
branches:
- "main"
- "maintenance/.+"
schedule:
- cron: "0 0 * * *"

Expand Down Expand Up @@ -66,24 +58,13 @@ jobs:
create-args: >-
python=${{ matrix.python-version }}
- name: Additional info about the build
run: |
uname -a
df -h
ulimit -a
- name: Make oe_license.txt file from GH org secret "OE_LICENSE"
env:
OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }}
run: |
echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE}
run: echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE}

- name: Install package
run: |
# Maybe remove the packaged openff-toolkit, installed as a dependency of openmmforcefields
# and/or Interchange
micromamba remove --force openff-toolkit-base
python -m pip install .
run: python -m pip install .

- name: Remove undesired toolkits
run: |
Expand All @@ -110,6 +91,7 @@ jobs:
python -c "from openff.toolkit.utils.toolkits import ${TK}_AVAILABLE; assert not ${TK}_AVAILABLE, '${TK} available'"
done
fi
- name: Environment Information
run: |
micromamba info
Expand Down
2 changes: 1 addition & 1 deletion devtools/conda-envs/openeye-examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dependencies:
# Toolkit-specific
- openeye-toolkits
# Test-only/optional/dev/typing/examples
- pytest
- pytest =8
- pytest-xdist
- pytest-rerunfailures
- pyyaml
Expand Down
2 changes: 1 addition & 1 deletion devtools/conda-envs/openeye.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies:
# Toolkit-specific
- openeye-toolkits
# Test-only/optional/dev/typing
- pytest
- pytest =8
- pytest-cov
- pytest-xdist
- pytest-rerunfailures
Expand Down
2 changes: 1 addition & 1 deletion devtools/conda-envs/rdkit-examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies:
# https://github.com/rdkit/rdkit/issues/7221 and https://github.com/rdkit/rdkit/issues/7583
- rdkit =2024
# Test-only/optional/dev/typing/examples
- pytest
- pytest =8
- pytest-xdist
- pytest-rerunfailures
- pyyaml
Expand Down
2 changes: 1 addition & 1 deletion devtools/conda-envs/rdkit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dependencies:
# https://github.com/rdkit/rdkit/issues/7221 and https://github.com/rdkit/rdkit/issues/7583
- rdkit !=2024.03.6,!=2024.03.5
# Test-only/optional/dev/typing
- pytest
- pytest =8
- pytest-cov
- pytest-xdist
- pytest-rerunfailures
Expand Down
2 changes: 1 addition & 1 deletion devtools/conda-envs/test_env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ dependencies:

- openeye-toolkits
# Test-only/optional/dev/typing
- pytest
- pytest =8
- pytest-cov
- pytest-xdist
- pytest-rerunfailures
Expand Down
4 changes: 4 additions & 0 deletions docs/releasehistory.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ Releases follow the `major.minor.micro` scheme recommended by [PEP440](https://w

- [PR #1981](https://github.com/openforcefield/openff-toolkit/pull/1981): Updates documentation to run quicker and use new features, including some in Interchange 0.4.

### Miscellaneous

- [PR #1822](https://github.com/openforcefield/openff-toolkit/pull/1922): Updates internal tests to use Pytest 8.

## 0.16.7

### Bugfixes
Expand Down
14 changes: 0 additions & 14 deletions openff/toolkit/_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
"""
Configuration file for pytest.
This adds the following command line options.
- runslow: Run tests marked as slow (default is False).
"""

import logging
Expand All @@ -20,16 +16,6 @@
pass


def pytest_configure(config):
"""
Initialization hook to register custom markers without a pytest.ini
More info: https://docs.pytest.org/en/latest/reference.html#initialization-hooks
"""
config.addinivalue_line(
"markers", "slow: marks tests as slow (deselect with `-m 'not slow'`)"
)


def untar_full_alkethoh_and_freesolv_set():
"""When running slow tests, we unpack the full AlkEthOH and FreeSolv test
sets in advance to speed things up.
Expand Down
16 changes: 8 additions & 8 deletions openff/toolkit/_tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ def run_script_str(script_str):
"""
with tempfile.TemporaryDirectory() as tmp_dir:
temp_file_path = pathlib.Path(tmp_dir, "temp.py").as_posix()

temp_file_path = (pathlib.Path(tmp_dir) / "temp.py").as_posix()
# Create temporary python script.
with open(temp_file_path, "w") as f:
f.write(script_str)
Expand All @@ -57,16 +56,17 @@ def find_example_scripts() -> list[str]:
example_file_paths : list[str]
List of full paths to python scripts to execute.
"""
# Count on the examples/ path being equivalently accessible as the README file
readme_file_path = _get_readme_path()

if readme_file_path is None:
if "site-packages" in __file__:
# This test file is being collected from the installed package, which
# does not provide the examples folder in the same location
return list()

examples_dir_path = pathlib.Path(_get_readme_path().parent, "examples")
examples_dir_path = pathlib.Path(__file__).parents[3] / "examples"

# Examples that require RDKit
rdkit_examples = {examples_dir_path / "conformer_energies/conformer_energies.py"}
rdkit_examples = {
examples_dir_path / "conformer_energies/conformer_energies.py",
}

example_file_paths = []
for example_file_path in examples_dir_path.glob("*/*.py"):
Expand Down
7 changes: 3 additions & 4 deletions openff/toolkit/_tests/test_forcefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ def test_parameterize_large_system(
force_field,
):
"""Test parameterizing a large system of several distinct molecules.
This test is very slow, so it is only run if the --runslow option is provided to pytest.
This test is very slow, so it is only run if the slow marker option is provided to pytest.
"""
box_file_path = get_data_file_path(
os.path.join("systems", "packmol_boxes", box)
Expand Down Expand Up @@ -1882,9 +1882,8 @@ def test_handlers_tracked_if_already_loaded(self):

plugins = load_handler_plugins()

assert (
len(plugins) > 0
), "Test assumes that some ParameterHandler plugins are available"
if len(plugins) == 0:
pytest.skip("Test assumes that some ParameterHandler plugins are available")

assert ForceField(load_plugins=False)._plugin_parameter_handler_classes == []
assert ForceField(load_plugins=True)._plugin_parameter_handler_classes == [
Expand Down
18 changes: 12 additions & 6 deletions openff/toolkit/_tests/test_links.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import pathlib
import re
from urllib.request import Request, urlopen

import pytest

from openff.toolkit._tests.utils import _get_readme_path


def find_readme_links() -> list[str]:
"""Yield all the links in the main README.md file.
Expand All @@ -14,16 +13,23 @@ def find_readme_links() -> list[str]:
readme_examples : list[str]
The list of links included in the README.md file.
"""
readme_file_path = _get_readme_path()

if readme_file_path is None:
if "site-packages" in __file__:
# This test file is being collected from the installed package, which
# does not provide the README file.
# Note that there will likely be a mis-bundled file
# $CONDA_PREFIX/lib/python3.x/site-packages/README.md, but this is not
# the toolkit's README file!
return list()

else:
readme_file_path = pathlib.Path(__file__).parents[3] / "README.md"
with open(readme_file_path.as_posix()) as f:
readme_content = f.read()

return re.findall("http[s]?://(?:[0-9a-zA-Z]|[-/.%:_])+", readme_content)
with open(readme_file_path.as_posix()) as f:
readme_content = f.read()

return re.findall("http[s]?://(?:[0-9a-zA-Z]|[-/.%:_])+", readme_content)


@pytest.mark.parametrize("readme_link", find_readme_links())
Expand Down
28 changes: 8 additions & 20 deletions openff/toolkit/_tests/test_toolkit_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"""

import os
import pathlib
import sys
import tempfile
Expand Down Expand Up @@ -944,14 +943,6 @@ def test_from_file_obj_smi_supports_stringio(self):
assert mol.name == "CHEMBL113"


@pytest.fixture(scope="class")
def tmpdir(request):
request.cls.tmpdir = tmpdir = tempfile.TemporaryDirectory()
with tmpdir:
yield
request.cls.tmpdir = None


def assert_is_ethanol_sdf(f):
assert f.readline() == "ethanol\n" # title line
f.readline() # ignore next two lines
Expand All @@ -973,12 +964,9 @@ def assert_is_ethanol_smiles(smiles):


class BaseToFileIO:
def get_tmpfile(self, name):
return os.path.join(self.tmpdir.name, name)

@pytest.mark.parametrize("format_name", ["SDF", "sdf", "sDf", "mol", "MOL"])
def test_to_file_sdf(self, format_name):
filename = self.get_tmpfile("abc.xyz")
def test_to_file_sdf(self, format_name, tmp_path):
filename = tmp_path / "abc.xyz"
self.toolkit_wrapper.to_file(ETHANOL, filename, format_name)
with open(filename) as f:
assert_is_ethanol_sdf(f)
Expand All @@ -999,8 +987,8 @@ def test_to_file_obj_sdf_with_bytesio(self):
self.toolkit_wrapper.to_file_obj(ETHANOL, f, "sdf")

@pytest.mark.parametrize("format_name", ["SMI", "smi", "sMi"])
def test_to_file_smi(self, format_name):
filename = self.get_tmpfile("abc.xyz")
def test_to_file_smi(self, format_name, tmp_path):
filename = tmp_path / "abc.xyz"
self.toolkit_wrapper.to_file(ETHANOL, filename, format_name)
with open(filename) as f:
assert_is_ethanol_smi(f)
Expand All @@ -1026,19 +1014,19 @@ def test_to_file_qwe_format_raises_exception(self):
self.toolkit_wrapper.to_file(ETHANOL, fileobj.name, "QWE")

@pytest.mark.parametrize("format_name", ["smi", "sdf", "mol"])
def test_to_file_when_the_file_does_not_exist(self, format_name):
filename = self.get_tmpfile("does/not/exist.smi")
def test_to_file_when_the_file_does_not_exist(self, format_name, tmp_path):
filename = tmp_path / "does/not/exist.smi"
with pytest.raises(OSError):
self.toolkit_wrapper.to_file(ETHANOL, filename, format_name)


@pytest.mark.usefixtures("init_toolkit", "tmpdir")
@pytest.mark.usefixtures("init_toolkit")
@requires_openeye
class TestOpenEyeToolkitToFileIO(BaseToFileIO):
toolkit_wrapper_class = OpenEyeToolkitWrapper


@pytest.mark.usefixtures("init_toolkit", "tmpdir")
@pytest.mark.usefixtures("init_toolkit")
@requires_rdkit
class TestRDKitToolkitToFileIO(BaseToFileIO):
toolkit_wrapper_class = RDKitToolkitWrapper
Expand Down
9 changes: 2 additions & 7 deletions openff/toolkit/topology/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -1688,12 +1688,7 @@ def from_pdb(
(24, 23, 29, 36)
(32, 31, 40, 42)
>>> [*top.hierarchy_iterator("residues")]
[HierarchyElement ('A', '1', ' ', 'ACE') of iterator 'residues' containing 6 atom(s),
HierarchyElement ('A', '2', ' ', 'SER') of iterator 'residues' containing 11 atom(s),
HierarchyElement ('A', '3', ' ', 'NME') of iterator 'residues' containing 6 atom(s),
HierarchyElement ('B', '1', ' ', 'ACE') of iterator 'residues' containing 6 atom(s),
HierarchyElement ('B', '2', ' ', 'CYS') of iterator 'residues' containing 11 atom(s),
HierarchyElement ('B', '3', ' ', 'NME') of iterator 'residues' containing 6 atom(s)]
[HierarchyElement ('A', '1', ' ', 'ACE') of iterator 'residues' containing 6 atom(s), HierarchyElement ('A', '2', ' ', 'SER') of iterator 'residues' containing 11 atom(s), HierarchyElement ('A', '3', ' ', 'NME') of iterator 'residues' containing 6 atom(s), HierarchyElement ('B', '1', ' ', 'ACE') of iterator 'residues' containing 6 atom(s), HierarchyElement ('B', '2', ' ', 'CYS') of iterator 'residues' containing 11 atom(s), HierarchyElement ('B', '3', ' ', 'NME') of iterator 'residues' containing 6 atom(s)]
Polymer systems can also be supported if ``_custom_substructures`` are
given as a ``dict[str, list[str]]``, where the keys are unique atom
Expand All @@ -1716,7 +1711,7 @@ def from_pdb(
... get_data_file_path("systems/test_systems/PE.pdb"),
... _custom_substructures=PE_substructs,
... )
"""
""" # noqa: E501
import io
import json

Expand Down
Loading

0 comments on commit 74cfe94

Please sign in to comment.