Skip to content

Commit

Permalink
Added reporting of code coverage by test suite.
Browse files Browse the repository at this point in the history
Code coverage by the test suite is measured via pyTest and its
pyTest-cov plug-in. The script `coverage.py` runs the coverage
test, renders the coverage report, and also creates the coverage
badge, unless that file already exists in the `tests` folder.
  • Loading branch information
john-hen committed May 20, 2021
1 parent be06a13 commit 79193dd
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 41 deletions.
Binary file added .coverage
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/develop/
/deploy/docs/
/deploy/dist/
/deploy/coverage/
/deploy/coverage.sqlite
/dist/
**/__pycache__
**/.pytest_cache
Expand Down
13 changes: 6 additions & 7 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ in Python, with added test coverage.

Find the full [documentation on Read-the-Docs][docs].

[![citation](https://zenodo.org/badge/263433787.svg)](https://zenodo.org/badge/latestdoi/263433787)
[![license](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![release](https://img.shields.io/pypi/v/kde-diffusion.svg)](https://pypi.python.org/pypi/kde-diffusion)
[![downloads](https://pepy.tech/badge/kde-diffusion)](https://pepy.tech/project/kde-diffusion)
[![documentation](https://readthedocs.org/projects/kde-diffusion/badge/?version=latest)](https://kde-diffusion.readthedocs.io/en/latest/?badge=latest)

[paper]: https://dx.doi.org/10.1214/10-AOS799
[kde1d]: https://mathworks.com/matlabcentral/fileexchange/14034
[kde2d]: https://mathworks.com/matlabcentral/fileexchange/17204
[docs]: https://kde-diffusion.readthedocs.io


[![citation](https://zenodo.org/badge/263433787.svg)](https://zenodo.org/badge/latestdoi/263433787)
[![license](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![release](https://img.shields.io/pypi/v/kde-diffusion.svg)](https://pypi.python.org/pypi/kde-diffusion)
[![downloads](https://pepy.tech/badge/kde-diffusion)](https://pepy.tech/project/kde-diffusion)
![coverage](tests/coverage.svg?raw=true)
[![documentation](https://readthedocs.org/projects/kde-diffusion/badge/?version=latest)](https://kde-diffusion.readthedocs.io/en/latest/?badge=latest)
7 changes: 1 addition & 6 deletions deploy/build.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
"""Builds documentation and installation package."""
"""Builds the installation package."""
__license__ = 'MIT'

from subprocess import run
from pathlib import Path
from shutil import rmtree

root = Path(__file__).resolve().parent.parent

process = run(['sphinx-build', 'docs', 'deploy/docs'], cwd=root)
if process.returncode:
raise RuntimeError('Error while building documentation.')

process = run(['flit', 'build', '--format', 'wheel'], cwd=root)
if process.returncode:
raise RuntimeError('Error while building wheel.')
Expand Down
8 changes: 4 additions & 4 deletions deploy/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
from pathlib import Path
from shutil import rmtree

root = Path(__file__).absolute().parent.parent
root = Path(__file__).resolve().parent.parent

for folder in root.rglob('__pycache__'):
rmtree(folder)
rmtree(folder, ignore_errors=True)

for folder in root.rglob('.pytest_cache'):
rmtree(folder)

for folder in (root/'deploy'/'dist', root/'deploy'/'docs'):
rmtree(folder, ignore_errors=True)
for folder in ('docs', 'dist', 'coverage'):
rmtree(root/'deploy'/folder, ignore_errors=True)
24 changes: 24 additions & 0 deletions deploy/coverage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Measures code coverage by test suite."""
__license__ = 'MIT'


from subprocess import run
from pathlib import Path


here = Path(__file__).resolve().parent
root = here.parent
file = here/'coverage.sqlite'

run(['pytest', '--cov'], cwd=root)

print('Rendering coverage report.')
folder = (here/'coverage').relative_to(root)
run(['coverage', 'html', f'--directory={folder}'], cwd=root)

badge = root/'tests'/file.with_suffix('.svg').name
if badge.exists():
print('Coverage badge already exists.')
else:
print('Rendering coverage badge.')
run(['coverage-badge', '-f', '-o', str(badge)], cwd=root)
14 changes: 0 additions & 14 deletions deploy/notes.txt

This file was deleted.

3 changes: 1 addition & 2 deletions deploy/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from pathlib import Path

root = Path(__file__).resolve().parent.parent

process = run(['flit', 'publish', '--format', 'wheel'], cwd=root)
if process.returncode:
raise RuntimeError('Error while publishing to PyPI.')
raise RuntimeError('Error while publishing on PyPI.')
11 changes: 11 additions & 0 deletions deploy/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Steps to take when releasing a new version:
* Bump version number and enter current date in `__init__.py`.
* Add a dedicated commit for the version bump.
* Tag the commit with the version number, for example: `git tag -a v1.0.3`.
* Enter the release notes as an annotation.
* Push the commit (but not the tag): `git push origin main`.
* Check that documentation built successfully on Read-the-Docs.
* Publish on PyPI by running `deploy/publish.py`.
* Check that meta information is correct on PyPI.
* Then push the tag: `git push --tags`.
* Create a new release on GitHub and add the release notes.
10 changes: 10 additions & 0 deletions deploy/render.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Renders the documentation."""
__license__ = 'MIT'

from subprocess import run
from pathlib import Path

root = Path(__file__).resolve().parent.parent
process = run(['sphinx-build', 'docs', 'deploy/docs'], cwd=root)
if process.returncode:
raise RuntimeError('Error while rendering documentation.')
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ classifiers = [
'License :: OSI Approved :: MIT License']

[tool.flit.metadata.requires-extra]
test = ['pyTest']
doc = ['Sphinx', 'Sphinx-RTD-theme', 'reCommonMark']
doc = ['Sphinx', 'Sphinx-RTD-theme', 'MyST-parser', 'CommonMark']
test = ['pyTest', 'pyTest-cov', 'coverage-badge', 'flake8']

[tool.flit.metadata.urls]
Documentation = 'https://kde-diffusion.readthedocs.io'
Expand Down
21 changes: 21 additions & 0 deletions tests/coverage.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 19 additions & 3 deletions tests/test_1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def setup_module():
# Tests #
########################################

def test_density():
def test_reference():
x = reference['x']
N = reference['N']
assert N == len(x)
Expand All @@ -40,11 +40,27 @@ def test_density():
assert isclose(bandwidth, reference['bandwidth']).all()


def test_arguments():
(density, grid, bandwidth) = kde1d([-2, -1, 0, +1, +2]*20, 4)
assert len(grid) == 4
assert isclose(grid.min(), -2.4)
assert isclose(grid.max(), +1.2)
(density, grid, bandwidth) = kde1d([-2, -1, 0, +1, +2]*20, 4, 2)
assert isclose(grid.min(), -2)
assert isclose(grid.max(), +1)
try:
kde1d([-2, -1, 0, +1, +2]*10, 4)
raised_error = False
except ValueError:
raised_error = True
assert raised_error


########################################
# Main #
########################################

if __name__ == '__main__':
# Runs if test script is executed directly, and not via pytest.
setup_module()
test_density()
test_reference()
test_arguments()
44 changes: 41 additions & 3 deletions tests/test_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def setup_module():
# Test #
########################################

def test_density():
def test_reference():
x = reference['x']
y = reference['y']
N = reference['N']
Expand All @@ -47,11 +47,49 @@ def test_density():
assert isclose(bandwidth, reference['bandwidth']).all()


def test_arguments():
samples = [-2, -1, 0, +1, +2]
(density, grid, bandwith) = kde2d(samples*5, samples*5, 16)
assert len(grid[0]) == 16
assert len(grid[1]) == 16
assert isclose(grid[0].min(), -3.0)
assert isclose(grid[0].max(), +2.625)
assert isclose(grid[1].min(), -3.0)
assert isclose(grid[1].max(), +2.625)
(density, grid, bandwidth) = kde2d(samples*5, samples*5, 16, (2, None))
assert isclose(grid[0].min(), -2)
assert isclose(grid[0].max(), +1.75)
assert isclose(grid[1].min(), -3)
assert isclose(grid[1].max(), +2.625)
(density, grid, bandwidth) = kde2d(samples*5, samples*5, 16, (None, 2))
assert isclose(grid[0].min(), -3)
assert isclose(grid[0].max(), +2.625)
assert isclose(grid[1].min(), -2)
assert isclose(grid[1].max(), +1.75)
(density, grid, bandwidth) = kde2d(samples*5, samples*5, 16, 2)
assert isclose(grid[0].min(), -2)
assert isclose(grid[0].max(), +1.75)
assert isclose(grid[1].min(), -2)
assert isclose(grid[1].max(), +1.75)
try:
kde2d(samples, samples*2, 16)
raised_error = False
except ValueError:
raised_error = True
assert raised_error
try:
kde2d(samples, samples, 16)
raised_error = False
except ValueError:
raised_error = True
assert raised_error


########################################
# Main #
########################################

if __name__ == '__main__':
# Runs if test script is executed directly, and not via pytest.
setup_module()
test_density()
test_reference()
test_arguments()
13 changes: 13 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,16 @@ ignore =
E741
per-file-ignores =
kde_diffusion/__init__.py:F401


[pytest]
addopts = --verbose
testpaths =
tests
filterwarnings =
ignore::UserWarning


[coverage:run]
source = kde_diffusion/
data_file = deploy/coverage.sqlite

0 comments on commit 79193dd

Please sign in to comment.