Not as easy as advertised!

Days 10–12 of the 100 Days of Code course from TalkPython is dedicated to unit testing with pytest, and has been a plenitude of information. Prior to this, I had very little experience with pytest and found it less intuitive than the language itself—at least at first. And I think this was due to trying to sophisticate the actual tests; rather than hardcoding the input and expected output of a given test for a function with the parametrize decorator, I would essentially try to rewrite the function logic in a different way to reproduce the expected output. This, however, is counterintuitive because you're introducing another possibility for faulty logic, albeit in your test, so if your tests pass but both models are flawed, you'd never know. That, and I was testing a command-line driven app, so figuring out how to write tests for sys.argv input took a bit of understanding—and I'm still not entirely sure I've written the most efficient tests but I did achieve complete coverage so I'm satisfied with the result. What I want to share, though, is the apparent discrepancy between the advertised way to ignore or exclude directories in your project repository, and what's actually needed to get it done.

First, the pytest docs suggest that pytest will "intelligently identify and ignore a virtualenv"—but this wasn't happening for me. So I tried the norecursedirs in my setup.cfg to no avail. Next, I took a chance with collect_ignore and collect_ignore_glob in my conftest.py. This, too, came up short. I then thought I'd settle for invoking pytest with the --ignore option and was duly mystified when that proceeded to fail. Unwilling to accept defeat, I returned to my setup.cfg, drew up a [coverage:run] section, and threw in omit—alas, it worked! Here's what you need in your setup.cfg if you run into the same problem:

[coverage:run]
omit =
     .env/*

Save it in your project root, and pytest will omit the .env directory contents from its testing. Obviously, you can specify any number of locations, and replace .env with your Python virtual environment directory name.

Tangentially, if—like me—you're obstinately chasing 100% coverage, you can add the following to circumvent the Pythonic problem:

[coverage:report]
exclude_lines =
     if __name__ == .__main__.:

If you haven't already been using pytest, I highly recommend you give it a go!

pytest coverage report

Comments

comments powered by Disqus