Loading video player…

Structuring Your Tests

00:00 In the previous lesson, I gave an overview of the course. In this lesson, I’ll introduce you to the TestCase class and how to discover and run your tests.

00:09 As I mentioned in the overview, the standard library has a module named unittest, which includes the tools you need to write automated unit tests in Python.

00:18 The module itself is executable, and when you run it, it looks for your tests, creates a test suite, and then executes that suite. You run Python modules using the -m flag.

00:30 To run test discovery, you do python -m unittest. This executable module looks for Python files that start with test_ and then looks in those files to create a test suite.

00:42 The discovery process will look in the current module as well as subdirectories, so if you have a lot of tests, you can stick them together in a directory.

00:52 Common practice is to name that directory tests.

00:56 Inside any of the test files that start with test_, you import the TestCase class from unittest and create a class that inherits from it.

01:05 You can have more than one of these in your test file if you like, using the same kinds of practices you would with your code, putting things that make sense together in the same file. You define the tests to be run by writing methods in your TestCase class.

01:19 Any method that starts with test_ is considered a test. If a test method finishes without throwing an exception, the test is considered passed.

01:29 So to recap, you might have a tests directory, which contains one or more test_*.py files, which contain one or more TestCase classes, which can contain one or more test_ methods.

01:41 So that’s tests, test_, TestCase, test_. Yeah, that’s a lot of the word test. This might seem strange, but it makes it simple for the discovery process to know what is and isn’t a test and allow it to properly create a suite.

01:56 TestCase classes can contain methods that don’t start with test_, so if you’ve got common code you want your tests to call, you can do that.

02:04 And since they don’t start with test_, they won’t be considered a test. Let’s look at some sample code and a test class to go with it.

02:13 This is simple.py. If you’ve downloaded the sample code using the supporting materials dropdown below the video player, this file is in the intro directory.

02:23 It isn’t particularly complicated code, just a function that prints “Hello” to the screen. The interesting part isn’t here, but in the tests that go along with it.

02:34 This is test_simple.py, which is also in the intro directory. This file contains the single test for my code. You define tests as methods on a class which inherit from unittest.TestCase, so I need to start out by importing the base class.

02:51 In order to test the code, you need to be able to call it from this file, so here I’m importing the function that I’m going to test. This class defines my set of tests.

03:01 The name is more or less irrelevant. That’s not to say you shouldn’t name it well, but Python looks for anything that inherits from TestCase, so you can think of it as a label that helps you understand what it is.

03:11 I’ve called it SimpleTestCase, but people don’t always call it a test case. Sometimes they just call it a test. Some people put the word test first, so it could be SimpleTestCase, SimpleTest, or TestSimple.

03:25 I tend to put the name before Test to make it more searchable, but that’s just me. As long as you inherit from the base TestCase class, the unittest discovery process will find it.

03:36 Your TestCase class isn’t special, it’s just a regular Python class. Within it, you define methods. The unittest discovery process looks for methods that have a name starting with test_, like test_say_hello() does here.

03:50 Test methods don’t take arguments, well, except for the usual self that all methods in a class require. You can have methods that don’t start with test_, but those don’t get run by the discovery process.

04:02 That can be helpful if you want to write utility methods for use in your class. I’ll talk more about that in a future lesson. So once more, if it’s in a file that starts with test_, in a subclass of TestCase, and starts with the word test_, then the unittest framework will run it as a test.

04:19 Inside of the test method, you run the code you want to test. Our say_hello() method doesn’t really do anything, so you can’t really check if it works.

04:28 You can make sure that it doesn’t blow up, though. If say_hello() throws an exception, this test will fail. If all the code in a test method runs without an exception being thrown, then the test passes.

04:40 Okay, that’s the test script. Let’s run it. I’m going to execute the unittest module inside of the intro directory.

04:51 The -v argument means verbose. This makes the test framework a little more chatty. There are a few things to look at in the output here. First, it says the name of the test method.

05:03 Then, it gives the fully qualified name of the test. This includes the file name, the class name, and the method name. You can use this label to invoke this test explicitly, but I’ll show you that in a future lesson. The word hello isn’t from the testing framework, but a side effect of what was being tested.

05:23 Recall that the say_hello() method called print(). This is the result of that print(). This can be a little strange.

05:30 Normally, your print() starts at the beginning of the line, but the test framework printed something there instead, so your test’s output gets intermixed.

05:38 This can take a little getting used to, especially if you’ve sprinkled prints in your code for debugging. It won’t always appear on the screen in the place you might expect.

05:46 Finally, the test framework outputs a summary. In this case, there was only one test, and it tells you that it went so quickly that the timing rounds to zero.

05:55 If any of your tests fail, this would be the spot where you’d see that. I’ll show you an example of failure later as well. Okay, that’s the basic structure.

06:05 Next up, I’ll show you a more realistic test where you validate your code’s outcome.

Become a Member to join the conversation.