00:00 In the previous lesson, I gave an overview of the course. In this lesson, I’ll introduce you to writing tests with pytest. Want a little challenge? Make an estimate of the number of times I say the word test in this course.
Take a guess. See how you’ll do. Testing, testing! Is this thing on? A little Joan Rivers call-out for the old folks in the room. pytest is a third-party library, and as such, you should be using a virtual environment and using
pip to install it.
Nothing tricky here, simply run
pip install with the
pytest library, and you’ll be all set. To get started, let me first show you what a typical test case looks like if you’re using the standard library’s
You have some code and then assert an expected value, with the test passing if the assertion passes. The
TestCase base class has a dozen different assertion methods in it, which you get by inheriting. In this sample code, I’m using just one of them,
If the value passed into the assertion method resolves to
True, then the assertion is valid, and in this case, the test passes. Of course, in the real world, you’re likely to be passing in an actual value or doing a comparison operation rather than just the
False keywords. But you get the idea.
01:55 You’ll notice that there is a fair amount of boilerplate here. These are the shortest possible tests, and in order to use them, you have to import the module and declare a class. Let’s run these in the bottom window.
That’s because the testing tools look in subdirectories for files beginning with the name
test. So I’ve got sample code divided up by directory so that I’m only running one collection at a time.
02:50 This tells me two tests were found: one ran, and one failed. The rest of the output is the details of the failure. It tells me what line of code was the source of the assertion failure and why it failed.
When you run the command, it looks for files starting with the name
test and runs any function inside the file that starts with the name
test. Second, no need for a class to inherit from. Third—and this is the biggest difference—rather than using a parent class’s assorted assert methods, pytest just uses the
Anything that evaluates to
False in an assertion is considered a failed test. In case you haven’t used the
assert keyword before, one quick word of warning: it isn’t a function. Don’t put parentheses like you’re calling a function. That causes problems. As
assert is just a keyword, any parentheses you use would get treated as a tuple, and non-empty tuples are considered true.
04:12 So you can end up asserting something completely different than what you were trying to assert. More recent versions of Python will warn you if you do this, but older versions don’t, so be very careful. All right, let’s run this.
That’s a lot. Let me just scroll up here.
pytest starts out by telling you what it is running. You’ll see here that I’m on a Mac—that’s that
pytest-7.1.1, with the default plugins installed. It then tells you what directory it is using to search for tests, how many tests it found, and what file they were found in. Like
unittest, it has an indicator for each test, but in this case, it’s divided up by the file. Also like
F means failed, and the dot means success. After that, you get a list of all the failures that happened in your test suite.
Each failure tells you what function had the problem, what line it was, and what the error was. In this case, it’s
assert False. At the bottom here, there is a quick summary. It feels redundant because everything more or less fits on the screen, but if you’ve got lots of failed tests, these lines at the bottom can be rather helpful. Because I like failure, let’s do that again. This time I’m going to use the
-q argument to
And this third example uses the
in operator to check if
37 is in the dictionary that is created by the dictionary comprehension in the rest of this blurb. This example is also a good representation of the just ‘cause you can doesn’t mean you should school of coding.
There is another way of grouping your tests together, which is you can label them with marks. When you call
pytest on the command line, you can pass in an argument so that only the tests with a certain mark get run.
07:30 Marking a function requires two things. First, you use a decorator to indicate the mark on the test function. And second, you have to register the mark. I’ll show you that second part in a minute.
I have two tests in here, each of which have some marks. You can apply multiple decorator marks to a function so that it can be a member of multiple groups. When testing large suites of software, it is often common to have a smoke test, a set of tests that can be run quickly but provide a decent amount of coverage, and then a full regression test that might take a lot longer. Here I’ve marked the
test_smoke() function with both the
smoke mark and the
regression mark, so this function gets run with either of those marks.
test_more() function only gets run in the regression case. This is probably overkill as, in all likelihood, the regression suite would just be all of the tests, and so you wouldn’t need to mark it explicitly.
Other configuration can go in this file as well, but here I’m showing the creation of the two marks I used in the test functions before. If you fail to do this registration, you’ll get a warning message if try to call
pytest with marks.
Become a Member to join the conversation.