Skip to content

Use pytest-doctestplus to skip some inline doctests - #1790

Merged
seisman merged 4 commits into
mainfrom
skip-doctest
Mar 8, 2022
Merged

Use pytest-doctestplus to skip some inline doctests#1790
seisman merged 4 commits into
mainfrom
skip-doctest

Conversation

@seisman

@seismanseisman commented Mar 7, 2022

Copy link
Copy Markdown
Member

Description of proposed changes

We're adding more and more inline code examples in function docstrings as tracked in issue #1686. We don't want these new doctests slow down our CI, so we skip these doctests using the # doctest: +SKIP directive. Here is an example doctest in grdlandmask:

 >>> import pygmt # doctest: +SKIP
>>> # Create a landmask grid with an x-range of 125 to 130,
>>> # and a y-range of 30 to 35
>>> landmask = pygmt.grdlandmask(
... spacing=1, region=[125, 130, 30, 35]
... ) # doctest: +SKIP

As you can see, there are many downsides for this kind of doctests:

  1. # doctest: +SKIP only works for one single line, so we have to add # doctest: +SKIP many times
  2. # doctest: +SKIP has 18 characters. So even a short code like landmask = pygmt.grdlandmask(spacing=1, region=[125, 130, 30, 35]) must be split into multiple lines
  3. there is no simple way to run these tests

In this PR, the pytest-doctestplus plugin is used to solve the problems above. For each module, we just need to define an internal variable __doctest_skip__, which contains a list of functions/classes whose tests should be skipped.
See the changes in pygmt/src/grdlandmask.py as an example and also the official documentation of pytest-doctestplus.

As you can see, it solves the problems 1 and 2 above.

BeforeAfter
imageimage

For problem 3, there is still no easy way, but I think it's possible to comment the __doctest_skip__ line, run the tests, and then revert the changes.

@seisman

Copy link
Copy Markdown
MemberAuthor

Ping @meghanrjones @weiji14@willschlitzer@michaelgrund for comments on the new doctest method.

@seismanseisman added the maintenance Boring but important stuff for the core devs label Mar 7, 2022
@seismanseisman added this to the 0.6.0 milestone Mar 7, 2022

@weiji14weiji14 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great find! Should have found this earlier 😆 I have one suggestion in regard to Problem 3 below.

Comment threadpyproject.toml Outdated
[tool.pytest.ini_options]
minversion = "6.0"
addopts = "--verbose --durations=0 --durations-min=0.2 --doctest-modules --mpl --mpl-results-path=results"
addopts = "--verbose --durations=0 --durations-min=0.2 --doctest-plus --mpl --mpl-results-path=results"

@weiji14weiji14Mar 7, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For problem 3, there is still no easy way, but I think it's possible to comment the doctest_skip line, run the tests, and then revert the changes.

Actually, from reading the doctest-plus docs (https://github.com/astropy/pytest-doctestplus/tree/v0.12.0#setup-and-configuration), it says:

Using pytest's built-in --doctest-modules option will override the behavior of this plugin, even if doctest_plus = enabled in setup.cfg, and will cause the default doctest plugin to be used. However, if for some reason both --doctest-modules and --doctest-plus are given, the pytest-doctestplus plugin will be used, regardless of the contents of setup.cfg.

So maybe we just need to edit the Makefile, and have have a make doctest command that uses --doctest-modules instead of doctest-plus to run all of these doctests? Could also setup a CI to have it run weekly if needed.

@seismanseismanMar 7, 2022

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. I removed the --doctest-plus option from pyproject.toml, and added it to make test command. I also the make fulltest target with the --doctest-modules option (I think the make doctest command is misleading).

Now, running make test collects 541 tests, and running make fulltest collects 542 tests. The extra one in make fulltest comes is the grdlandmask doctest.

@seisman
seisman marked this pull request as ready for review March 7, 2022 14:25

@maxrjonesmaxrjones left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!

I think the contributors guide should provide information about adding inline examples/doctests including how to skip tests using __doctest_skip__ and run the full tests using make fulltest or pytest pygmt/src/<module>.py --doctest-modules, but this could be handled in a separate PR.

@weiji14weiji14 added the final review call This PR requires final review and approval from a second reviewer label Mar 7, 2022
@seisman

seisman commented Mar 8, 2022

Copy link
Copy Markdown
MemberAuthor

pytest pygmt/src/.py --doctest-modules

I added the --doctest-modules option back to pytest's default options so that people don't have to give the --doctest-modules option when running tests in a single module.

Now here are three different ways to run tests:

  • make test: use the default pytest options (i.e., --doctest-modules --doctest-plus), so that all tests and some doctests will run
  • make fulltest: use --doctest-modules, all tests and all doctests will run
  • pytest pygmt/src/<module>.py: any doctests in the module will run

@seisman
seisman requested review from maxrjones and weiji14March 8, 2022 02:03
@seismanseisman removed the final review call This PR requires final review and approval from a second reviewer label Mar 8, 2022
@seisman
seisman merged commit d24c0a6 into mainMar 8, 2022
@seisman
seisman deleted the skip-doctest branch March 8, 2022 03:01
sixy6e pushed a commit to sixy6e/pygmt that referenced this pull request Dec 21, 2022
…ols#1790)
* Use pytest-doctestplus to skip some inline doctests
* Install pytest-doctestplus in workflows
* Add the fulltest target to run all tests, including all doctests
@seismanseisman mentioned this pull request Jan 11, 2024
14 tasks
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenanceBoring but important stuff for the core devs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@seisman@maxrjones@weiji14