Skip to content

Latest commit

 

History

History
96 lines (67 loc) · 4.46 KB

File metadata and controls

96 lines (67 loc) · 4.46 KB

Testing

"If debugging is the process of removing bugs, then programming must be the process of putting them in."

-- Edsger Dijkstra

But there are ways to make it easier to find bugs and prevent the introduction of new ones. This is where testing comes in. There are two types that I often use (discussed below):

We also the discuss the use of GitHub Actions. for continuous integration (CI), namely the software practice of committing code to a shared repository where the project is built and tested.

Assertion tests

Assertion tests are lightweight Boolean checks that you can include in your code to check that certain conditions are met. For example, you can check that the input/output is what you expect. If the condition is not met, the test will fail and code execution will stop.

For example, for :class:`pydevtips.fftconvolve.RFFTConvolve` we check that the input is indeed real:

def __init__(self, filt, length) -> None:
    assert np.isreal(filt).all(), "Filter must be real."
    ...

Unit tests

Unit testing is a method to test small pieces of code, usually functions. With a large code base, having unit tests can ensure you don't break core functionality when you make changes.

In Python, there is the pytest package that can be used to write and run unit tests. A common practice is to create a tests folder in the root of your project and write your tests there. The test functions should begin with test_ so that pytest can find them.

For example, for our FFT convolvers -- :class:`pydevtips.fftconvolve.RFFTConvolve` and :class:`pydevtips.fftconvolve.FFTConvolve` -- we can write unit tests to check that they are consistent with :py:func:`numpy.convolve`, as done in this script.

To run the unit tests:

# install in virtual environment (if not done already)
(project_env) pip install pytest

# run tests
(project_env) pytest

To run a specific test:

# inside virtual environment
(project_env) pytest tests/test_fftconvolve.py::test_fft

Continuous integration with GitHub Actions

Continuous integration (CI) is the practice of automatically building and testing code whenever a change is made to the codebase. This is useful to ensure that the codebase is always in a working state.

With GitHub Actions, you can set up a workflow that will run, e.g. on every push to the repository. This workflow can build the package, run the unit tests, build the documentions, etc for different versions of Python and operating systems.

Workflows are defined in YAML files in the .github/workflows folder. For example, the workflow for this project is defined in this file. The workflow performs the following:

  • Triggers on pushes and pull requests to the main branch (code link).
  • Performs the test on all combinations of Python 3.8, 3.9, and 3.10 and operating systems Ubuntu, Windows, and macOS (code link).
  • Installs the package and its dependencies (code link).
  • Checks for code formatting and style and errors if it doesn't conform (code link). Make sure it matches the code formatting you've setup in your project, e.g. via :ref:`pre-commit hooks <Code formatting>`.
  • Runs the unit tests (code link).

More information on configuring GitHub Actions can be found in their documentation.