[No Audio]
Let's take a look now what we
expect to have in our unit test methods.
This will give us a good template on how to code
them, which we can use as we're doing our unit testing.
If you keep this mental template in your
head when you're coding a unit test, you
can't go far wrong in my opinion.
It keeps things nice and simple and provide us with
a structure we can use consistently across all tests.
So it's generally accepted that there are two main
types of logical structure for our unit test methods.
I'll just say unit test now for this,
but just know i'm referring to
the methods which form a single unit test, i.e.
Test a specific aspect of your system and
the test or the production class you're testing,
if you prefer to call it that. Both of these
approaches are pretty much the same, but just
look at testing from a slightly different perspective
and are better suited to different audiences.
We'll come to this in a second, but the two
choices you have for the logical structure of our
unit tests are either Arrange/ Act/ Assert sometimes
referred to as AAA and Given-When-
Then. Let's think for a second about high
level things we need to have happen
when we write a test from a logical viewpoint,
the method we're testing needs to be called.
This is the thing we're testing, so
we definitely need that to happen.
Also, the point of calling the method, is so we
can check what the method did after the fact.
So we need to have some code which
allows us to observe what happened. So we
can evaluate whether the test passed or failed.
That only leaves the other aspect, which is
to set up the context correctly for the
test, before we invoke the method. Now
if we rearrange these into their correct order, which
is set up, invoke the method, then check the results.
We have the AAA formula for Arrange/ Act/ Assert.
In this scheme, we have an Arrange phase.
This is where we put code which will set up our test.
For example, put the system on the test into a
particular state prior to inverting the method being
tested. This might be setting it up with references
to mock collaborators that it will work with
during the execution of the method, and similarly
setting up any state or behavior we require
those mock collaborators to exhibit during the tests.
Once we have that set up done, our Arrange phase,
then we can actually invoke the method we're testing.
This is the Act phase.
We really just want to have
a single method being called here.
Don't call multiple methods.
If you do, you're allowing the implementation
detail of the production class being tested,
to leak into the test case.
So the Act phase is just one method
invocation, the one method that's being tested.
Then once we've invoked the method, we can
do the checking part and check the results.
This is the Assert phase.
Like its name suggests in this part, this is
where you'd put assertions about the state of the
world after the method has been invoked. This
can either be Asserting something about the return
parameter of the method called, if it returns some
results, or might be assertions around the state of
the objects passed into the method called, or possibly
verifying the calls or data, etc, which were
passed to the mock collaborators.
Now there are two schools of thought on unit testing.
State based verification,
you do these with Assertions and behavior verification,
you do these with checking the method calls on mocks.
We won't get into this now, as it's a bit advanced, but
however you're checking the results, just understand
that you put them in the assert phase of the unit
test. Now that we know what a Arrange/ Act/ Assert
is, what about this Given-When-Then format?
Well, this is a style referred to as behavior driven
testing. In behavioral driven testing, what you're
doing is looking at the system from the behavior you
want it to have. Breaking it down.
we have the phases as first off, have a Given
phase which sets up the preconditions or the state of
the system before we invoke the behavior being tested.
Next, have a When phase which performs the behavior,
and finally have a Then phase which asserts the
state of the union after the behavior has been done.
In other words, looks at the post conditions.
This notion of pre and post conditions, by the
way, is a good way of looking at things.
Preconditions are what you want to
be true before the test.
Post conditions are what you're looking
to be true after the test.
You could have, for example, a test scenario
like this, given the user is logged in.
When the user logs out, then
the user cannot make a purchase.
Tests like these or more specifically, using Given When
Then wording usually lend themselves to being at a
higher level of abstraction than a simple unit test.
In fact, Given unit tests are more low level anyway.
Focusing on a single class, you tend to
encounter Arrange/ Act/ Assert a lot more.
Nevertheless, it's a valid style of writing
test cases, so it's worth mentioning.
Typically, you'll find these more in tests,
which are for business consumption by
business analysts, testers, and product owners.
In other words, you find them more in integration and
acceptance tests, so it's less common in unit tests.
So which one should you use?
Well, it's up to you, really.
Arrange/ Act/ Assert is popular with developers.
It's a bit more technical oriented
in its choice of wording.
The focus is on what the unit test
does by its implementation. Given-When-Then
however, it's popular with business analysts and
testers because it focuses more on looking
at the behavioral aspects, and it reads
easier for those less technical audiences.
Whichever one you use, though,
the structure is the same.
Just make sure you're consistent in using them.
In other words, pick one style and stick to it.
I usually do Arrange/ Act/ Assert and have comments
in the test code with those words so it's very
clear which bit of code is doing which phase.
It's a good practice to get into and
you can even set up a template in
your IDE to generate this automatically for you.
So now we know how to structure our test methods
with either Arrange/ Act/ Assert or Given-When-Then
this should put you in a good place to write your tests
from here. Just remember the different phases, stick to
them and you'll be writing very clean, very focused and
easy to understand test code.