Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed JavaScript Unit Testing!
You have completed JavaScript Unit Testing!
Preview
Fixtures are the part of a test suite that set the stage for our specs. In this video, we’ll write code to run before every spec and also before each test spec that makes testing simpler.
Resources
Video review
- Mocha provides useful functions to help us set up conditions for our tests, like creating test objects and simulating the conditions inside our app
- The "setup" phase is the part of our tests where we set up conditions for testing
- Mocha splits the setup process into two blocks: the stuff we set up before the entire series of tests, and the stuff we set up before each individual test
- Mocha provides the hooks
before()
,after()
,beforeEach()
, andafterEach()
to set up preconditions and clean up after your tests -
beforeEach()
works like before, only it will run the function before each spec, instead of just once at the start of the suite
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
[MUSIC]
0:00
Writing unit tests might seem like
magic sometimes, but in the end,
0:04
we're still just writing JavaScript.
0:07
You'll want to follow the same best
practices you use when writing
0:10
any JavaScript program.
0:13
We should keep our test dry and tidy.
0:15
In this stage, we'll explore some handy
ways to avoid repeating ourselves.
0:17
We'll also expand our tests
to build our confidence and
0:22
the code we've written so far.
0:25
So far, I've been writing the dependencies
for every test within each spec.
0:27
For example, in our check for
0:32
ship test suite, I wrote a new
player object for every test.
0:33
So the first test has a player, and
the second test has the same exact player.
0:37
So we need this code to simulate a player
object to test the checkForShip function.
0:43
In other words, the checkForShip function
doesn't work without a player object, so
0:49
we need to fake or mock a player
object in order to test the function.
0:53
So as you can see duplicating
this code in our test file
0:58
goes against the programming best
practice of don't repeat yourself or dry.
1:02
Fortunately Mocha,
like all testing frameworks,
1:08
comes with a few useful functions o
help us set up conditions for tests,
1:10
like creating test objects and
simulating the conditions inside our app.
1:15
This is called the Setup Phase,
1:20
the part of our tests where we
set up conditions for testing.
1:22
In fact, Mocha splits the setup
process into two blocks.
1:26
The stuff we set up before
the entire series of tests, and
1:30
the stuff we set up before
each individual test.
1:33
Let me show you an example.
1:36
The checkForShip function
doesn't alter any other code.
1:38
It doesn't have side effects
on our player object or ships.
1:42
It doesn't make changes anywhere.
1:46
It just does some calculations and
then gives us a report back
1:48
that says pulse if there's no
ship at the given coordinates, or
1:52
it tells us which ship it
found if there is one.
1:55
So because checkForShip won't
change a player object in any way,
1:59
it's safe to set up a single player object
once with the information we need and
2:02
then use that for
all of the checkForShip tests.
2:07
So the first thing I'll do is
initialize a player variable
2:11
at the top of the test suite.
2:14
So right after I import the checkForShip
function, I'll type Var player.
2:15
Then right below it,
I'll set up a before block.
2:23
So before just needs one argument,
2:30
a function that runs before any of our
test specs, to set up any state they need.
2:34
In this case, each test spec needs
a player object with a ship's array.
2:42
So I'll simply cut the player object
out of this first test spec and
2:47
paste it into my before block.
2:53
So now the first spec will have access
to the same player it did initially.
2:57
And before anything else
happens in my test suite,
3:02
Mocha will make a player object for
all of the specs below to use.
3:05
Pretty cool.
3:10
So now I can go ahead and delete
the player object from my second spec too,
3:11
because it will use the same player
object, the first one you used.
3:16
Now to repeat this for the other specs,
we have to make sure we're keeping
3:22
all the added complexity those
tests need in this player object.
3:26
So for instance, when I get to the third
spec, I see that the player object up
3:31
here in the before block is going
to need a bit more complexity for
3:35
a test suite to work, because I see
that this ship needs a second location.
3:40
And in fact,
the next test spec needs a bunch of ships.
3:45
So, what we'll do is take the most
complex player object in this suite and
3:49
use it up here, in our before block.
3:54
So, the last spec, and
we check for ship suite,
3:57
represents the most complicated
object we need for any of our specs.
4:01
So, I'll cut the ships array
used in this last spec, and
4:06
replace the one up top by pasting
it in to the before block.
4:11
All right, so
now all the tests in my checkForShip suite
4:19
will use this player object.
4:23
But we only need to write it in one place,
and it will work for
4:25
both my complex test and for
all the simpler tests too.
4:28
So now I can go ahead and delete any
player object in my checkForShip specs.
4:33
So now, since all of my test backs
have access to the player object and
4:46
the before block,
if I run the test in the console.
4:51
Great.
All my tests still pass.
4:58
All right, so
let's clean up the fire spec now.
5:07
The fire function is
different than checkForShip.
5:11
Fire is not a pure function.
5:14
It has side effects in other
parts of our code base.
5:16
In this case, fire changes the damage
array of the shipped object.
5:19
It's given by calling damageShip.
5:24
So if we ran it over and over,
5:28
we would just keep pushing damage
records onto the same ship.
5:30
So that means that our test specs will
be altering the application state
5:34
from one to another,
which will mess up our expectations and
5:38
maybe make them fail,
even when our function works.
5:41
So instead of setting up
a ship once in a before block,
5:45
like we did earlier,
we'll reset the ship for each spec.
5:48
To do this, we can use a beforeEach block.
5:53
So first I'll initialize a player
variable at the top of the fire suite.
5:56
So right after I import the fire function,
I'll type var player.
6:02
beforeEach works just like before,
only it will run the function
6:07
before each spec instead of just once
at the start of the whole suite.
6:12
So, right after the player variable,
I'll set up a before each block.
6:17
[SOUND] If I copy just the player object
6:22
below Into the beforeEach block.
6:29
So I'll go ahead and remove var.
6:36
That means that the player object
will be overwritten before each test.
6:39
So no matter what changes happen inside of
the first spec, it will all be erased and
6:45
set back up new for
the next spec right here.
6:50
That makes our application state
predictable between specs,
6:54
even when the function we're
testing has side effects.
6:57
A nice bonus of using before and
beforeEach blocks for
7:03
setup is that our suites
feel easier to read.
7:07
We can see exactly how the test author
thinks this function needs to work.
7:11
It acts like a little bit
of documentation, for
7:16
how the function is intended to be used.
7:19
So if I save my file and
run the test again in the console.
7:24
Nice, all my tests still pass.
7:33
So in the next video, we'll cover the last
phase of a test suite, tear down.
7:35
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up