Days 10–12 of the 100 Days of Code
TalkPython course is dedicated to unit
pytest, and is a foison of information. Prior to this, I had
very little experience with
pytest but found it less intuitive than the
language itself, and somewhat obscure—at least at first. I think, however, this
was because of trying to concinnate the actual tests—much like I would any
program—rather than simply hardcoding the input and expected output of a
function's given test with the
parametrize decorator. Instead, I would
essentially try to rewrite the function logic differently to reproduce the
desired behaviour. This, however, is counterintuitive because I'm introducing
another possibility for faulty logic, albeit in the test, so if the tests pass
but both models are flawed, I'd never know. On top of which, I was testing a
command-line driven app, so figuring out how to write tests for
input required additional 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. Nonetheless, what I want to share 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.
Not as easy as advertised!
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
collect_ignore_glob in my
This, too, came up short. I then thought I'd settle for invoking
--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, set an
omit option, and alas—it worked!
Here's what you need in your
setup.cfg if you run into a similar situation:
[coverage:run] omit = .env/*
Save to your project root, and
pytest will omit
.env directory contents
from 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
__main__ Pythonic problem:
[coverage:report] exclude_lines = if __name__ == .__main__.:
If not already using
pytest, I recommend trying it with a personal project.
Some benefit may be derived from this integral component of test-driven
development. Besides which, many software development life cycles incorporate
testing, so the experience could prove useful.