This course will be retired on June 1, 2025.
Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
The first phase of red-green-refactor is to write tests and make sure that they fail as expected.
This video doesn't have any notes.
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
In the TreeHouseDefense game,
invaders move down a path.
0:00
Let's use driven development to
write the code for the Path class.
0:04
Because we're using test
driven development now,
0:07
we'll write the test first.
0:10
We'll first add a class to our
test project named PathTests.
0:12
I'll clean it up a little bit, and
then make the class public, so
0:23
that it can be accessed
from the test runner.
0:26
Let's create a new test method.
0:31
So the first thing I'll do is say [Fact],
and then public void,
0:33
and I'll name this test
method MapLocationIsOnPath.
0:38
I've got a red squiggly here on fact, so
0:43
I use my quick action to
add the using statement.
0:47
Now MapLocationIsOnPath will test
the IsOnPath method of the Path.
0:52
So I'll first need to create a bunch
of MapLocations for the Path.
0:59
Before I do that,
I'll need to create a map object.
1:03
So I'll say var map = new Map (3, 3).
1:06
I need to fix my namespace here.
1:12
A MapLocation, pathLocations =
1:18
new MapLocation at,
1:25
I'll make this one 0, 1,
1:29
And I'll add a couple more.
1:39
So 1 at 0, or 1 and 1, 1, and 1 at 2, 1.
1:43
Now I'll create the instance
of the Path class.
1:47
So I'll say var target = new Path,
and it will take
1:51
the Path locations as a parameter,
so pathLocations.
1:56
Now let's test calling the isOnPath
method of the Path class.
2:03
So we'll say Assert.True(target.IsOnPath)
2:09
with a new MapLocation at 0, 1.
2:17
So this is the completed test for
MapLocation IsOnPath.
2:23
But notice that we have
these red squigglies here,
2:30
under the Path class name, that's
because we don't have a Path class yet.
2:32
We can have Visual Studio
generate the Path class for
2:37
us with the cursor on the red squiggles,
2:40
just hit Ctrl., on the keyboard to open
up the Quick Actions Context menu.
2:42
Go down to Generate Type, and
2:48
here we see a few options for
generating the Path class.
2:51
These first three will generate the Path
class inside of our test project,
2:54
that's not what we want.
2:59
So go on to the fourth one,
into Generate New Type,
3:00
then change the project
to TreehouseDefense, and
3:03
have it create a new file called Path.cs,
and hit OK.
3:08
As you can see,
Visual Studio created the Path file, and
3:13
Path class in
the TreehouseDefense project.
3:17
This is what it looks like.
3:21
Let's go back to our test code.
3:22
Now that we've generated the Path class,
3:23
we see a squiggly red line
under the Is OnPath method.
3:27
Again, we can have Visual Studio
generate this method for us.
3:31
Now the red squigglies are gone, and
3:34
we have a method named
IsOnPath in the Path class.
3:36
With no red squigglies,
our code will compile, and
3:39
we can have IntelliSense help us while
we code the rest of the methods.
3:43
Let's create another test method to test
when the map location is not on the path.
3:47
To do that I'll copy our existing test,
3:53
Paste it down here, and
rename it MapLocation IsNotOnPath.
4:00
We change the assert to false,
And we change this
4:07
MapLocation to something that's definitely
not on the path, so make it 3, 3.
4:14
We could continue to write some more
tests, but I think this is good enough for
4:18
right now.
4:22
One thing we should consider doing right
now is removing some duplicate code.
4:23
Notice how both of these methods
are almost identical, except for
4:28
the assert statement.
4:32
You might think that we should just
combine these two tests into a single
4:33
method that has multiple
assert statements.
4:37
This is problematic though because it
isn't clear what's being tested, or
4:39
what causes the test to fail.
4:43
It's best to have two separate test
methods with descriptive names like this.
4:46
Instead, we can move the creation of
the map, the map locations array and
4:50
the Path, outside of the methods, and
4:54
create them in the constructor of
the Path test class, so let's do that.
4:57
I'll create a constructor up here.
5:01
I'll say public PathTests,
with no parameters, and
5:06
go down here, and we'll just copy this.
5:11
In fact, I'll cut them,
and put them in here, and
5:18
no need to turn these into fields
that the other methods can access.
5:23
So we'll say this one is, we'll call
this one map, and we'll call it map3x3.
5:28
Because in the future,
5:35
we might have more than one map that
our Path test class wants to use.
5:37
We can have Visual Studio generate this
field in the path as class for us.
5:41
We'll do the same thing for
Path locations,
5:46
except change this, so
that it creates a new MapLocation array.
5:51
And we'll need to change these, so
that they're using our map field,
6:04
so say map3x3, Copy that around,
6:10
And again, have Visual Studio
generate this one for us.
6:23
Actually let's name this
Path locations three,
6:28
since it's an array of three
Path locations on the 3x3 map.
6:32
So to rename, I'll go Ctrl+R R, and
6:37
at the end here, I''ll just add a 3 there.
6:40
And we'll create a Path field named was,
6:45
just call it Path three.
6:50
For the same reasons, we named the
PathLocation3, and it takes PathLocations,
6:53
And again, create field.
7:04
Okay, so now all the methods in the Path
test class can access these fields.
7:09
So now, let's go down here, and use them.
7:16
I still like calling my target object,
target, so
7:17
I'll keep that conventional,
say var target = path3, and I'll fix this.
7:21
Same thing down here.
7:35
So there might be something we
would be concerned about, that is,
7:51
we have two methods that can
potentially alter our target object.
7:56
The problem with that is if one
method alters the target object, and
8:03
then the other test method is called,
8:07
we might have some unexpected
behavior in the next method.
8:09
What we want is there to be a clean slate,
each time one of these methods is called.
8:14
So we want these three fields appear
to be reinitialized every time
8:20
before each test method is called.
8:25
X unit actually handles this for
us by creating a new instance
8:27
of Path test,
before calling each one of these methods.
8:32
This allows us to use the constructor
of Path test to set up each method.
8:37
Other unit test framework,
such as NUnit and
8:43
MSTest have a special setup method that's
called before each test method is ran.
8:45
Each test method should be completely
independent of the other test methods.
8:50
In fact, xUnit runs test
methods in a random order, so
8:55
that we can't count on methods
being called in a certain order.
8:59
Now that we've cleaned up the test code,
let's go ahead and run these tests.
9:02
To just run these two tests,
9:07
we'll just right click on PathTests,
and then click Run Tests.
9:08
Let's check out the results
in the test Explorer.
9:18
Looks like they both fail, let's get some
more room by moving this pane down here.
9:20
So MapLocationIsOnPath, fails with
the expected NotImplementedException.
9:29
However, if we look at
MapLocationIsNotOnPath,
9:35
it fails with a different exception,
it fails with the OutOfBoundsException.
9:39
That's not right,
this is why we use red, green refactor.
9:44
We first run our test to make
sure that they fail as expected.
9:48
If they don't fail the way
we expect them to,
9:52
then there's probably
something wrong with the test.
9:54
In this case,
we're getting the wrong exception.
9:57
Something must be throwing an exception
before we call the IsOnPath method.
10:00
Let's take a look.
10:06
I see the problem, I created
a MapLocation that wasn't on the map,
10:15
that's why we're getting
the out of bounds exception.
10:23
But this isn't what we're trying to test.
10:30
Let's make it a valid map location
that's not on the Path, 0, 0 will do.
10:32
Now, we can rerun these tests.
10:41
We can do that by going
into the Test Explorer, and
10:42
clicking on Run, Repeat Last Run.
10:45
Now, if we look at the Test Explorer,
we see that they're both failing
10:50
with NotImplementedException,
and that's what we expect.
10:54
Now, it's time to move on to the next
step of making them all green.
10:57
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