Hey, welcome back.
In this video we're continuing with unit test, we're not talking about particular assertions.
Instead, I'm going to show you some functionality, some features that we get with unit tests that
are really, really useful.
When you're testing larger applications, oftentimes you have code that you need to run before tests
or after all your tests.
Whether that's having to do with a database, adding data to a database or creating fake data that you
want to use in all of your tests, you create a fake user account and you want to, instead of recreating
it in every single test function, you want it to be available everywhere.
We can define two methods called set up and tear down.
They do have to be named in a particular way, and like I said, in a larger application, you might
want some similar code to run before every test.
So you put that code in setup and it runs before every test method.
Similarly, if you have code, you want to run after all your tests, which if you're not using a database,
it's probably not that common.
And in our situation we're just going to focus on setup.
But imagine you are testing something with a database and you add a bunch of data into the database
for your tests.
You don't want to just keep it there.
If you call tear down, it will remove it after every test.
So that's what teardown does.
So common use cases, like I said, removing or adding data from a test database or creating instances
of a class that you're going to reuse, creating some data, whether it's not in whether it's in the
database or not, just data that you want to use in your tests.
So here's an example.
None of these this doesn't do anything, but we have these two tests, test first and test second,
but then we have setup and teardown.
And if they're named correctly inside of this test in a class it inherits from test case, whatever
we put in here, it's going to run before the code and test first and before the code and test second.
And whatever's in teardown, it will run after test first and after test second.
So to help explain this, I have a class called Robot and I've already typed it up.
It doesn't really matter too much.
The details don't matter, but it's a class called robot.
Every robot has a name, a battery level, which is a number and a list of skills.
There's a method called charge where we just set self battery to be 100.
We fully charge the battery.
And then we have two methods that have a different results, different outcome depending on the charge
of the battery.
So to say when we call say name, if self battery is positive, we're going to return beep boop boop
im self name uppercase and subtract one decrement self battery.
It takes one battery to say name and if battery is negative, we return low power.
Please charge and try again.
Similarly, let me add some space with learn skill.
You pass in a skill to learn and a cost to learn it.
And then we check is cost to learn lesson or is battery greater than or equal to cost to learn?
If it is, then we subtract the cost to learn from the battery and we append skills to array, append
the new skill to skills.
Then we return.
Whoa.
I now know whatever the skill is, how to make a sandwich.
Otherwise we return insufficient battery.
Please charge and try again.
Okay, so very basic robot class.
Now let's write a few tests.
So I have a file called robot test up by importing robot from the robot file.
I just named them both.
The file is robot pie.
The class is robot import unit test to find my class inherits from test case and let's start by testing
the charge method.
So we do def test charge and to test that we're going to need to make a new robot.
So let's go with, I don't know, megaman equals robot and I do need to capitalize this.
That's the name of the class so we'll just pass in name is Megaman and let's say battery is set to 50
at the beginning.
So what I want to do is call Megaman charge and then test that charge.
That charge is now 100.
So I would just do self dot, assert equal megaman dot and then I check for battery karma 100 and this
should work, right?
That's how the method is set up right now.
Let's test it.
Yes.
Passing.
That's all good.
Now let's add one to test.
Say name.
I should mention we're not doing this TDD style.
I already wrote all the code, but that's just to save time.
Okay, so we want to test this.
Let's go back here and do the same thing again.
So def test, say name, and then here we're going to do the same thing.
Make a new robot because we have to have a robot to test because this is a function.
Whatever code is in here is scoped to this.
So we don't have access to it.
We have to redefine it down here.
So I make that again and then I'm just going to do a self assert equal when I call Megaman Dot, say
name.
I'm just going to copy the string here.
We should get boop, boop, boop, boop.
I am Megaman in all caps.
Paste it in.
Put this on new lines.
Boop, boop, im.
And then we replace this with mega man like that.
And on top of that, we also want to check that the battery has gone down.
So that should be megaman dot battery should now equal 49.
Let's see if it works.
Robot has no attribute, no tests.
A name that should be same name.
Oh, and we need to run, say name as well.
All right, so this is now.
This should work.
Make new megaman.
Make a new robot.
We call, say name.
It should equal this.
And after that happens, battery should have gone down.
And it works.
So I won't make you sit through watching me test all the other functions.
But if I want to test learn skill, I would have to write well.
I would test another same name.
I would test if battery was too low, so that'd be another function.
And then I would test learn skill if battery was too low to learn the skill or if there is enough battery
to learn the skill.
So that's three different times, three different functions at a bare minimum that I would be defining
and I'd make Megaman again instead.
However, we can use Setup to help us out and you might be thinking, couldn't I just do this?
Put Megaman up here and all of them would access Megaman.
That is true.
That works.
But there's a difference because whatever side effects that happened in this code would alter Megaman
and every other test function we have would be using the exact same copy of this robot.
So if we set the battery to zero, then I write another function to test that the battery should be
full.
If it was already set to zero in the previous test function, it's still going to be zero.
So with setup, it reruns the code every time it doesn't run it once it reruns it before every function.
So I just write def set up like this camel case self and then we'll just do self megaman equals just
copy this.
Just like that.
And now what we can do is reference self megaman in all of these instances.
So let me just copy my cursor a couple of times.
So it does need to be self megaman, but this code now has will run before every single function and
I can now get rid of this and this as well, where I'm defining Megaman.
Let's see if it works.
Awesome.
So you could imagine, hopefully if we actually wrote tests for all the other functions and let's say
we had ten functions in that class, we could be rerunning the same code a lot.
So setup is really, really useful and tear down is exactly the same, except it runs after each one
of our test functions.
So that's pretty much all there is to it set up to find it that way.
It must be called setup tear down must be called tear down unit test.
It looks for them automatically and it runs them before and after each test case respectively.