Writing Your First Test & The Core TDD Cycle
After setting up the project, you’ll now write your first unit test and learn about the core TDD cycle.
To start, let’s just go ahead and create a skeleton for our stack data structure. To do that, I’m going to create a class called
Stack. And since I don’t have any particular implementation, I’m just going to type in
So, this will at least be syntactically correct if I try to run it. Next, I would like to import this
Stack class into my test file. So, normal import rules apply—I’m going to say
from ds.stack import Stack.
00:41 Now, what I can do is run this. Now of course, there are no actual tests, but that won’t prevent us from running it. I’m going to switch over to the terminal and I’m going to run this and just see what happens.
So, how you can run
pytest is you type in
python -m—which means module—
pytest -v. And
-v means verbose, so, “Show me all the particular tests that are either passing or failing.” And of course we can see here, it says
collected 0 items—that means there were no tests—and we can see that there were no tests, and this test ran in
If I were to create
def—which is, “I’m going to create a function”—I’m going to, call it
test_constructor(), just like that. And so how
pytest works is the name of the function should be prepended with
test underscore). If you were testing a dog, you would say
test_dog(). If you were testing a cat—
I’m going to call this object
s and it’s going to come from this
Stack class. Now, once you have this object, you can make what’s called an assertion against it. And what assertions are—it’s a keyword,
assert, and what happens after it… Let’s imagine I say
1 == 2. This, what
assert is looking for, is a Boolean expression.
1 == 2 will evaluate to either a
False. If it’s
True, the assert passes.
False, the assert fails. So here, because
1 clearly does not equal
2, this test actually will fail. So if I come back here and run this test again, we can see down here it says
assert 1 == 2—that was an error. It happened because
1 does not equal
2, and it says
1 test failed. So, how you can make this test pass, of course, is you could type in
2 == 2 or
1 == 1.
We can flip back here and run the test again. And it says
1 passed and it’s in green. The
test_constructor() actually passed. So, this is how you can actually test out something—whether it works or not—using these assertion statements.
04:00 Now, the question you want to ask yourself is, “Is this a good test?” And I would say “No.” The reason is because when you create a stack, it’s actually a data structure that contains internal data—like a list contains data, or a set contains data, or a dictionary contains data.
There’s nothing in this
Stack over here that actually contains data. And so what we can do is let’s go ahead and override our constructor so it actually will contain some data, and then we can test it.
04:29 Now, this is called test driven development, and it’s called test driven development because you should actually do the tests first. And so what I would like to do is just go ahead and write our tests.
I’m going to say
assert, and the test is going to fail and it should fail—that’s the whole purpose behind it, is a test will fail and then we’ll make it pass. And in the process of making it pass, we are essentially adding functionality to our
If I save this and I flip back to here and I run my test again, last time it gave me an error and it said
len() was undefined. Now it says that
3 doesn’t equal
0, because remember, I’m actually returning
3 from that test.
And of course, I could actually just return
0 and the test would pass, but that’s not true to what I’m trying to do here. So how can I make this
.__len__() return a number
0 and actually do what I want to do, which is contain some internal data? And how I’m going to do this is I’m actually going to create a constructor method.
Now, you may be wondering why am I calling it
_storage instead of just
storage. Well, sort of by doing an underscore (
_), I’m relaying information to potential other programmers—or maybe my future self—that this attribute should be private.
So, I don’t actually want to expose
._storage to the external world. I want it to be private, I want to be internal, so that’s why I’m, prefixing
_storage with the underscore (
_). Now—now that I have this—what I can do in my
.__len__() function is instead of returning
3, I can just say return the length of
Okay? And so that should return
0. So, hopefully this test will pass. I’m going to switch back to my terminal and let’s see what happens. So here I am in the terminal, I’m going to clear my screen and rerun the test—and it passed.
And that’s exactly what I wanted to happen. So, in recap, I create an object called
s from the
Stack class. And what happens is I create some internal storage that’s private, that’s a list. And it’s empty—it’s an empty list.
And when I happened to call
len() on this
Stack, it actually calls this
.__len__(), and it returns the length of this actual list, which happens to be
0, and therefore this assertion passes, and the assertion on line 6 passes as well too, because
s is a
Become a Member to join the conversation.