Testing with noxΒΆ

The epifx testing suite uses the pytest framework and the nox automation tool. The test cases are contained in the ./tests directory, and can be run with:

nox

The noxfile.py contents are shown below, and include targets that check whether the documentation in ./doc builds correctly.

import nox
import os
from pathlib import Path
import shutil


# Ensure that nox supports session tags.
nox.needs_version = ">=2022.8.7"


@nox.session()
def build(session):
    """Build source and binary (wheel) packages."""
    build_dir = Path('build')
    if build_dir.exists():
        shutil.rmtree(build_dir)

    pkg_dir = Path('.nox-build')
    if pkg_dir.exists():
        shutil.rmtree(pkg_dir)

    session.install('build')
    session.run('python', '-m', 'build', '--outdir', pkg_dir,
                '-C--global-option=-q')

    # On local machines, copy the wheel to a known directory that can be used
    # by upstream packages.
    if os.environ.get('GITLAB_CI') == 'true':
        print('Detected GitLab CI, will not copy package')
    else:
        packages = sorted(pkg_dir.glob('*.whl'))
        if len(packages) != 1:
            raise ValueError(f'Found {len(packages)} packages')
        package = packages[0]
        dest_dir = Path.home() / '.ci-packages'
        dest_dir.mkdir(parents=True, exist_ok=True)
        print(f'Copying {package} to {dest_dir}')
        shutil.copy(package, dest_dir)


def _find_pypfilt():
    """Locate the most recent pypfilt wheel."""
    pkg_dir = Path.home() / '.ci-packages'
    packages = sorted(pkg_dir.glob('pypfilt-*.whl'))
    if len(packages) == 0:
        raise ValueError(f'Cannot find pypfilt wheel in {pkg_dir}')
    return packages[-1]


@nox.session()
def tests(session):
    """Run test cases and record the test coverage."""
    session.install('pytest', 'pytest-cov')
    session.install(_find_pypfilt())
    session.install('.')
    # Run the test cases and report the test coverage.
    package = 'epifx'
    session.run(
        'python3', '-bb', Path(session.bin) / 'pytest',
        f'--cov={package}',
        '--pyargs', package, './tests', './doc',
        *session.posargs,
        env={
            # NOTE: Do not import sphinx_rtd_theme in doc/conf.py.
            'READTHEDOCS': 'True',
        })
    # Ensure that regression test outputs have not changed.
    session.run('git', 'diff', '--exit-code', '--stat', 'tests/',
                external=True)


@nox.session()
def docs(session):
    """Build the HTML documentation."""
    session.install('-r', 'requirements-rtd.txt')
    session.run('sphinx-build', '-W', '-b', 'html',
                './doc', './doc/build/html')


@nox.session(tags=['check'])
def ruff(session):
    """Check code for linter warnings."""
    session.install('ruff')
    session.run('ruff', 'src', 'tests')


@nox.session(tags=['check'])
def blue(session):
    """Check code formatting."""
    session.install('blue')
    session.run('blue', '--check', '--diff', '--color', 'src', 'tests')