Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Using Subtests

00:00 In the previous lesson, I showed you how to use the skip decorator. In this lesson, I’ll show you how to use subtests to help parameterize your errors.

00:09 The beauty of using Python scripts to test your code is, well, it’s still Python. So far, you’ve seen some pretty linear stuff, but that doesn’t mean it has to be that way. For example, if you had a long list of values you wanted to check in your code, you could put them in a list and iterate over it, calling and asserting your code for each value. I sometimes do this with a list of tuples, where the first part of the tuples are the arguments to the function I’m testing, and the last item in the tuples is the expected answer.

00:39 The problem with this approach is not enough information gets provided when a failure happens. The stack trace will tell you which assertion failed, but how can you know which spot in the iterable caused the failure?

00:50 Before I knew about this next trick, I’d stick a print() in, and then go through it in pieces. But there’s a better way. The .subTest() mechanism is a parameterized context manager, which can augment your assertion with extra info.

01:04 Back to my terminal to see an example.

01:07 Instead of putting the code I’m testing in a separate file like you would in the real world, I’ve just stuck it up here at the top of my test script. This is a simple function that returns True if its argument is an even number.

01:20 If I want to test a whole bunch of values, instead of writing .assertEqual() over and over, I can use a loop, in this case testing for even numbers.

01:30 The .subTest() context manager takes as many keyword arguments as you want to give it. Here, I’m creating an argument named num and passing in the current value of num in the loop.

01:41 Then inside the context manager, I test the code. If something fails, the .subTest() context manager will augment the resulting error with the current value of the keyword arguments given.

01:53 Down here, I’m doing it again with the odd numbers. Note I’m using .assertFalse() instead as each of these should return False since they’re not even.

02:02 To show you why you’d choose to use subtests, I’m doing it again, but this time providing a value that should cause a problem. -11 is not an even number.

02:13 Let’s try this out.

02:17 As expected, the test_failure() method failed. In addition to the usual message though, the current state of .subTest() is also appended.

02:27 This is the clever bit. I now know that the value of -11 is what caused the problem. Without the subtest, this wouldn’t be there and I’d only know what failed, not what its arguments were when it did.

02:40 Short lesson that, but I tell you I wish I knew about it years ago. It would’ve saved me some hair loss.

02:46 Next up, test fixtures.

Become a Member to join the conversation.