Debugging with test cases
About this video
The instructor debugs a two-car racing game where cars sometimes vanish from the track display. By testing the display function in isolation with four test cases (car one ahead, car two ahead, same position, past the end), he finds and fixes two bugs: drawing up to the maximum of all positions, and drawing an X only when the current position equals both cars' positions.
You'll be able to
- narrow a bug down by testing a single function in isolation.
- choose test cases that include tricky edge cases like ties and out-of-range values.
- explain why a condition must check the current position as well as the cars' positions.
Key words
- test case
- A specific set of inputs used to check that a function gives the result you expect.
- in isolation
- Testing one function on its own, separate from the rest of the program.
- edge case
- An unusual input at the limits, like two cars on the same spot or a car past the end of the track.
- max
- A built-in function that returns the largest of the values you give it.
Transcript
- [Instructor] Let's apply test cases to debug a racing game. Our game prototype has two cars that race on a straight track. Each round the cars move forward a random number of spaces and whichever car passes the end of the track first wins. Let's take a look at the code we have so far.
We use a while loop to repeat rounds until the race is over. On each iteration we move the cars, we print the status of the race, and we display the track state. When I run it, it kind of seems like this game works, but there does seem to maybe be a little bug here.
On the last round, it seems like cars are sometimes disappearing from the track, so maybe I'm missing something in my display function. I'm gonna open up the track module to see how this display function works. It takes in the positions of the two cars and the length of the track and it returns out a string drawing of the track state.
Seems reasonable, but what's going wrong then? To narrow this down, I'm going to test the display function in isolation. So I'll pop back over to main.py and run through a few test cases. There's the case where the first car is ahead. There's the case where the second car is ahead.
There's a case where both cars I guess are on the same position of the track and then there's the end case where a car is beyond the end of the track. Okay, let's see what values we get back. I'm gonna comment out this game loop for now because its output is a little distracting.
It looks like a car is disappearing in two test cases, so lucky us, maybe we have two bugs to fix. Let's start with the last case where a car's position is greater than the track length. What do we want to happen in this case? Well, I'd like to still see where the car is, so maybe we just keep drawing until we reach the furthest position.
Right now our draw loop only goes up to the length of the track, but plus one since range is exclusive. So if the track length is five and car one is at position seven, then we wanna keep drawing segments until we pass position seven. So really the end of the range should be whichever is greater, the position of car one or the end of the track.
But car two might also be the furthest, so we should really take the maximum of all three positions. Hmm, let's see if that fixed the problem. And let's double check the case where car two is the furthest. Whew. That's three test cases passing now. So let's wrap this up by fixing the case where the cars are at the same position on the track.
Right now it looks like display is only showing the symbol for car one. What do we expect? Well, it's not all that obvious. One solution might be to just draw a different symbol that indicates both cars are on that space. I can change the symbol later, but for now, let's just say I draw an X.
So let's go back to our display function and see what we need to modify. It looks like this nested function call controls which symbol we draw for each segment. So we need to update the get symbol for space function to handle that X case. If car one and car two's position are the same, then we return an X.
Ooh, everything is an X now, what did we do? It seems like for every segment get symbol for space is returning X. Hmm, we do need to check that car one and car two are at the same position, but we also need to check that that's the position we're currently trying to get the symbol for.
It doesn't matter if car one and car two are both at position five if right now we're trying to get the symbol for position one. So to draw an X, all three of these values should be the same, which we can verify by checking that position equals equals car one.
Alright, all four test cases are passing. I'm fairly confident that the display function works now, so let's put the game back together. I'll clean up those test cases and uncomment out the game loop. The next time you encounter a bug in your program, try narrowing it down to the individual function level and hopefully you'll have an easier time debugging just that one unit of code.
Video © Khan Academy, used under CC BY-NC-SA. Watch on Khan Academy. Puzzicle is not affiliated with Khan Academy.