From 126dcf7c39b95a756b7a31c2112aee59fe795579 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Wed, 5 Aug 2020 00:02:40 +0200 Subject: [PATCH] Include doctests in the test suite - use xdoctest to validate all code snippets in docstrings - add xdoctest to the nox session "test" --- noxfile.py | 24 ++++++++++++++++++---- poetry.lock | 32 +++++++++++++++++++++++++++-- pyproject.toml | 1 + src/urban_meal_delivery/__init__.py | 8 +++++++- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/noxfile.py b/noxfile.py index 8fdfc1f..f60687d 100644 --- a/noxfile.py +++ b/noxfile.py @@ -13,6 +13,8 @@ MAIN_PYTHON = '3.8' # Keep the project is forward compatible. NEXT_PYTHON = '3.9' +PACKAGE_IMPORT_NAME = 'urban_meal_delivery' + # Path to the *.py files to be packaged. PACKAGE_SOURCE_LOCATION = 'src/' @@ -48,6 +50,8 @@ def format_(session): Otherwise, they are interpreted as paths the formatters work on recursively. """ _begin(session) + # The formatting tools do not require the developed + # package be installed in the virtual environment. _install_packages(session, 'autoflake', 'black', 'isort') # Interpret extra arguments as locations of source files. locations = session.posargs or SRC_LOCATIONS @@ -78,6 +82,8 @@ def lint(session): Otherwise, they are interpreted as paths the linters work on recursively. """ _begin(session) + # The linting tools do not require the developed + # package be installed in the virtual environment. _install_packages( session, 'flake8', @@ -122,13 +128,15 @@ def lint(session): def test(session): """Test the code base. - Runs the unit and integration tests (written with pytest). + Runs the unit and integration tests with pytest and + validate that all code snippets in docstrings work with xdoctest. If no extra arguments are provided, the entire test suite is exexcuted and succeeds only with 100% coverage. If extra arguments are provided, they are - forwarded to pytest without any changes. + forwarded to pytest and xdoctest without any changes. + xdoctest ignores arguments it does not understand. """ # Re-using an old environment is not so easy here as # `poetry install --no-dev` removes previously installed packages. @@ -139,9 +147,12 @@ def test(session): ) _begin(session) - # Install only the non-develop dependencies and the testing tool chain. + # The testing tools require the developed package and its + # non-develop dependencies be installed in the virtual environment. session.run('poetry', 'install', '--no-dev', external=True) - _install_packages(session, 'pytest', 'pytest-cov') + _install_packages( + session, 'packaging', 'pytest', 'pytest-cov', 'xdoctest[optional]', + ) # Interpret extra arguments as options for pytest. # They are "dropped" by the hack in the pre_merge() function # if this function is run within the "pre-merge" session. @@ -154,7 +165,12 @@ def test(session): '--cov-report=term-missing:skip-covered', PYTEST_LOCATION, ) + session.run('pytest', '--version') session.run('pytest', *args) + # For xdoctest, the default arguments are different from pytest. + args = posargs or [PACKAGE_IMPORT_NAME] + session.run('xdoctest', '--version') + session.run('xdoctest', '--quiet', *args) # --quiet => less verbose output @nox.session(name='pre-commit', python=MAIN_PYTHON, venv_backend='none') diff --git a/poetry.lock b/poetry.lock index d4b0b02..78a265a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -137,7 +137,7 @@ version = "7.1.2" [[package]] category = "dev" description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" +marker = "sys_platform == \"win32\" or platform_system == \"Windows\" or platform_system == \"Windows\"" name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" @@ -885,8 +885,32 @@ optional = false python-versions = "*" version = "1.12.1" +[[package]] +category = "dev" +description = "A rewrite of the builtin doctest module" +name = "xdoctest" +optional = false +python-versions = "*" +version = "0.13.0" + +[package.dependencies] +six = "*" + +[package.dependencies.Pygments] +optional = true +version = "*" + +[package.dependencies.colorama] +optional = true +version = "*" + +[package.extras] +all = ["six", "pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "pygments", "colorama"] +optional = ["pygments", "colorama"] +tests = ["pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11"] + [metadata] -content-hash = "899f376a54c187e41392fb83831a59926668b662bfb32004f4a0964c1202698c" +content-hash = "79e46e67260312ba1b227f7717d0ba781a6ad5df352f83fe6e1b72a98ad1ec5b" lock-version = "1.0" python-versions = "^3.8" @@ -1311,3 +1335,7 @@ wemake-python-styleguide = [ wrapt = [ {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, ] +xdoctest = [ + {file = "xdoctest-0.13.0-py2.py3-none-any.whl", hash = "sha256:de861fd5230a46bd26c054b4981169dd963f813768cb62b62e104e4d2644ac94"}, + {file = "xdoctest-0.13.0.tar.gz", hash = "sha256:4f113a430076561a9d7f31af65b5d5acda62ee06b05cb6894264cb9efb8196ac"}, +] diff --git a/pyproject.toml b/pyproject.toml index 5ee058e..200a42a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,7 @@ wemake-python-styleguide = "^0.14.1" # flake8 plug-in packaging = "^20.4" # used to test the packaged version pytest = "^6.0.1" pytest-cov = "^2.10.0" +xdoctest = { version="^0.13.0", extras=["optional"] } [tool.poetry.scripts] umd = "urban_meal_delivery.console:main" diff --git a/src/urban_meal_delivery/__init__.py b/src/urban_meal_delivery/__init__.py index 5a68f43..425f95f 100644 --- a/src/urban_meal_delivery/__init__.py +++ b/src/urban_meal_delivery/__init__.py @@ -1,4 +1,10 @@ -"""Source code for the urban-meal-delivery research project.""" +"""Source code for the urban-meal-delivery research project. + +Example: + >>> import urban_meal_delivery as umd + >>> umd.__version__ != '0.0.0' + True +""" from importlib import metadata as _metadata