From the course: Unit Testing in Python

Basic tests and assertions - Python Tutorial

From the course: Unit Testing in Python

Start my 1-month free trial

Basic tests and assertions

- [Instructor] Now, lets move to the code. I'll be using a Mac for the remainder of this course, your experience should be similar on Windows since we're using Docker containers to run our tests. Let's start to define behaviors we want our code to execute. In VS Code we'll start by opening the exercise folder. Once we've done that, you should see the project in the left navigation pane. Let's start by opening up two files. The first one will be in the Scripts folder, under Chapter Two, Video Two. It's called mapmaker_start. The next file is under the test folder, it's under also Chapter Two, Video Two and is called test_mapmaker_start. It may be handy to split the screen so that you can see both of these at the same time. I'm going to select Split Left so I have the test mapmaker on one side and then my mapmaker start on the other. You may see that VS Code also opens the test file here but you can close it. While setting up these two files, you might see that VS Code prompts you to install the Python extension. We can disregard this. Since we're running our tests in Docker it will take care of all the Python package installations we need. In essence, this is what makes Docker great, you don't need to change your underlying configuration to run tests. Next, we'll want to open a terminal window. You can do that by going to View, and Terminal. It will open in the bottom section of your editor. If you've already built the project with the Docker compose build command, you can proceed to run Docker compose run test sh, to enter the shell that allows us to run pytest in the Docker container. Once you see the hashtag, that means we're in the Docker container and we're ready to run our pytest commands. To get started, let's run the test file that we have to the left. We can do this by writing pytest down here, make sure we spell it right and we can use our keyword args to then run this file specifically. So we can use a keyword like, let's say map which is a portion of that file name and that will allow pytest to automatically pick up this particular test to run. As we see here, pytest has run our test and at this point it's passed. It's not really doing anything. Let's move to start writing this test and get into a red state first where we'll introduce what functionality we want our source code to the right, to implement. Before doing that, let's clear our output in the terminal. For this example, we will define a module to create points that consist of a city name, it's latitude and longitude coordinates. Let's start by creating a point in our test to verify we import our source code as expected. At this point, the test should fail after we do that. To get started, let's change this pass portion to p1, this will be our first point, and we want to instantiate it to be a part of the point class. So it will be, and act like a point. Let's save. Once we've done that, we can go back to our terminal and run the pytest command as we had before. So again, that's pytest-k and then map, so we're picking up that keyword argument. Aha, we have one error. Right here you can see name error, name point is not defined. This indicates that the test can't find the point module to create the point. In our red-green development cycle, we're currently in the red phase and need to fix this error. We can make our test pass or in other words, go green by actually importing the source code. Let's do that. At the top of our file, what we need to do is import the file to the right. So we can do that by typing the keyword from and then the path to that file, which in our case is scripts Chapter Two, Video Two and then we need the file itself, mapmaker_start. And then, we import the actual class that we're using, which is point. You may notice that VS Code attempts to auto-complete it for you. Now that we've done that, let's run our test again and make sure to save before you run it in the terminal. If we examine our terminal, on this first line we see that our test make one point has passed. However, you'll see a few pyflakes failures. This is because pytest runs linting checks before running the unit tests. It catches that our p1 variable, while successfully assigned to the instantiation of the point class is not used in any test. You'll see that right here, where it says unused variable. This is one of pyflakes' default linting rules. We can fix this as we move back to our test. Before we do that, let's clear our output. Moving back to our test, let's refactor it to actually make use of the point class. Remember those behaviors we mentioned before? We should be able to give a point a city name and also assign it a longitude and latitude. After that, we can then assert that it has the qualities we have assigned to it. To get started, let's just do that. We're going to add a name, in our case we'll call this city Dakar and then we're going to give it coordinates of 14.7167 and then its longitude should be 17.4677. Next, we want to assert that this point actually has the latitude and longitude that we've assigned to it. Let's make up a function, in our case, maybe, we can call it get lat long. This function should return to us those two points that we've set up before. Let's say it brings back a tuple, we'd bring us back that 14.7167 and then again, that longitude that we set up. And once we've done that, we have a functioning test. Let's get rid of this white space. Our linter will pick up that there's white space at the end of the file and it doesn't like that. Let's save and then overall, we expect this test to not pass. As you can see in the code to the right, we haven't implemented this in our point class but this is a great start for us to get our functionality all down on paper. To run our test and see our expected failure, again we can run pytest with out keyword flag and then simply put map. Aha, and we see here test make one point has failed and it's because the point class takes no arguments. And we can fix that quite simply by going to the source code. In our source code we want to do two things, first we need an init function. This will allow the point class to take three arguments which on our case is the city name, latitude and longitude. Next, we want to create that function that we talked about on the left, get lat long. This should return to us the lat and the longitude that we passed to the point in the first place. Let's get started. If we move down to the pass we can remove this, this was a great way to get the test to pick up the source code, being a empty class but we want to fill our class now. So we'll start by creating our first function, which is that init function. In order to make use of this function, first we have to pass itself a name argument, latitude and then also longitude. Now that we've done that, in order to make the point class access each argument as a part of its class instance, we can do this as follows. We'll create an argument for the class name name and what it will do is pick up the name argument that we've passed. We'll also do the same for longitude and latitude. Additionally, if we want to make sure that these instance objects are not accessible to the average user we should go back, put a _ in front of each one. After we've done this, we can move on to that next function that was our def, get lat long. This functions doesn't need to have any arguments, it only needs to refer to the class instance. Next, we want this function to simply return the latitude and the longitude. Additionally, we want to do this in a tuple format. So we'll create our tuple here, we should return our latitude and our longitude. Make sure we save this. After we've added this functionality, let's run our test. First, let's clear our output. We want to run a fresh pytest run. Oh wait, I spotted one error. Let's fix this before proceeding. Moving back to our point class, let's make sure that we're actually returning the class instantiation of latitude and longitude. We can do this by appending self for each. After we've done that, let's save our file and we'll move back to our terminal to run this test. Again we can type pytest, with our keyword flag and then map to run the test on the left. It looks like our test make one point has passed. The last thing we need to deal with are a few pep eight failures. Of our two errors, the first one expects that there be two blank lines in front of our test make one point function. The next one expects a blank line at the end of the file. However, we can see that the file to the left has no blank line. This indicates to me that there might be a disconnect between the container and the VS Code configuration. We can get by this for this video, by adding a blank line to the end of this file. This is how I'll handle this minor bug for this course. However, in your own testing environment, this shouldn't be something you need to do. The first thing I'll do is add that extra blank line that we need in front of our test function. The next thing I'll do, is go to the bottom of our file and another blank line, making sure to remove any white space preceding it. Make sure to save that file and then we'll move back to our terminal. And run pytest-k and then map. Aha! We can see here, that our test make one point has passed and so have the linting tests. We're now in a green state. Now you've iterated through the red-green development process, a part of test driven development. This type of iteration will help us keep in mind what types of core functionality we want to include in our source code. It will also help us isolate and fix potential errors in small chunks, rather than writing our code in large sweeps. This helps us avoid the need to tackle multiple types of errors at once.

Contents