IntroductionWelcome| 00:04 |
Hi.
I'm Simon Allardice, and welcome to
| | 00:06 |
foundations of programming, test driven
development.
| | 00:09 |
Now, this is programming, and you should
never just hope that your code works properly.
| | 00:14 |
You should be able to prove it, and prove
it again and again, every step of the way.
| | 00:18 |
From the very first lines of code you
write, all the way through to deploying
| | 00:21 |
an application.
And the best way to prove it is with
| | 00:25 |
automated tests.
But this isn't the kind of testing you
| | 00:27 |
only do at the end as part of a quality
assurance state.
| | 00:30 |
Test-driven development, or TDD for
short, is a way of doing automated
| | 00:35 |
testing that is built-in to your
day-to-day routine.
| | 00:38 |
It becomes an integral part of everything
you do.
| | 00:41 |
And in this course, we'll see how to get
started with test driven development.
| | 00:46 |
First, by clearing up some misconceptions
about TDD versus other kinds of software testing.
| | 00:52 |
We'll then explore the basic ideas and
jargon of TDD, working with tests and
| | 00:58 |
test fixtures and text suites, setting up
and tearing down and mock objects.
| | 01:03 |
We'll see what makes a good test.
We'll then explore what software exists
| | 01:08 |
to help you create, run and manage your
tests.
| | 01:11 |
And perhaps most importantly, see how to
move to a test-first mindset, to take
| | 01:16 |
your testing from being an afterthought
into something that drives your everyday development.
| | 01:21 |
So, let's get started.
| | 01:22 |
| | Collapse this transcript |
| What you need to know| 00:01 |
This is a course you should watch once
you feel reasonably comfortable
| | 00:04 |
developing in a general purpose
object-oriented programming language.
| | 00:08 |
Something like Java, C Sharp, Objective
C, Python, and so on.
| | 00:13 |
Because I expect at least at least object
or development skills here to be able to
| | 00:17 |
write and understand write methods,
conditions, iterations.
| | 00:23 |
I'm going to talk about being able to
write and understand TDD so I can talk
| | 00:26 |
about how to add TDD practices on top of
it.
| | 00:30 |
A question I sometimes get is, does
test-driven development replace or
| | 00:34 |
conflict with other things?
I have been learning or hearing about
| | 00:37 |
like object-oriented design or
refactoring, or agile methodologies.
| | 00:42 |
And no, test-driven development doesn't
conflict with those at all.
| | 00:45 |
In fact, it's entirely complementary.
And many of what might be considered best
| | 00:50 |
practice skills and techniques are
professional enterprise developers.
| | 00:54 |
Things like refactoring, Scrum, are often
found hand-in-hand with using TDD.
| | 01:00 |
So, how are we going to learn this?
As with most of these foundations of
| | 01:03 |
programming courses, I want you to find
this one useful for many different languages.
| | 01:08 |
But test-driven development isn't just
some idea.
| | 01:11 |
This isn't an academic ivory tower,
theoretical thing you only do on a whiteboard.
| | 01:17 |
This is an intensely practical, hands-on,
in the code technique.
| | 01:21 |
So, I will show it being used in a few
different languages.
| | 01:24 |
But regardless of language or
environment, it is based on some core
| | 01:28 |
ideas that really don't care which
language you use.
| | 01:31 |
So expect that when I can, I will teach
this as generically as possible.
| | 01:36 |
Often using either pseudocode or simple
Java code.
| | 01:39 |
But, we'll get more into that in a
moment.
| | 01:41 |
With that in mind, let's cover exactly
what test-driven development is and clear
| | 01:46 |
up some of the misconceptions and
misunderstandings people have about it.
| | 01:50 |
| | Collapse this transcript |
|
|
1. Introduction to Test-Driven Development (TDD)What kind of testing is this?| 00:01 |
You may, right now, have the wrong idea
about this course.
| | 00:04 |
So understand this is not a course on how
to test software in some kind of generic sense.
| | 00:11 |
Because testing is a vague word in
software development, there's lots of
| | 00:15 |
different kinds of testing we could do.
We need another word alongside it to make
| | 00:19 |
it more specific.
Some of the better known kinds of
| | 00:21 |
software testing would be things like.
Beta testing, providing a finished or
| | 00:26 |
nearly finished application to a group of
users, and seeing what problems they come
| | 00:30 |
up with.
There's performance testing using
| | 00:33 |
profiling tools to measure if we're
getting acceptable response times.
| | 00:37 |
Is this application running as fast as it
should be, or at least as fast as it
| | 00:41 |
needs to be?
This stress testing, one kind of
| | 00:44 |
performance testing where we want to know
how well the code works on the heavy
| | 00:47 |
load, so this web application works fine
with one person, what about a 100 or 1000
| | 00:52 |
or 10,000 at the same time.
There's other kinds of testing, we have
| | 00:57 |
got integration testing, testing one app
integrating with external other systems,
| | 01:02 |
there's exemptions testing, there's
regression testing, there's usability testing.
| | 01:07 |
Well, this course isn't about any of
these.
| | 01:09 |
We're talking here only about unit
testing.
| | 01:14 |
Testing we do as programmers not as end
users.
| | 01:17 |
We are testing the code itself not just
the results we might get from clicking
| | 01:22 |
buttons on a user interface.
So this is about us testing the
| | 01:26 |
individual units of our code.
The smallest logical piece as possible.
| | 01:30 |
So we're proving that a single class
works the way that class is suppossed to.
| | 01:34 |
More than that, we're proving that
individual methods work the way they should.
| | 01:39 |
But if we pass in these particular values
into that particular method, we will get
| | 01:45 |
this specific result back.
And we go ahead and prove that this is true.
| | 01:49 |
But this is not the kind of testing where
you act as an end user as a finished application.
| | 01:55 |
I mean, we might do that.
But that would be later.
| | 01:58 |
Sometimes much later.
We don't wait to have a finish
| | 02:01 |
application, we are doing this right from
the start.
| | 02:04 |
We are testing a code as we write it.
We might not have a user interface yet.
| | 02:08 |
We may not have written most of our
classes yet.
| | 02:10 |
We are still testing our code so this
course is about unit testing but more
| | 02:16 |
than that its about having automated unit
test because if you want to test down to
| | 02:21 |
the level of the individual methods in
our application you don't want to have to.
| | 02:25 |
Manually type method cords into a command
line window, and then check the results
| | 02:29 |
against some massive book of tests.
We don't want to do any of this manually
| | 02:33 |
again and again, that would be completely
painful.
| | 02:37 |
So we will automate this, we will write
code that tests our application code.
| | 02:43 |
So we'll have our application code and
saved right alongside it, and considered
| | 02:47 |
just as important.
Are simple, repeatable testing code.
| | 02:51 |
Now that might sound like a huge amount
of additional work.
| | 02:54 |
It really isn't.
As you'll see, writing tests is done very simply.
| | 03:00 |
It requires minimal code, minimal logic
to write a test and we'll have it so that
| | 03:04 |
we can easily write these tests, save
them, and then run them repeatedly at the
| | 03:09 |
press of a button.
We need it to be as easy to to run our
| | 03:12 |
tests as it is to compile our code, or
run our application.
| | 03:17 |
And as we build our application we build
our unit tests right along side it.
| | 03:22 |
So we can run our unit test right along
side it.
| | 03:24 |
So we can run those tests ten 20 or 100
times a day.
| | 03:26 |
Now among other benefits, having
automated unit test allows us to easily
| | 03:31 |
validate that any change we make at one
place whether that's tomorrow or six
| | 03:36 |
months down the line.
We can verify that it doesn't break
| | 03:38 |
something we did earlier or it makes life
much easier when building application,
| | 03:43 |
adding features, fixing bugs.
So with test driven development we're not
| | 03:47 |
beta testing, stress testing, acceptance
testing, ability testing, we're unit
| | 03:52 |
testing but, that is not all we are doing
with test driven development there's one
| | 03:57 |
more idea that we are missing and that's
up next
| | 04:00 |
| | Collapse this transcript |
| What is TDD?| 00:01 |
The next couple of hours focuses on
deeply on creating and using these
| | 00:04 |
automated unit test.
But this course isn't called foundations
| | 00:08 |
of programming unit testing, it's
Foundations of Programming Test-Driven Development.
| | 00:13 |
And let me be very specific, doing unit
testing is not the same thing as doing
| | 00:18 |
test-driven development.
You see, having these automated unit
| | 00:22 |
tests, it's great, it's amazingly
helpful, very worthwhile.
| | 00:25 |
And we're going to do those unit tests,
but to do TDD, we take that idea one step further.
| | 00:31 |
So, what's the difference?
Well, when most developers first
| | 00:35 |
encounter this idea of automated unit
tests of writing code that tests our
| | 00:40 |
code, they understandably make the
assumption that this is how the process goes.
| | 00:44 |
First, we would write a bunch of our
normal application logic.
| | 00:48 |
And then, we would write our automated
unit test to check and verify the logic
| | 00:53 |
that we just wrote.
So as an example, we might write a method
| | 00:57 |
called calculate loan.
We'll add some functionality to that,
| | 01:00 |
compile that.
And then after we've written, we'd think
| | 01:04 |
about creating a few tests, what kind of
values might I pass in and verify those
| | 01:09 |
results is what we expect?
And this is unit testing.
| | 01:12 |
We are testing and validating an
individual method down to the individual
| | 01:17 |
unit in the code, but this is not
test-driven development.
| | 01:21 |
Understand that TDD has the same piece
two elements a piece of application for
| | 01:25 |
that logic but the test for that unit.
It turns the process completely around.
| | 01:30 |
What test developers asks of us as
developers is to write the test first
| | 01:36 |
before we write the application logic.
That might sound counter-intuitive, if
| | 01:41 |
not indeed impossible.
But Simon, I hear you say, I can't
| | 01:44 |
exactly test a method I haven't written
yet.
| | 01:46 |
Actually, you can, and in test-driven
development, we do, and not just once or
| | 01:52 |
twice, but all the time.
We will write tests that attempt to
| | 01:56 |
instantiate an object, where we haven't
written a class for that object yet.
| | 01:59 |
We will write tests that call a method
that doesn't exist and we will run those tests.
| | 02:04 |
And the first time we run those tests,
they should fail depending on the
| | 02:08 |
language, they may not even compile or
they might run and then tell us, well, I
| | 02:12 |
can't find this method, I can't find this
class.
| | 02:16 |
But we want the test to fail, because
after all, if it doesn't fail, we have
| | 02:20 |
some other kind of problem going on and
this is the fundamental first step of
| | 02:25 |
every day test-driven development.
The core distinction between doing TDD
| | 02:29 |
and not doing TDD.
That before we write any new code, we
| | 02:34 |
first write a failing test and only after
it fails do we write the application
| | 02:39 |
logic to pass that test.
And we write the minimum necessary code
| | 02:44 |
to just pass the test.
One thing it immediately removes is the
| | 02:48 |
common situation where we create a new
class or a new method, and end up staring
| | 02:53 |
at blank screen, trying to juggle in our
heads all of the things this might need
| | 02:57 |
to do today and tomorrow and in the
future.
| | 03:00 |
All of this speculative code that we're
trying to come up with that is quicksand
| | 03:04 |
for every developer.
Now, just pass the test, this one test.
| | 03:08 |
It keeps us focused, this gives us
clarity on exactly what we're doing at
| | 03:12 |
any one point.
Don't do anything more than pass this
| | 03:15 |
small test and this is what is meant by
test-driven development.
| | 03:20 |
The tests drive our development.
So TDD is not just development that uses
| | 03:26 |
unit tests.
Test-driven development as a process and
| | 03:29 |
technique is all about the priority and
the position that we give to those unit tests.
| | 03:34 |
Now, for all of who are looking for is to
know more about automated unit testing,
| | 03:38 |
you will find this course very helpful
because that is what we're doing.
| | 03:42 |
But just know that I will take a TDD
approach to unit testing, shifting the
| | 03:48 |
idea of testing as an afterthought,
something that we only do later, to
| | 03:53 |
putting the tests up front.
Figure it out first, let it drive what
| | 03:57 |
you write.
I'm saying this multiple times, because
| | 03:59 |
for most developers this is a very subtle
change in priority that has a dramatic
| | 04:05 |
impact on the way that you approach and
write code.
| | 04:08 |
So this course is focused on automated
unit testing.
| | 04:10 |
Having a systematic, repeatable process
that is totally integrated into our
| | 04:16 |
regular project and with TDD, what we'll
use these unit tests to drive everything
| | 04:22 |
else that we do.
| | 04:22 |
| | Collapse this transcript |
| Common questions and concerns| 00:01 |
I'm going to take a moment to deal with a
couple of questions that you may already
| | 00:04 |
have depending on your background.
Because test room development is
| | 00:08 |
something when I teach it's common to get
initial push back.
| | 00:11 |
If i have a group of very experienced
developers encountering TDD for the first time.
| | 00:16 |
I expect quite a lot of resistance
because it does feel different to the way
| | 00:20 |
they're used to working.
It's like suddenly driving on the wrong
| | 00:23 |
side of the road.
You're doing all the same things, but
| | 00:27 |
everything feels little unnatural.
It feels alien.
| | 00:30 |
So expect that.
And want to avoid is taking that initial
| | 00:34 |
weirdness as a reason to And validate any
of this before you begin.
| | 00:38 |
So do take care that you're not trying to
come up with a this does not apply to me factor.
| | 00:44 |
The, I don't really understand what it is
yet, but I'm pretty sure test driven
| | 00:47 |
development won't work for me, or for my
project, or for my team or for my environment.
| | 00:53 |
By all means, be critical.
Bring your brain.
| | 00:57 |
But do try this.
I've never met a developer that hasn't
| | 01:00 |
found it worthwhile to just take a few
hours to work through these ideas.
| | 01:03 |
And typically, the response that I get at
the end, from even the most skeptical
| | 01:07 |
upfront developer is okay, that wasn't
what I thought it was going into it, and
| | 01:13 |
yes I can see how this would be really
useful.
| | 01:16 |
But here's a handful of common questions
and concerns I get upfront.
| | 01:20 |
First, I have heard that test-driven
development doesn't work for everything.
| | 01:26 |
Well, that's absolutely true, there are
certain problems in programming where
| | 01:30 |
automated unit test are not the only
thing you need to guarantee the code is perfect.
| | 01:36 |
Some situations with multi-threading,
security options testing user interfaces,
| | 01:43 |
some parts of game development are
well-suited and we will talk more about this.
| | 01:47 |
But bear in mind, unit testing does not
replace all other kinds of testing and
| | 01:54 |
isn't intended to and even in places
where unit testing may not apply to 100%
| | 01:59 |
of your code.
It may still be very worthwhile for 80 or
| | 02:02 |
90% of them.
And the next thing that people wonder is,
| | 02:06 |
so am I supposed to write all my tests
before writing any code?
| | 02:10 |
No, not at all, let's get a sense of
proportion here.
| | 02:13 |
If you're thinking that this breaks down
as January, write all your test, have a
| | 02:19 |
big test fest and then in February start
writing code that is way off.
| | 02:24 |
It's not even Monday write a test,
Tuesday write code to pass the test.
| | 02:29 |
No, it's more like Monday at 9 a.m.
Monday at 9 a.m.
| | 02:35 |
and 20 seconds.
See that test fail.
| | 02:38 |
Monday 9 a.m.
and 30 seconds, start writing code to
| | 02:42 |
pass the test.
Very small steps repeated often.
| | 02:47 |
Creating tests isn't and should never be
any kind of major road block, barrier or
| | 02:52 |
even speed bump to writing code.
It should be the tiniest amount of work.
| | 02:57 |
You're just about to write a new method.
You pause, take a few seconds.
| | 03:01 |
You think, how would I call this method
to prove that this is about to work, or
| | 03:06 |
that it doesn't work?
And you would write that test.
| | 03:09 |
You would verify it fails, and you would
then start writing code to pass the test.
| | 03:14 |
Now, another question I will sometimes
get is, we have a team of testers, so do
| | 03:19 |
we use them To write these unit tests.
Now, this used to be quite common in
| | 03:24 |
large scale development.
But these days, if you have the wonderful
| | 03:27 |
luxury of having an independent team of
testers or even just separate people on
| | 03:32 |
your own team, well that's usually for a
different kind of testing.
| | 03:36 |
It's for a quality assurance stage or
acceptance or integration with other
| | 03:40 |
systems and this is not what we're
talking about here.
| | 03:43 |
We are talking runway level, day-to-day,
minute-to-minute programming.
| | 03:48 |
If you're writing code, you need to write
your own unit test.
| | 03:53 |
Using anybody else would impose a
completely different drag on the system.
| | 03:58 |
Sure, you would still use your testers
but not on this.
| | 04:02 |
But the most common resistance I get
either, in person or online is really
| | 04:09 |
just a misrepresentation.
Its the all or nothing logical fallacy
| | 04:13 |
that you will also hear when people talk
about scrum or agile methodologies or
| | 04:18 |
design patterns or any other software
technique.
| | 04:21 |
Oh, the TDD fanboys say this fixes
everything and I know it doesn't so we're
| | 04:26 |
not going to use it, which is kind of
like saying, well, anesthetic doesn't fix
| | 04:31 |
every problem in medicine so we're not
going to use that either.
| | 04:34 |
Well, it's true; it doesn't fix
everything.
| | 04:37 |
But it's very nice to have sometimes.
But if it makes you happy, I guarantee,
| | 04:42 |
test-driven development will not by
itself fix every one of your software
| | 04:46 |
development issues.
I also promise that object orientation won't.
| | 04:51 |
That design patents won't.
That agile methodologies won't.
| | 04:54 |
But I also guarantee that all of these
skills are excellent to have.
| | 04:58 |
They're great for your development
ability, your competence, and your
| | 05:01 |
confidence about what you're doing.
They're great for your career.
| | 05:04 |
There is simply no downside to knowing
how to do test-driven development.
| | 05:09 |
Alright, enough.
Let's get into what we need to get
| | 05:13 |
started with it.
| | 05:14 |
| | Collapse this transcript |
|
|
2. Getting StartedUsing unit testing frameworks| 00:00 |
When I said that a large part of what
we're doing here is writing code that
| | 00:04 |
tests our code, your brain may have even
wandered off on a little tangent.
| | 00:08 |
And thought about what that new code
might look like.
| | 00:11 |
And perhaps you thought, well if I'd
written a new class and I wanted to test
| | 00:14 |
it I guess I could create another new
class call this one Tester.
| | 00:18 |
In it I'll instantiate that new class I'd
just written.
| | 00:22 |
I'll call a method on that new object,
I'd check the result and have a condition
| | 00:26 |
that would.
Fire off a message, either way.
| | 00:28 |
You could do this.
It is reasonably simple code.
| | 00:31 |
But it would be very tedious code to have
to write a lot of this, and we will not
| | 00:36 |
have to do this.
Instead, there are unit testing
| | 00:40 |
frameworks we can use.
Things like JUnit for Java, NUnit for .NET.
| | 00:45 |
unittest for Python.
These are libraries of code.
| | 00:48 |
Already written, already proven that help
us do automated unit testing.
| | 00:52 |
Providing a lot of that basic plumbing.
The duplicated structure we'd otherwise
| | 00:56 |
have to write.
Now, it would be easy to assume that if
| | 00:59 |
you learned how to do this in Python and
then had to go to Java, or to C++, or
| | 01:04 |
Objective-C, you'd have to learn a whole
new approach to testing.
| | 01:07 |
But, luckily, that is not the case.
And I can make this course work for
| | 01:11 |
multiple languages.
Because most of these testing frameworks
| | 01:15 |
are based on the same ideas, the same
common ancestor.
| | 01:19 |
So, there are enormous similarities
between unit testing in Python, unit
| | 01:23 |
testing in Java, unit testing in .NET,
and Objective-C and many more.
| | 01:28 |
Why?
Because history, that's why.
| | 01:31 |
Back in the 90s, a gentleman by the name
of Kent Beck developed a simple unit
| | 01:35 |
testing framework now referred to as
SUnit in the Smalltalk programming language.
| | 01:40 |
And this provided a basic structure of a
helping developers easily create and run
| | 01:44 |
unit tests without duplicating a lot of
this unnecessary code.
| | 01:48 |
Now SUnit wasn't and isn't particularly
complex or even large, but it formalized
| | 01:53 |
some terms and concepts that have become
part of the common unit testing
| | 01:57 |
vocabulary we will explore.
Things like Test fixtures and setup and teardown.
| | 02:03 |
And this became very popular in the
Smalltalk world and was converted from
| | 02:07 |
Smalltalk into a version for Java called
JUnit, which was and still is the most
| | 02:13 |
popular and widespread unit testing
framework.
| | 02:16 |
It really took off as JUnit, so the same
idea was converted for .NET, and
| | 02:21 |
converted for Python, and for C++.
And there's a version for Objective-C.
| | 02:26 |
So, we have NUnit, PyUnit, CppUnit,
OCUnit, and many more.
| | 02:31 |
And these shared the same core ideas of
how to create, run, and manage your
| | 02:36 |
automated unit tests.
And there are now dozens and dozens of
| | 02:40 |
unit testing frameworks, in pretty much
any language you could wish for.
| | 02:44 |
And there's often several competing
frameworks for the same language.
| | 02:47 |
If I look at the Wikipedia page for the
list of unit testing frameworks we'll
| | 02:51 |
find entries for any language you're
likely to need.
| | 02:54 |
And often times multiple testing
frameworks for the same language.
| | 03:00 |
Now, if a unit testing framework is based
on those original ideas from the
| | 03:04 |
Smalltalk days, it is considered an xUnit
testing framework.
| | 03:08 |
xUnit is this generic term to
collectively group these SUnit, JUnit,
| | 03:12 |
OCUnit, CppUnit together, as coming from
the same ideas.
| | 03:17 |
And it is xUnit style of unit testing
we'll be doing in this course.
| | 03:22 |
Now, are all unit testing frameworks
xUnit?
| | 03:25 |
Well, no they are not.
xUnit style frameworks are by far the
| | 03:29 |
most common but there are some competing
ideas.
| | 03:31 |
So, if I go to this Wikipedia entry for
unit testing frameworks and pick one of
| | 03:35 |
the languages like C++, what I'll see is
the several different entries.
| | 03:39 |
But one of the columns here is basically
asking, is this an xUnit style testing framework?
| | 03:45 |
Most of the time.
That is going to be yes.
| | 03:48 |
Not all of the time, but most of the
time.
| | 03:50 |
Now I will not in this course be
comparing any of the different per
| | 03:55 |
language options.
I will leave that as an exercise for the viewer.
| | 03:58 |
But (UNKNOWN) to say you don't really
have to worry about all the different
| | 04:02 |
options for all the different languages.
Because most languages have one typical
| | 04:07 |
xUnit framework that is associated with
it.
| | 04:09 |
And I will use the most common one when
doing any demos.
| | 04:13 |
So, unit testing frameworks are there for
just about every conceivable language and
| | 04:17 |
environment although the culture.
And community that evolves and exists
| | 04:21 |
around different languages deeming that
its uptake and usage can be quite different.
| | 04:26 |
Unit testing is extremely common in the
Java world.
| | 04:30 |
If you're a Java developer looking for a
job, the expectation that you would know
| | 04:34 |
how to use JUnit is pretty high.
And that's much higher, than say, an
| | 04:39 |
average Objective-C developer being
expected to know OCUnit.
| | 04:43 |
An much of this is, simple history.
JUnit was the first unit testing
| | 04:47 |
framework, to take the Smalltalk ideas to
a wide commercial audience, the first to
| | 04:52 |
really popularize these.
The first books on test driven
| | 04:55 |
development were Java focused, and it
really snowballed from there.
| | 04:58 |
So, although the ideas originated in
Smalltalk, most of the xUnit frameworks
| | 05:04 |
are really based on JUnit and it's
popularity, rather than the official
| | 05:08 |
Smalltalk ancestor.
It might sound like your first task is to
| | 05:12 |
spend hours going through dozens of
different options for the different
| | 05:17 |
available languages.
And identifying the unit testing library
| | 05:21 |
that you're going to work with, but
usually you won't have to.
| | 05:24 |
Because if you were working with a
general purpose programming language,
| | 05:28 |
unit testing frameworks are probably
already there.
| | 05:30 |
They're baked into your language, or at
least your IDE, making it very easy to
| | 05:35 |
get started without downloading or
installing anything.
| | 05:39 |
As an example, if I have the standard
eclipse IDE for doing Java.
| | 05:44 |
And I don't have any kind of project
created here.
| | 05:46 |
I just jumped over to eclipse.
What I'm going to find if I go to my File
| | 05:50 |
option, is the option to create a new
JUnit Test Case, so JUnit support is in
| | 05:57 |
there already.
If I'm on the PC side with visual studio,
| | 06:00 |
with C# or VB.NET, I also have built in
support for creating tests already there.
| | 06:07 |
And even when doing Objective C
development on the Apple side, which
| | 06:10 |
doesn't have a huge culture of test
driven development, the OC unit testing
| | 06:15 |
framework has been baked into XCode since
2005.
| | 06:19 |
I can just create a new project and one
of the options that I'll find is to
| | 06:22 |
include unit tests when I'm doing that,
and I have full support for OC unit, unit test.
| | 06:29 |
And unit test support is actually
included with the standard library in
| | 06:33 |
Python as it is with Ruby.
But the only place you won't always find
| | 06:37 |
it is with more informal casual
languages, say scripting languages like
| | 06:41 |
JavaScript, where the demand for unit
testing is no where near as common.
| | 06:45 |
And you wouldn't expect built in support
for that.
| | 06:48 |
In that case you might find surfing
through this list of unit test frameworks
| | 06:52 |
useful, so you can find an external unit
testing library and download that yourself.
| | 06:57 |
| | Collapse this transcript |
| Understanding assertions| 00:01 |
Before I write my first line of testing
code, I want to talk about the most basic
| | 00:05 |
word in unit testing, one that we will
use all the time and that word is assert.
| | 00:10 |
To assert is to state something
positively.
| | 00:14 |
I assert that the earth moves around the
sun.
| | 00:17 |
I'm not asking a question.
This is not an if.
| | 00:22 |
I'm not inviting opinion.
I'm not trying to change or alter
| | 00:25 |
anything, I am simply stating something
to be true.
| | 00:28 |
Now, these assertions can be positive.
I'm asserting something is true.
| | 00:32 |
I assert there are only 30 days in April.
Yeah, but assertions could also be
| | 00:37 |
negatively, so I'm asserting something is
not true.
| | 00:40 |
I assert the book War and Peace was not
written by Ernest Hemingway.
| | 00:46 |
But I'm not presenting any of these as
opinion.
| | 00:48 |
I'm saying these are facts.
Now, it is possible an assertion I make
| | 00:52 |
could be wrong.
But if my assertion is wrong, then there
| | 00:56 |
is something fundamentally flawed with
whatever I'm talking about.
| | 01:00 |
So we take this idea over to programming.
We can make assertions at any point in
| | 01:04 |
our code.
At this point in my code, I assert these
| | 01:08 |
two strings are equal.
At this point in my code, I assert this
| | 01:12 |
integer is positive.
At this point in my code, I assert this
| | 01:15 |
object is not null.
I'm not asking questions.
| | 01:19 |
These are not if statements.
I'm not inviting opinion.
| | 01:22 |
I'm not trying to change any of these
things.
| | 01:24 |
I'm simply stating something to be true.
Now, an assertion is sometimes referred
| | 01:29 |
to as a sanity check in code.
It is a simple way for us to stick a flag
| | 01:34 |
in the ground to explicitly state that we
have a fundamental assumption about what
| | 01:38 |
is true in our code at a particular line.
You might think, well, aren't I doing
| | 01:43 |
this already?
I mean, I check a lot of things in my
| | 01:45 |
code with if statements and switch
statements, but we are not talking about
| | 01:50 |
the general flow of a program.
And we're not even talking about graceful
| | 01:54 |
error handling or exception handling.
You still do those things.
| | 01:58 |
But assertions are different.
If an assertion fails, then your code is
| | 02:03 |
broken, or your assumptions about what is
going on, they're fundamentally flawed.
| | 02:06 |
Something is wrong in your development
and you need to fix it now.
| | 02:10 |
You need to find out why that thing
you're asserted is not true.
| | 02:14 |
So an assertion failing is not an issue
to be gracefully and programmatically
| | 02:19 |
handled in your code.
It is a reason for your program to error
| | 02:23 |
immediately on that line.
And we want to fail as soon as possible.
| | 02:27 |
There is no point in going forward.
Because, if we continue on but our
| | 02:31 |
earlier logic is flawed, our code isn't
correct, we may have really bad side
| | 02:36 |
effects, but only feel the impact of
those much much later and have to retrace
| | 02:40 |
our steps through multiple methods and
classes, so the sooner we find and fix
| | 02:44 |
it, the better.
So you don't use assertions to
| | 02:47 |
programmatically manage a complex
situation you might do with exceptions or
| | 02:53 |
air handling.
And you don't use assertions to generate
| | 02:57 |
helpful diagnostic dialogue boxes for the
end user.
| | 03:00 |
Because assertions aren't for the
engineers here, this is code that is only
| | 03:05 |
for us as programmers.
In almost all languages, if you've
| | 03:09 |
written an assertion in your
application's source code, they are
| | 03:12 |
stripped out of production code, using a
compiler directive or even just check box
| | 03:17 |
in your IDE.
So those assertions will be ignored in
| | 03:20 |
any shipping code, because an end user
should never see the effect of an
| | 03:24 |
assertion in code.
There's only two possible options for an assertion.
| | 03:29 |
If what you assert is true, nothing
happens.
| | 03:32 |
No messages are generated.
It's what we expected, it's business as usual.
| | 03:36 |
We just keep going on to the next segment
But if what you had said is false,
| | 03:40 |
there's a fundamental problem in the
code.
| | 03:42 |
Shut everything down.
Fail, and fail immediately.
| | 03:46 |
So how do we actually do this in a
language?
| | 03:48 |
Well, let's see that next.
| | 03:49 |
| | Collapse this transcript |
| Using assertions in programming| 00:00 |
Many languages have the assert keyword
built directly into the language itself
| | 00:05 |
or the foundational framework of that
language without even needing an external
| | 00:09 |
unit testing framework or library.
For example in Java or at least in
| | 00:13 |
version 1.4 of the language alment we
have he assert keyword.
| | 00:16 |
Anywhere in a regular message you can
just use the assert keyword and give it
| | 00:22 |
an expression so something like Assert x
greater than 10.
| | 00:25 |
That's it.
This doesn't need anything else.
| | 00:28 |
We execute this line just like this.
If the variable x is greater than 10, we
| | 00:33 |
will continue to the next line.
If it's false, this immediately throws an error.
| | 00:37 |
Now, we're not trying to run this assert
and then follow it with an if statement
| | 00:42 |
to check the result of doing the assert,
we simply assert something.
| | 00:46 |
And only if the assert fails will we
notice any impact.
| | 00:50 |
Likewise we don't then try to handle
this, we don't add code to attempt to
| | 00:54 |
gracefully react to this situation as we
might do with exception handling and
| | 00:58 |
having multiple (UNKNOWN) finally blocks,
it's really just this little assert
| | 01:03 |
statement, self contained by itself
wherever we need it...
| | 01:07 |
There's a couple of other things we can
do with the assert key word syntax and
| | 01:10 |
java but it's not necessary to get into
language specifics just yet.
| | 01:15 |
So let me show an equivalent in, say,
objective C.
| | 01:19 |
Here it's the N S assert key word this is
because many things in objective C come
| | 01:23 |
from the old next step days.
And we have this format.
| | 01:27 |
NSAssert, then the expression, the
condition that we're checking.
| | 01:31 |
And optionally we can add a string that
will show up as a log message if this
| | 01:36 |
assertion fails it would look something
like this.
| | 01:38 |
We are asserting that x is greater than
10.
| | 01:41 |
If this assertion fails, we'll output a
log message with an error saying x is not
| | 01:46 |
more than 10.
And other languages have a similar keyword.
| | 01:51 |
So is this what we're doing in this
course?
| | 01:53 |
Well, no, certainly not just this.
You could include this kind of simple
| | 01:58 |
code, just an assertion statement here
and there, directly in your application
| | 02:02 |
logic in your own classes, your own
methods, as a sanity check to cause an
| | 02:06 |
immediate error when testing and
debugging.
| | 02:09 |
And there is some value to that.
But I wouldn't dignify a simple, assert
| | 02:14 |
statement with the term unit test.
It's really just a one-line sanity check.
| | 02:18 |
because what we're doing in this course
is not just adding an assert here and
| | 02:22 |
there, directly in our normal application
code.
| | 02:25 |
We will be creating entirely new test
classes, entirely separate unit tests.
| | 02:31 |
Now we're still going to be doing a
search.
| | 02:33 |
But because we'll be using unit testing
frameworks you will find most of them
| | 02:37 |
provide multiple additional assert
methods to make it easier to read when
| | 02:42 |
we're asserting something to be true or
to be false or to be equal.
| | 02:46 |
So in Java as an example, with the JUnit
framework, rather than the kind of basic
| | 02:51 |
Assert keyword built directly into the
language.
| | 02:53 |
When we're using this framework you might
see lines like Assert equals, so that
| | 02:57 |
takes two arguments, two parameters so as
an example if we said assert equals 1,1
| | 03:03 |
this would pass do nothing.
If we said 1,2 that assertion is false we
| | 03:08 |
would fail, we would immediately throw an
error.
| | 03:10 |
So you were just passing whatever two
objects, two variables you are assuming
| | 03:15 |
to be equal.
And there are even some specialized
| | 03:18 |
methods for checking equality, like
assertArrayEquals.
| | 03:21 |
And this could take two object arrays,
two integer arrays, whatever you have.
| | 03:25 |
But we have other assert methods.
We have things like assertNotNull.
| | 03:30 |
We are saying this object is not null.
If the object is Null, this would throw
| | 03:35 |
an error.
The flip side of that, you might be
| | 03:37 |
asserting that something is Null.
Also, as you know, when comparing
| | 03:41 |
objects, there's a big difference between
having two objects that are equal in
| | 03:45 |
value and having two separate references
to the same object.
| | 03:50 |
So in JUnit, if we wanted to check that
two object references are actually the
| | 03:55 |
same underlying object, we have a special
assert: assertSame.
| | 03:59 |
And its flip side assetNotSame, which
would be different from asserting them to
| | 04:04 |
be equal to each other.
And more generally we have things like
| | 04:07 |
assertTrue with a condition or
assertFalse with a condition.
| | 04:11 |
Now all of these assert methods are void,
they don't return a value you just call
| | 04:16 |
them directly.
Passing in whatever parameters or
| | 04:19 |
conditions that you want to assert.
They either pass and continue onto the
| | 04:23 |
next statement or they fail and throw an
arrow.
| | 04:26 |
And you're not supposed to gracefully
handle that arrow.
| | 04:28 |
You're supposed to understand it and fix
it.
| | 04:31 |
Now there are a few other assert methods
and there are versions where you can add
| | 04:35 |
your own descriptive strings.
To provide a useful message if an
| | 04:38 |
assertion fails but this will do as an
example for now.
| | 04:42 |
I'm not trying to get you to remember all
of these methods, I'm just showing one of
| | 04:47 |
the benefits of using a unit testing
framework.
| | 04:50 |
So while that example was in Java, expect
exactly the same thing.
| | 04:54 |
Using a unit testing framework in other
languages as well.
| | 04:56 |
And the reason I show these right now and
talk about assertions early on is to keep
| | 05:02 |
in mind that while we'll cover a few
different ideas and techniques, the end
| | 05:06 |
goal of a unit test is to support us
making some kind of assertion.
| | 05:10 |
That if we create this object and then
call this method passing in these values,
| | 05:15 |
we then assert a result.
And because whatever I insert I assume to
| | 05:20 |
be true.
Successful assertions, successful tests
| | 05:24 |
simply continue.
We don't need to report them, we don't
| | 05:27 |
need to log every successful test we are
taking success as assumed.
| | 05:32 |
The only ones we want to bring our to
attention to of the assertions the fail.
| | 05:36 |
But these are unit testing frame works
will do more than just help us make
| | 05:40 |
assertions even specialized one.
They'll also help us do the initial set
| | 05:44 |
up if we need to create new objects or
use sample data in our tests.
| | 05:49 |
They help us do sample data in our tests.
They help us string multiple tests
| | 05:53 |
together so we could run multiple tests
at the same time.
| | 05:56 |
But running lots of tests comes a little
later.
| | 05:58 |
We need to start to see what one
particular test would look like.
| | 06:02 |
| | Collapse this transcript |
| Creating a test| 00:00 |
I'll talk later about how you might add
unit tests to an existing code base, but
| | 00:04 |
I'm going to start first from a
completely blank slate with a TDD test
| | 00:09 |
first mindset, to write a test before I
write any application code.
| | 00:13 |
So I'm beginning with nothing.
No code written at all.
| | 00:17 |
And let's say what I have in mind is to
make a very simple banking application.
| | 00:21 |
Okay, I get it.
That's a little conventional.
| | 00:24 |
It's a little dull.
But I'm not looking to make a cool
| | 00:27 |
project here.
I'm looking for clarity on these ideas.
| | 00:30 |
I'm with a bank account.
We have concepts everybody understands.
| | 00:33 |
Like balances, withdrawals, deposits, and
so on.
| | 00:37 |
And you might have do a little bit of up
front object oriented design.
| | 00:41 |
Sketch some things on a white border.
Even have A UML diagram or some use cases
| | 00:46 |
and user stories.
And that would be fantastic because those
| | 00:49 |
would make it much easier to come up with
your tests.
| | 00:52 |
But let us begin by imagining the
simplest bank account class in the world.
| | 00:58 |
And even a very straightforward UML
version of this so it's just a field to
| | 01:02 |
hold balance, there's a deposit method,
there's a withdrawal method, and yes I
| | 01:07 |
know we would have more detail, we would
have more properties and methods and i
| | 01:11 |
know you could take this and bring up
your code editor and just write this
| | 01:16 |
class right now, probably one handed...
But before doing that, before actually
| | 01:20 |
creating this class let's quickly think
about what a simple test for this might be.
| | 01:26 |
So what I'm going to do is just switch to
a very simple text editor, just so I can
| | 01:31 |
write a couple of things down.
Think about, well how would we prove what
| | 01:34 |
we're about to do works.
We'd create a new bank account object.
| | 01:41 |
We then call the deposit method passing
in, let's say 50.
| | 01:47 |
And check the balance is 50.
Then we withdraw 30.
| | 01:51 |
Check the balance is 20.
So our test is not just can we call the
| | 01:57 |
deposit method, can we call the withdraw
method.
| | 01:59 |
It's Did that call work after we call the
deposit method passing n 50, is the
| | 02:04 |
balance 50?
After we call withdraw passing n 30, is
| | 02:07 |
the balance now 20?
I'm doing here just a little bit of
| | 02:10 |
thought, just taking a few seconds before
I begin.
| | 02:13 |
And, no, you don't need to write these
always down in kind of pseudo-code plain
| | 02:17 |
English in A note pad or a text edit,
editor, it's just to kind of demo our
| | 02:22 |
thought process here.
Although, depending on how much design
| | 02:25 |
we've done, or even how much I've either
thought or not thought about the business
| | 02:29 |
problem I'm attempting to solve.
It's likely I'll write down a few notes
| | 02:33 |
to myself as I'm doing this.
Now sometimes they might be technical concerns.
| | 02:39 |
They might be things like, what's the
best data type I should be storing values in?
| | 02:44 |
What's the best way to create a unique
ID?
| | 02:46 |
Sometimes they might be related to the
business problem, so is there a
| | 02:49 |
limitation on the maximum amount I can
deposit at any one time?
| | 02:53 |
Do I need to speak to somebody about
that?
| | 02:55 |
I'm just trying to write this down, so I
can come back to them later.
| | 02:57 |
But I am trying to stay focused on this
first task, creating a new object and
| | 03:03 |
making sure this deposit method works.
So let's do this.
| | 03:06 |
Let's do some test driven development.
Write an actual failing test and then
| | 03:10 |
pass the test.
| | 03:11 |
| | Collapse this transcript |
| Creating a test in Eclipse| 00:00 |
I'm going to do a test driven development
cycle in Eclipse here using Java as the
| | 00:04 |
language with Junit as the library but
again I will be as generic as I can.
| | 00:08 |
The language and the IDE is not the focus
here.
| | 00:11 |
So, even if you are a Java and Eclipse
person focus less on the syntax and
| | 00:15 |
specific menu items and just more on the
overall approach.
| | 00:19 |
So, I have no code at all.
I have an empty project here and I know I
| | 00:24 |
want to make that simple bank account
class I described a moment ago.
| | 00:28 |
So this is test driven development.
We begin not by adding that class, but by
| | 00:32 |
first adding a unit test.
So I'm creating a JUnit test case here,
| | 00:38 |
and I get this dialog box.
Now this is a place I can often hear that resistance.
| | 00:42 |
Well, how am I supposed to create a
meaningful unit test?
| | 00:45 |
Or even know what to name it, which is
what it's asking for right now, when I
| | 00:49 |
have nothing to test?
Well, it is true that we have no code.
| | 00:53 |
But I do have an intention, and we always
have an intention when creating our test.
| | 00:58 |
I know that I want to make a bank account
class.
| | 01:00 |
That's what I'm about to do.
That's the reason I'm in this environment.
| | 01:04 |
So I will name this one accordingly.
It's asking me for a name here.
| | 01:07 |
I'm going to call this BankAccountTest.
I will talk about naming tests in a
| | 01:13 |
moment, as well as some of these other
options.
| | 01:15 |
But I'm just going to go ahead and click
Finish.
| | 01:18 |
Eclipse is just popping up a dialog box
making sure that I can add any necessary
| | 01:22 |
libraries, that's fine.
Assume the equivalent in other languages.
| | 01:27 |
So it's created this file, BankAccount
Test.
| | 01:29 |
And it is its own independent class.
And eclipse has provided me with a bit of
| | 01:34 |
default code, this one method here.
Now I could actually go ahead and run
| | 01:39 |
this class right now, if I right click it
over here, I could choose to run as Junit test.
| | 01:45 |
It runs, and we have officially what's a
failure, this red bar here, and I'll come
| | 01:50 |
back to that in a moment.
because what's happening is if I want to
| | 01:53 |
run this as a unit test, it's going to
look inside this class and run any method
| | 01:57 |
that has this at sign Test annotation.
Other languages have their own
| | 02:02 |
equivalent, a little marker that we can
add to a method to say, hey this is a
| | 02:06 |
unit test.
So, I'm going to jump in here and take
| | 02:10 |
this bit of provided skeleton code, this
failure here, and just add my own test.
| | 02:15 |
I know that what I want to do is create a
new instance of this new BankAccount class.
| | 02:24 |
I want to then call the deposit method
and check whether that worked.
| | 02:32 |
Now even as I'm typing I can see that I'm
getting several detected errors and
| | 02:36 |
Eclipse can see, well there is no
BankAccount class.
| | 02:39 |
We're not even able to compile.
Eclipse, like many development
| | 02:43 |
environments does have some options where
it can help us generate some of this code.
| | 02:47 |
If I mouse over this I've got options to
create the class, bank account, and I'm
| | 02:52 |
going to go ahead and let it do that
because right now we couldn't go ahead
| | 02:55 |
and run.
Create class bank account I am just
| | 02:59 |
going to go ahead and accept all the
default options for right now I am trying
| | 03:01 |
to stay simple as possible.
So we have this now bank account class
| | 03:05 |
absolutely fine jump back over to the
test I will not getting any complaints on
| | 03:09 |
that first line but I am getting
complaints on the second because it's
| | 03:13 |
detecting that there is no deposit method
in the bank account class.
| | 03:17 |
We do have another quick fix available.
So for purposes of time, I'll select that.
| | 03:23 |
It's gone ahead and added a public void
deposit method here that takes a
| | 03:27 |
parameter of one integer.
I'm going to leave it as that for right now.
| | 03:32 |
Jump back over to my test code and it's
finally complaining about this last line here.
| | 03:37 |
What I want to do is the assert.
I'm using the assert equals method in
| | 03:41 |
Junit which takes two parameters the two
things you're trying to compare.
| | 03:45 |
And I want to compare the balance in the
account object with the explicit value
| | 03:49 |
fifty.Again it's giving me an option to
do a field here.
| | 03:53 |
I could just manually type it myself.
I am intentionally adding the simplest
| | 04:02 |
thing that could possibly work.
In my final code, would balance of a bank
| | 04:06 |
account class be a public integer?
Well, almost certainly not, but I'm not
| | 04:10 |
worrying about that right now, I'm just
trying to get this test to run.
| | 04:14 |
Well, I'm not getting any complaints any
more about it, so the code seems
| | 04:19 |
syntactically correct, so I'm going to go
ahead and run it.
| | 04:23 |
Over here I have my Junit window, and I'm
actually going to drag this to the lower
| | 04:27 |
section so I can see my code when I have
them there.
| | 04:30 |
I'm going to right click my Bank Account
test, and just say, run as J-unit test
| | 04:37 |
Save and launch, the test fails.
My first real failing unit test and in
| | 04:43 |
Eclipse with Junit I'll see this bar down
here, the red bar.
| | 04:46 |
Not all IDE's and unit testing frameworks
have GUI support to show you a red bar
| | 04:52 |
when your test fails.
Sometimes you just have log messages, you
| | 04:55 |
have 17 succeeded one failed but it is
quite common.
| | 04:59 |
The idea of a red bar for failing tests.
A green bar for successful tests.
| | 05:04 |
And sometimes you'll hear the three word
phrase red green refactor as a quick
| | 05:10 |
summary of the test-driven development
cycle.
| | 05:12 |
Red, make your test fail.
Green, make your test pass.
| | 05:16 |
Refactor, make the code right.
And then just rinse and repeat this.
| | 05:20 |
But where red, the test runs, but it
fails.
| | 05:23 |
Why is the assertion failing?
And that's what is failing here.
| | 05:26 |
Well it's because my deposit stub may
actually exist.
| | 05:31 |
I can call it, but it doesn't do
anything.
| | 05:33 |
I didn't add any functionality.
Deposit being passed in with an integer
| | 05:37 |
really what I need to do is add that to
the balance.
| | 05:43 |
I'll save that.
I want to run this again.
| | 05:45 |
I could right click the bank account test
class, or I could use the Menu option
| | 05:50 |
here and select to run this as a Junit
test.
| | 05:54 |
It runs again.
Now we have the green bar.
| | 05:56 |
We have passed the first test.
Now here's the thing, if I had not been
| | 06:00 |
talking and talking this would've taken
me what?
| | 06:03 |
About 30 seconds if that and this is an
example of how fast you would expect to
| | 06:08 |
work in test driven development.
| | 06:10 |
| | Collapse this transcript |
|
|
3. Working with TestsThe process of TDD revisited| 00:00 |
There's several ways the basic idea of
test driven development can be described.
| | 00:04 |
We have this phrase red green re-factor
as a quick summary of the TDD process.
| | 00:11 |
Red, make a test that fails.
Green, make that test pass.
| | 00:16 |
And then re-factor.
Make it right.
| | 00:18 |
And this isn't done once.
This is a cycle.
| | 00:21 |
We repeat that throughout the lifetime of
our project.
| | 00:24 |
We're taking a different approach.
I could even perhaps say that test room
| | 00:28 |
development has two simple steps.
Step one, before you write any new code,
| | 00:33 |
you first write a failing test.
And step two, pass the test then go back
| | 00:37 |
to step one and keep repeating this.
This is technically accurate, this is TDD
| | 00:43 |
but that's too simplistic, it doesn't
really give us any guidance.
| | 00:46 |
I could break this apart a little bit and
say instead that test-driven development
| | 00:50 |
has six steps.
Step one, we write a test.
| | 00:54 |
Step two, we watch that test fail.
We go red bar.
| | 00:57 |
Step three, we will quickly write an
application code to pass the test.
| | 01:01 |
And we're talking here about the simplest
thing that could possibly work.
| | 01:05 |
Step four, pass the test.
Go green.
| | 01:08 |
Now step five, importantly we now
refactor it.
| | 01:11 |
We knock that code into shape.
Particularly this idea of removing duplication.
| | 01:16 |
That sounds like a throwaway phrase here
but it's really quite important.
| | 01:19 |
I will talk a lot about what removing
duplication means in the context of
| | 01:24 |
jumping between test code and application
code.
| | 01:28 |
And then after we've refactored, we want
to make sure we keep at a green bar, we
| | 01:32 |
pass that test again.
But whether I want to use two steps or
| | 01:37 |
six steps or I'm sure I could come up
with the ten rules of test-driven
| | 01:42 |
development or the five phase of TDD
however I wanted to do it.
| | 01:45 |
As the test-driven development is a
simple idea.
| | 01:48 |
Test then code.
A very small test then a small amount of code.
| | 01:52 |
And repeat that hundreds or thousands of
times throughout a project.
| | 01:57 |
And notice both with the demo that I did
a moment ago and as we go forward this
| | 02:01 |
one thing, how quickly and continuously
we shift from writing test code and to
| | 02:07 |
writing application code and back again.
This is not as some people initially fear.
| | 02:11 |
We create a massive test project.
We work just on that for a while.
| | 02:16 |
And then we close that all down.
We switch everything over to regular code.
| | 02:20 |
We boot that up.
We work on that for a while.
| | 02:22 |
Close that all down.
Switch back over to the test.
| | 02:25 |
Run the test.
No.
| | 02:26 |
This is instant.
In test-driven development we do start on
| | 02:30 |
the test first but we're often over to
the application code in seconds.
| | 02:34 |
And then you start flipping almost
continuously back and forth between the
| | 02:38 |
task code and the application code.
This is and must be very lightweight to
| | 02:43 |
switch between them or you just won't do
it.
| | 02:45 |
But it's applying this idea.
Okay, that's what test driven development
| | 02:49 |
is, red, green re-factor and then repeat
that.
| | 02:53 |
But how do we do it?
That's the issue now.
| | 02:55 |
So what makes a good test, how many tests
should I have, how do I know when I have
| | 03:00 |
enough, how much code do I need to pass
the test successfully.
| | 03:04 |
What do I do when the situation changes.
What parts of my code are tested like
| | 03:10 |
this and parts aren't.
What do I do with my test when I'm done?
| | 03:14 |
And it's these questions and quite a few
others that we'll be getting into in the
| | 03:18 |
rest of the course.
A lot of the subtle impacts and changes
| | 03:21 |
that come from that simple shift in
priority of how we approach development.
| | 03:25 |
| | Collapse this transcript |
| Adding tests and removing duplication| 00:00 |
So let's keep going.
Test driven development is and should be
| | 00:03 |
always about very quick cycles, so I know
that this current test works where we're
| | 00:08 |
depositing and checking.
I'm going green bar, if I look at the
| | 00:11 |
notes that I had we have the next task
which is withdrawing.
| | 00:14 |
So making sure that I am in my test code
here...
| | 00:18 |
I'll add a line to call the withdraw
method and then do another assert.
| | 00:23 |
Not surprisingly we're getting a
complaint here that is detecting there is
| | 00:31 |
no withdraw method.
If I mass over I have got the quick fix
| | 00:34 |
to create the method in my bank account
class I will do that.
| | 00:39 |
I'll leave that as is.
Which means it's got no actual implementation.
| | 00:43 |
Just save that and run this test again.
Excellent we've gone red bar, we've failed.
| | 00:51 |
We need to go green.
So over in my test, what I'm asserting is
| | 00:54 |
that after we have withdrawn 30.
We're then going to check the balance for
| | 00:59 |
being equal to 20.
So if I flip over to the actual class
| | 01:02 |
itself, well I'm going to intentionally
write some terrible code here.
| | 01:06 |
Because here's the quickest possible way
I could make this work.
| | 01:10 |
Just set balance to 20 go ahead and run
this test again.
| | 01:16 |
Now we go green bar.
So we've gone red.
| | 01:19 |
We've made it fair.
We've gone green, we've made it past.
| | 01:21 |
Now it's re-factored, we make it right.
And particularly removing duplication.
| | 01:27 |
See some of our code already smells.
Things like using a public integer for
| | 01:31 |
the balance.
But this particular line stinks to high
| | 01:35 |
heaven in our actual bank account class
because now we're always going to set the
| | 01:39 |
balance to 20.
So, here's what we mean by removing duplication.
| | 01:43 |
Usually, when we talk about code
duplication, we're talking about blocks
| | 01:46 |
of code being duplicated within class.
Now, we should notice those anyway.
| | 01:51 |
But in test driven development, the extra
thing to be attentive of is duplication
| | 01:55 |
of code, or particularly of data, between
our application code and our test code.
| | 02:02 |
Now, here's the thing: we have this
little piece of literal data being
| | 02:06 |
written here, the number 20 that exists
both in the test code and in the
| | 02:09 |
application code.
Of course, this withdrawal method should
| | 02:12 |
not be setting to this fixed value.
It should just be subtracting it from
| | 02:17 |
whatever the parameter in this is being
passed in.
| | 02:20 |
Now while this is obviously a really
simple example and you're very unlikely
| | 02:25 |
to have written this kind of level of
really bad code.
| | 02:28 |
It's the habit of starting to notice any
kind of duplication between your test and
| | 02:34 |
your code that's an essential habit to
get into.
| | 02:36 |
Particularly if you are talking about
things like literal values.
| | 02:41 |
Now as we're doing this, it is very
common to see things that we want to take
| | 02:44 |
note of, but we're trying to stay focused
on one test at a time.
| | 02:48 |
So I'm trying to make my withdrawal
method works right now.
| | 02:51 |
But let's say this public integer balance
is really bugging me, well, what I would
| | 02:55 |
probably just do is add that as a note to
myself in my little list here.
| | 03:03 |
And you do want to have some kind of to
do list, some way of persisting these.
| | 03:07 |
Whether that's a causal text file or a
formalized (INAUDIBLE) list of tasks or
| | 03:12 |
even just scribbled things on a post it,
test driven development doesn't dictate this.
| | 03:16 |
You need some way to persist open issues,
and you want to be able to do this quickly.
| | 03:20 |
I don't want to have to create a new
online bug case or bug report for every
| | 03:25 |
single thing that comes to mind.
I just need to be able to scribble them
| | 03:28 |
down so I can come back to them.
Some of these I'll be able to fix myself.
| | 03:32 |
Some maybe a prompt for discussion with
other team members.
| | 03:35 |
So, jump back over here.
So let's try running this test again.
| | 03:39 |
It's still telling me I'm not always
saving.
| | 03:41 |
Let me just check that check box so we
always save before launching.
| | 03:45 |
And we've gone green bar.
So red green re factor.
| | 03:48 |
So flipping very quickly between the test
code and the application code.
| | 03:53 |
Saving it running it just repeatedly in a
matter of seconds.
| | 03:57 |
And being conscious of anything that
comes to mind and starting to write that
| | 04:00 |
stuff down.
We're not trying to avoid having any issues.
| | 04:04 |
The idea is that TDD will help us ask and
then answer a lot of these design
| | 04:08 |
questions as we're working our way
through them.
| | 04:11 |
| | Collapse this transcript |
| Testing privacy| 00:00 |
So in my simple text-based to-do list
here, I really need to start organizing
| | 00:04 |
it a little bit to make sure that I can
keep track of which things have actually
| | 00:08 |
been done and which things are still
to-do.
| | 00:11 |
because the process of moving from one
state to the other is going to be
| | 00:15 |
actually pretty quick.
So, I have this note here that balance
| | 00:18 |
should be private, now I could argue this
is not really adding any new
| | 00:22 |
functionality, it's just a re-factoring,
an improvement to the existing code.
| | 00:27 |
So I'm going to jump over to my bank
account class here, where I've got public
| | 00:31 |
int balance.
Just double checking that all my tests
| | 00:34 |
are running as little JUnit tests.
Yeah, we've got green bar.
| | 00:38 |
So go ahead, make a change to the code.
Change this to private.
| | 00:42 |
Save that.
Run the test again and we've got errors.
| | 00:47 |
I don't even get as far as running that
test.
| | 00:50 |
If I jump over into the test code what I
can see is the two places where I'm
| | 00:54 |
trying to directly access the balance
field are not letting me do this anymore.
| | 00:59 |
Now this is a good thing, this is good
object oriented practise to make as many
| | 01:04 |
things private in your class as possible.
So how we deal with it, and this is one
| | 01:08 |
of those areas that's going to differ a
little bit based on language.
| | 01:11 |
But the idea is, I want this balance to
be readable from outside of this class
| | 01:15 |
but not directly changeable from outside
of the class.
| | 01:19 |
So I'll keep this field as private, and
just add a simple getter method to get
| | 01:24 |
that value.
I'm not going to create a setter because
| | 01:31 |
I don't want anything to be able to
directly change this balance field
| | 01:34 |
without going through either the deposit
or withdrawal methods, or any other
| | 01:38 |
method that I create later on.
So, jump back over to the test.
| | 01:42 |
We'll just change these, and there are
often quicker ways with fixits to clean
| | 01:49 |
this up, but I wanted to make sure I only
had a getter and not a setter.
| | 01:52 |
Save that.
Go ahead and run this.
| | 01:56 |
We got green bar, we're good.
Again, a very simple example.
| | 02:00 |
But the idea of how, a quick change to
our code to improve it, the benefit of
| | 02:05 |
having these unit tests is I can easily
see if there's, some kind of other impact
| | 02:09 |
that I wasn't immediately envisioning.
So just having these tests, being able to
| | 02:13 |
run them all the time, very, very useful.
| | 02:15 |
| | Collapse this transcript |
| Creating multiple test methods| 00:00 |
I'm looking at my unit test code.
And right now, my test is this one method
| | 00:04 |
just called test, which is testing two
methods in my bank account class.
| | 00:08 |
The deposit method and the withdrawal
method within a CERT for each one.
| | 00:11 |
And while this is a simple and easy
enough test to read, it is more common to
| | 00:16 |
create separate methods in the unit test
code, testing the separate methods in the
| | 00:20 |
application code.
So I'm going to split this up into one
| | 00:23 |
test for deposit.
And a different test for withdraw.
| | 00:25 |
Because we really want our test to be
small, self-contained, simple, easy to
| | 00:30 |
read, easy to change.
And if I get into the habit of mixing
| | 00:33 |
multiple tests together for multiple
methods in my application code.
| | 00:37 |
Then soon they really won't be.
Now for purposes of time, I'm just going
| | 00:41 |
to copy this entire method signature and
duplicate it.
| | 00:45 |
Using JUnit in Java, we have this at sign
test annotation, which is what is telling
| | 00:50 |
JUnit this is a test, go ahead and run
this method.
| | 00:53 |
I still can't have two methods with
exactly the same name.
| | 00:56 |
I'll call this one test withdraw and the
first one test deposit.
| | 01:01 |
It is not essential to have the word test
at the start and we'll talk a little bit
| | 01:06 |
more about naming in the next video.
So I'm going to pull the withdraw out of
| | 01:10 |
the test deposit version so it's just
limited to that one.
| | 01:14 |
And then in withdraw, what I'd actually
like to do is create an object, a new
| | 01:19 |
bank account object, and start it off
with a balance of 75.
| | 01:22 |
Then, I want to withdraw 50 from it and
assert that the result is going to be 25.
| | 01:29 |
Now, this exposes one issue here that i
can't create a bank account class within
| | 01:34 |
an immediate open balance.
I don't have the ability to try and put
| | 01:38 |
in say 75 in here when I'm instantiating
it.
| | 01:41 |
It's immediately going to complain.
Well, I'd like to be able to do that, so
| | 01:45 |
I'm going to go ahead, hover over this.
Eclipse will give me the option to create
| | 01:49 |
a constructor.
I could obviously just type that myself,
| | 01:53 |
it's pretty easy code.
And in this constructor, which it's
| | 01:56 |
jumped me over to the bank account class,
I'm simply going to use it to set balance
| | 02:00 |
to whatever was just passed in.
So, let's jump back over into the test code.
| | 02:06 |
We started off with 75, we withdraw 50,
25, looks good.
| | 02:09 |
But if I go ahead and run this, I have
problems.
| | 02:13 |
Because the fact in Java that I've
created a new constructor that takes an
| | 02:16 |
integer, means that the default
constructor I was using in the previous
| | 02:21 |
test, is no longer going to work.
Not a useful thing for having tasks.
| | 02:25 |
So, I will let Eclipse give me the quick
fix for this, to create the empty
| | 02:30 |
constructor, and in that in the code,
I'll just explicitly set balance to zero.
| | 02:35 |
(SOUND) Back and run our test again, we
have green bar.
| | 02:40 |
So the basic withdrawal does seem to
work.
| | 02:43 |
And we've got two separate methods here.
So you may wonder, is it meant to be a
| | 02:49 |
one-on-one relationship between one
method In our test code and one method in
| | 02:54 |
our application code.
Well, that is a start, but no.
| | 02:58 |
As soon as you start building methods
with a little more to them, with more
| | 03:02 |
logic in your application, with
conditions and switch statements and
| | 03:05 |
multiple paths, well, what is much more
common is that each method in your
| | 03:09 |
application code, your regular code, may
have several test methods associated with it.
| | 03:15 |
Each test focusing purely on one
significant path, one significant option,
| | 03:20 |
that your code might execute.
Well, let's go through an example.
| | 03:25 |
So if I jump over to my to-do list that I
was messing around with, I did have this
| | 03:28 |
note to myself.
What about negative amounts?
| | 03:31 |
So let's say I talk with my colleagues
and we decide quite generously that we're
| | 03:35 |
going to allow our bank accounts to be
overdrawn.
| | 03:38 |
But we will add a $5 penalty every time
we make a withdrawal and the balance is negative.
| | 03:44 |
And yes, this is intentionally simple.
We're focusing here on how we would test
| | 03:49 |
additional behavior that we're adding to
the system.
| | 03:51 |
Well we are test driven development, so
it's test first.
| | 03:54 |
I'm going to add a new test method.
So we will have two methods.
| | 03:58 |
That are going to be testing different
parts of this withdraw method in our
| | 04:02 |
actual application code.
Again we can't call on the same name so I
| | 04:06 |
have testWithdraw and I also have
testWithdrawWithPenalty.
| | 04:10 |
And again I will talk again about naming
in the next movie.
| | 04:13 |
With this one, I'm going to create a new
class, I'd like to start the class off
| | 04:17 |
with a balance of 10.
Then I am going to withdraw 20 from it.
| | 04:22 |
That should take us to minus 10, negative
10.
| | 04:25 |
But if we are successfully subtracting
another five for the penalty I should be
| | 04:30 |
able to assert that the result is
negative 15.
| | 04:33 |
This code looks okay.
It should be compiling correctly, we'll
| | 04:36 |
go ahead and run this unit test.
We've got red bar, so we need to go red,
| | 04:42 |
green, kind of the expected failure here.
That it should have given us a penalty,
| | 04:46 |
but I haven't added that yet.
So, jump over into the application code,
| | 04:50 |
find the withdraw method, that's where
I'm subtracting from balance, and I'm
| | 04:55 |
going to say, if the result is negative,
we are going to subtract a further five.
| | 05:04 |
Run the test again, and we go from red
bar to green bar.
| | 05:10 |
And this test class now has three
separate tests then.
| | 05:13 |
Testing deposit once, testing withdraw
twice with vector behavior.
| | 05:17 |
So, that starts getting us into the
question, how many tests do we need to write?
| | 05:22 |
And the answer is, how many do you need
so you can relax and be confident that
| | 05:26 |
your code works.
With deposit, for example, I don't need
| | 05:29 |
to have multiple tests here, to first
verify I can add 50.
| | 05:33 |
And then another test to verify I can add
51, and then another test to say I can
| | 05:37 |
add 55, because if this one works, we're
good with the basic behavior of this
| | 05:42 |
deposit method.
But I needed to for withdrawal, because
| | 05:45 |
we have a major condition that needs
tested.
| | 05:48 |
And that is the intention here.
Every significant path that is in your
| | 05:52 |
application, whether that's an if else,
or switch, or usage of polymorphism or a
| | 05:58 |
loop that may run in one situation but
not in another, well, they should all
| | 06:02 |
have different tests.
A question might be, in more complex
| | 06:06 |
code, how would you know that you've done
enough, when it's not so easy to just
| | 06:09 |
recognize you have tested every
significant path that's in your code.
| | 06:14 |
And there are tools available that can
measure your unit test against the
| | 06:18 |
detectable paths through your code.
This is known as code coverage and I will
| | 06:22 |
come back to that later.
But as for first getting into this.
| | 06:25 |
A better rule of thumb is a phrase that
you will sometimes hear in regard to test
| | 06:30 |
driven development.
And that phrase is test until fear turns
| | 06:34 |
to boredom.
Whether you wnat to call it fear or
| | 06:36 |
tentativeness or concern.
We are writing complicated structures in
| | 06:40 |
code and we realize we are not
infallible.
| | 06:43 |
We all have the best of intentions.
But sometimes what we write does not do
| | 06:47 |
exactly what we intended it to do.
So add another test.
| | 06:50 |
And we're never just trying to duplicate
existing tests.
| | 06:53 |
We're trying to simply make sure every
significant path is being tested at least once.
| | 06:58 |
That we have in short written all the
tests we wish we had.
| | 07:04 |
Now, an important idea here.
I have three methods in this testing code
| | 07:09 |
and it is important that these methods
should be considered independent of each other.
| | 07:13 |
Let me say that again.
Your test methods should be considered
| | 07:17 |
independent of each other.
These should be able to run in a random
| | 07:21 |
order, doesn't matter whether testDeposit
runs before or after testWithdraw or testWithdrawWithPenalty.
| | 07:28 |
No test method has dependencies on
another test method.
| | 07:32 |
They should be self contained, isolated
from each other.
| | 07:34 |
Because if we have an assertion failure,
we need to be able to look directly at
| | 07:39 |
that test; not trying to figure out if
the, order of the 3, or the 27, or the
| | 07:44 |
500 tests that ran before it, had any
impact.
| | 07:47 |
It shouldn't matter.
So if I add a new test or if I later
| | 07:51 |
delete a test because it's not needed any
more, there is no impact on the others.
| | 07:55 |
But one thing we haven't talked about is
naming these well.
| | 07:58 |
So let's do that next.
| | 08:00 |
| | Collapse this transcript |
| Naming unit tests and test methods| 00:00 |
If you've been in programming for more
than about, oh, 5 minutes, you'll know
| | 00:04 |
that naming conventions can become almost
a religious issue.
| | 00:07 |
But, with unit testing, there's a bit
more importance to it than just personal
| | 00:12 |
or team or even company preference.
Because depending on the language, the
| | 00:16 |
names that you use can make the
difference as to whether your test even runs.
| | 00:20 |
I'm going to show simple examples in four
different languages in the next few
| | 00:24 |
minutes, but it is objectively worthwhile
for us to begin by showing some Java in
| | 00:29 |
JUnit, simply because, that's where most
of the other xUnit testing frameworks
| | 00:33 |
took their lead.
So first let's talk about creating new
| | 00:36 |
unit tests.
So in the examples I've done so far I've
| | 00:40 |
had the bank account class and its
corresponding bank account test class.
| | 00:45 |
And this isn't exactly a rule, but a very
good guideline to begin with, is that you
| | 00:49 |
would create a separate unit test, a
separate class for each new class you
| | 00:54 |
write in your project.
So when we were about to add a bank
| | 00:57 |
account class, we first added bank
account test.
| | 01:00 |
If I added a new person class I would
first go ahead and add a new person test
| | 01:05 |
Junit test case, so it's common
convention just to take the name of a
| | 01:10 |
class she want to add and adding the unit
test just put the word test after it.
| | 01:14 |
Sometimes, you'll see the test case
suffix instead of just test, and
| | 01:19 |
sometimes you will see tests plural
instead of singular.
| | 01:22 |
But with Java, it's usually more common
to just see test at the end, some people
| | 01:27 |
even put it at the front.
I preferred at the end.
| | 01:30 |
And once you've actually created this new
class, this new unit test, you have the
| | 01:35 |
individual testing methods inside of it.
Now, it used to be the case that in j
| | 01:39 |
unit you had to begin each test method
with the word test, because that's how
| | 01:44 |
JUnit worked.
It would be based on the name of the method.
| | 01:47 |
It would go through these classes looking
for methods that began with the word test.
| | 01:52 |
However, since JUnit 4 released, which
was in 2006, it's not necessary to do
| | 01:57 |
that because we use this at sign test
annotation instead and this is how JUnit
| | 02:03 |
knows what methods to treat as tests.
You can call these methods whatever you want.
| | 02:08 |
But it's certainly not unusual to still
see the individual test methods begin
| | 02:13 |
with test as I had in my example over
here called BankAccountTest, although, it
| | 02:17 |
really doesn't have to have that.
If I wanted to change this to just be
| | 02:21 |
Deposit or Withdraw, that would be
perfectly acceptable.
| | 02:24 |
But, as I will show in this video, some
other languages still do rely on using
| | 02:29 |
test as a prefix for your test methods.
Beyond that, you really just want to be
| | 02:35 |
readable and understandable.
And because you often want to test the
| | 02:38 |
same method in your application code,
multiple times in your test code for
| | 02:43 |
multiple different situations.
It is very common to see something along
| | 02:46 |
these lines.
That you would begin with the name of the
| | 02:48 |
unit being tested, meaning the name of
the piece of code, usually just the
| | 02:52 |
method name.
And then a bit of extra information to
| | 02:55 |
describe what's special about this test,
if anything.
| | 02:58 |
So if I had a method called Withdraw, if
I'm working in a language that requires
| | 03:03 |
test at the start, I might call my
testing method testWithdraw.
| | 03:07 |
Otherwise, if it's a basic call, I might
just call my testing method withdraw as
| | 03:11 |
well, have them both have the same name.
But, more likely, is there's something
| | 03:15 |
special about the particular test.
I want to withdraw and make sure that
| | 03:20 |
we're going to end up with a negative
balance; make sure we're going to end up
| | 03:23 |
with a penalty.
So I would describe that extra bit of
| | 03:26 |
information, so withdrawWithPenalty.
In this case, I'm using CamelCasing,
| | 03:31 |
although, you may also see a format using
underscores, to separate the name of the
| | 03:35 |
unit being tested with what is special
about this particular test.
| | 03:39 |
So, even something like this.
Withdraw is what we're testing, and the
| | 03:43 |
situation that we care about is there's a
penalty added if it's a negative balance.
| | 03:47 |
But really, hopefully, what's becoming
apparent is the idea that you want to use
| | 03:51 |
the method name to tell the difference
between the test that you're doing now
| | 03:55 |
and the one before it or the one after
it.
| | 03:57 |
So just focus on making it readable,
understandable, because you'll probably
| | 04:01 |
find more of an impact based on the
company that you are working for or any
| | 04:05 |
style guidelines that you have or just
the general way that things are named in
| | 04:10 |
your chosen language.
And just make sure that if you're working
| | 04:13 |
with other developers that you're all
roughly on the same page.
| | 04:16 |
Now, because I've been using Java up till
now this is actually a good point to show
| | 04:21 |
three other languages.
Now, I'm going to show objective C, some
| | 04:24 |
C Sharp, and some Python.
Now, if these aren't languages you're
| | 04:27 |
familiar with, don't worry too much about
that.
| | 04:29 |
And I'm not trying to get you to learn
the syntax of them.
| | 04:32 |
What I'm trying to do is give you some
exposure to, both, the core similarities
| | 04:36 |
and a couple of notable differences with
xUnit testing frameworks.
| | 04:40 |
So, let's kind of recap the Java example
with JUnit.
| | 04:44 |
And here, it really is all about the
@Test annotation.
| | 04:48 |
When we're creating a unit test class, we
don't need to inherit from any particular class.
| | 04:53 |
It's a pretty normal Java class.
We add this @Test, we can call the method
| | 04:58 |
anything we want, but we're just here to
get set up so that we can make some kind
| | 05:02 |
of assert, and here, I'm using the assert
equals method in JUnit.
| | 05:07 |
If I jump over to C Sharp, C Sharp has
the annotation equivalent.
| | 05:12 |
We mark the method though, instead of
using @Test, it's this test method word
| | 05:17 |
in square brackets.
This is the test method attribute.
| | 05:20 |
Although, it also uses the test class
attribute on the class itself, in my
| | 05:25 |
experience it's more common in the dot
net world to see the name of the unit
| | 05:29 |
test class end in tests plural, rather
than test singular, but there's no rule
| | 05:34 |
that says this must be the case.
Instead of the Assert Equals in Java, we
| | 05:38 |
have the Assert.AreEqual method but, as
you can see, otherwise, it's almost
| | 05:43 |
identical switching over to Objective-C.
Couple of differences here, mainly
| | 05:48 |
because of the Objective-C syntax, but
one notable thing.
| | 05:52 |
Using the OC unit testing framework and
Objective-C still does require that the
| | 05:57 |
method be prefixed with the word, test.
This is how JUnit used to be.
| | 06:01 |
So instead of just Deposit, it is
testDeposit.
| | 06:03 |
That would be required, it wouldn't run
properly without it.
| | 06:06 |
And if you notice, the assertion here,
instead of just AssertEquals, it's STAssertEquals.
| | 06:12 |
OCUnit, the library I'm using here, came
from an earlier library called Send Test,
| | 06:16 |
and that's where the ST prefix comes
from.
| | 06:19 |
And, finally, I'll jump over to Python,
and Python does have unit testing built
| | 06:24 |
into its standard library.
That library used to be called PyUnit,
| | 06:27 |
like most of the other xUnit libraries.
SUnit, JUnit, NUnit, but is now referred
| | 06:33 |
to as just unittest, all one word.
And in Python, the unittest will end with
| | 06:39 |
TestCase, not just Test, because it
inherits from the TestCase class built
| | 06:44 |
into Pythos.
So this is what you would typically see.
| | 06:46 |
But Python also does require that the
testing methods, the individual methods,
| | 06:51 |
begin with the word test.
So here it's test_deposit.
| | 06:56 |
And it has as you might expect, it's own
assert equal equivalent.
| | 07:00 |
So there are some naming impacts across
different languages and some conventions
| | 07:05 |
of the language itself that will really
have more of an impact.
| | 07:07 |
But once you're past figuring out if your
language requires the testing methods to
| | 07:11 |
begin with the word test or if you can
use an annotation or an attribute as in
| | 07:16 |
Java or C sharp.
They're really very similar.
| | 07:18 |
It all comes back to being able to make
an assertion.
| | 07:22 |
| | Collapse this transcript |
|
|
4. Individual TechniquesTesting return values| 00:00 |
My current basic implementation of the
withdrawal and deposit methods in the
| | 00:04 |
bank account class, don't return values,
they're both void.
| | 00:07 |
But those methods do have an effect on
the state of the bank account object I
| | 00:11 |
can then measure.
So my test is to create that new object
| | 00:15 |
to call one of those methods.
And then what I assert, what I test, is
| | 00:19 |
the assumed side effect.
Now quick sidebar here, you'll slowly
| | 00:23 |
recognize that tests start to take the
same general approach.
| | 00:26 |
We create an object or two, we do
something to that object, we test the result.
| | 00:31 |
And just as we can use the phrase red,
green, refactor to describe the overall
| | 00:36 |
process of test and development.
Each individual task can typically be
| | 00:39 |
summarized using three words beginning
with A, the three A rule.
| | 00:43 |
To arrange, to act, and to assert.
So, to Arrange is to get something set
| | 00:49 |
up, to manipulate.
In this case, we want to create our bank
| | 00:51 |
account object.
Then we Act, we change it.
| | 00:54 |
We do something to it.
And then we Assert, we check the result.
| | 00:57 |
We check it worked.
Now, not all arrange, act, and asserts
| | 01:01 |
can be done with one line each, some will
require more.
| | 01:04 |
But it is another reminder that each of
your tests are intended to be self contained.
| | 01:09 |
And that you should be thinking about
what each of these three a parts means
| | 01:13 |
successfully for every individual test
you create.
| | 01:16 |
All right, end sidebar.
Back to this.
| | 01:18 |
We are testing here the effect of a void
method.
| | 01:21 |
But if I decided that this method should
have a return value, and say just return
| | 01:26 |
the new balance directly, I would want to
test that.
| | 01:29 |
And I could assert that directly.
In this case, done in two lines, we
| | 01:33 |
create a new instance of the bank
account.
| | 01:36 |
And then we'll call assertEquals
expecting here that the call to
| | 01:39 |
acc.withdraw will return 25.
So if your methods return a value, you
| | 01:45 |
test that.
If your methods affect the state of an
| | 01:47 |
object, you test that too.
And depending on the behavior you need,
| | 01:51 |
you might require tests for both the
return value and the side effect of a method.
| | 01:55 |
As an example so I decide the next step
is I need this withdraw method to refuse
| | 02:01 |
certain withdrawals.
So this is the way I'm going to decide to
| | 02:05 |
test it.
I'll instantiate this new object and I'm
| | 02:08 |
going to expect that if I make a call to
withdraw passing in a huge amount that
| | 02:12 |
should be disallowed.
This will actually return false.
| | 02:15 |
So I'm going to use the assertFalse
method here.
| | 02:18 |
Now, I'm assuming that if withdraw
returns false, it doesn't change the
| | 02:22 |
balance at all.
But if I was at all worried or concerned
| | 02:26 |
that there was any way the object might
be affected, and I need to make it isn't.
| | 02:30 |
I may add another assert, in this case I
am going to assert equals to check the
| | 02:34 |
balances unchanged.
Again the key here is you want to test
| | 02:38 |
until fear turns to boredom.
And how you decide to implement this new
| | 02:42 |
functionality of the withdraw statement
that it will return false in the right conditions.
| | 02:46 |
That's completely up to you and from this
point onwards, I'm not really going to
| | 02:50 |
get into that.
We are focusing on the test.
| | 02:53 |
Not the implementation of these.
But I'd fine this completely readable.
| | 02:57 |
It should fail straight away.
I would go ahead and start adding in my
| | 03:00 |
business logic to do this.
But I would also find it fine that within
| | 03:04 |
this test I want to continue on, and
actually verify a successful result as well.
| | 03:10 |
So I'm going to do an assertTrue, that if
we call acc.withdraw passing in the
| | 03:14 |
number 1.
If the account already has a 100 in the
| | 03:17 |
balance it should return true.
It should also effect the state of the object.
| | 03:22 |
So we'll add another assertEquals
verifying that the balance is now 99.
| | 03:27 |
Now there's a subtle distinction that I
want to point out here, that I've really
| | 03:30 |
got two tests going on both, having two
assertions each.
| | 03:34 |
One calling the withdraw method and one
calling getBalance.
| | 03:37 |
But both assertions are tests for the
withdraw method.
| | 03:41 |
And testing that it returns true or false
when it needs to.
| | 03:44 |
And I'm then testing the impact that it
has on on the object.
| | 03:47 |
And this is what I mean by subtle
distinction.
| | 03:49 |
If I was reading somebody else's test
code and I just focused only on one of
| | 03:54 |
these assertEquals lines.
I might say oh, here we're testing the
| | 03:58 |
getBalance method.
But I am not interested in the
| | 04:00 |
functionality of the get balance method I
am just using it to test the
| | 04:04 |
functionality of the withdraw method.
But this does lead to a common question.
| | 04:08 |
Do I need to specifically test my getter
and setter methods?
| | 04:13 |
Usually, no.
But I will talk more about that in a few
| | 04:16 |
other questions at the end of this
chapter.
| | 04:18 |
| | Collapse this transcript |
| Creating a test for expected exceptions| 00:00 |
It's common in our application to create
methods that deal with incorrect input.
| | 00:04 |
Or some other issue by throwing a known
exception, which can then be caught, and
| | 00:09 |
handled elsewhere in the application.
Now to test this individually, meaning
| | 00:13 |
we're testing this happening at the
UniTEST level, we need a way to fully
| | 00:17 |
expect when an exception can occur.
Now this is one of the areas in uni
| | 00:21 |
testing where the way you do this will
differ a little based on the language.
| | 00:25 |
So lets take a look.
Starting in JUnit I am creating a
| | 00:29 |
calculator class here and I want to check
its divide functionality.
| | 00:33 |
Now I'll have some other tests to check
it works correctly with good data.
| | 00:37 |
But here I want to check its behavior if
we pass in bad data.
| | 00:40 |
In this case asking it to divide by 0.
So I want this divide method to actually
| | 00:46 |
throw an exception.
I'll write this test first, I'll run it
| | 00:51 |
and it will fail because the
functionality doesn't exist yet.
| | 00:53 |
That's fine.
I go ahead and write the divide method.
| | 00:56 |
Now I'm not going to jump over into that,
I don't want to get into syntax there.
| | 01:00 |
Just expect that my imaginary divide
method will check the input values.
| | 01:04 |
And if it detects wrong input, it will
throw an illegal argument exception,
| | 01:08 |
which is a common way of doing this in
Java.
| | 01:11 |
I'll come back and run this test again
and it will fail but this time that
| | 01:15 |
failure is because I have successfully
thrown an illegal argument exception and
| | 01:20 |
nothing caught it.
But here's the problem.
| | 01:22 |
Yes, failure is good.
We want to begin with a red bar but I do
| | 01:25 |
need every test to go green.
So I need this test to pass when we get
| | 01:30 |
an illegal argument exception from
calling c.divide.
| | 01:34 |
Now there's two things that may be going
through your mind here.
| | 01:37 |
First, you may have noticed that we don't
actually have any kind of assert method
| | 01:41 |
here so you might wonder is there a
special assert.
| | 01:44 |
Is there an assert exception method and
no or at least that's not the way we do
| | 01:49 |
it in JUnit.
That is true in other languages.
| | 01:52 |
Now alternatively, if you're comfortable
with exception handling in Java, you
| | 01:56 |
might think, okay, do we write our own
try-catch-finally blocks right here in
| | 02:01 |
this test?
And, no, we don't, there's an easier way.
| | 02:04 |
What I do is I add an extra piece of
information to the @Test annotation at
| | 02:10 |
the top.
In this case, the (expected=IllegalArgumentEception.class).
| | 02:16 |
What this tells JUnit is that if any code
in this test method throws this specific
| | 02:21 |
exception and no other kind of exception,
we will go green bar.
| | 02:26 |
If it throws any other kind of exception
we will still fail.
| | 02:28 |
And there are a couple of other ways you
can do this in JUnit but this is typical
| | 02:33 |
and this will now become sorted a green
bar passing test.
| | 02:36 |
Over in .NET with C# it's a very similar
idea.
| | 02:41 |
If we're expecting our divide method to
throw an exception, we'll fix this by
| | 02:45 |
adding a new attribute to this method.
This expected exception attribute,
| | 02:50 |
describing the exception we're expecting
to see.
| | 02:52 |
And again, the assumption here is the
code we're writing to pass this test will
| | 02:56 |
explicitly throw this exception in these
particular circumstances.
| | 03:01 |
Now an objective C.
Well objective C developers do not use
| | 03:04 |
exception handeling anywhere near as much
as Java or .net developers.
| | 03:09 |
Historically exceptions in the apple
world are reserved for very serious and
| | 03:13 |
typically unrecoverable errors not
general handeling of flow through the program.
| | 03:18 |
But there is a specific assert method in
OCUnit, in this case STAssertThrows, is a
| | 03:24 |
couple of versions of this.
If you expect an exception to occur and
| | 03:28 |
you want to test that, that your test
will only work if this is the case.
| | 03:32 |
Now I show it here for comparison but in
objective C, you're very unlikely to want
| | 03:37 |
to generate or expect an exception in
this kind of circumstance.
| | 03:42 |
And lastly, Python.
Well, Python also has a specific assert
| | 03:47 |
method to use if you expect an exception
to occur.
| | 03:50 |
In this case if the divide method checks
it in parameters then it will raise a
| | 03:55 |
value error, which is the usual one you
do in Python.
| | 03:58 |
If you received arguments with invalid
values, so this is how your task would
| | 04:03 |
specifically say you are expect to be
able to raise that error expecting a
| | 04:07 |
value error if I call the divide method
passing in 5 and 0.
| | 04:11 |
And this is how you can go green bar when
this occurs.
| | 04:15 |
So as you see, there are a few different
syntax options here but we go back to the
| | 04:19 |
idea that when we assert, we can assert
in multiple ways.
| | 04:23 |
Most usually we are asserting a positive
outcome, asserting some kind of success.
| | 04:29 |
But also as needed, we can insert a
negative outcome that if we pass in this
| | 04:33 |
bad data to this particular unit of code,
we fully expect this error or exception
| | 04:39 |
to happen.
And if it doesn't happen then that's
| | 04:42 |
something we want to be notified about.
| | 04:44 |
| | Collapse this transcript |
| Setting up and tearing down| 00:00 |
We've explored a couple of concepts
already.
| | 00:02 |
First, that for each of the, what you
might think of as regular classes in your
| | 00:07 |
application, you would typically create
separate unit test class files.
| | 00:11 |
And in each unit test class you'd have
multiple simple self contained test methods.
| | 00:18 |
Each testing a specific path through the
methods in the relevant application class.
| | 00:22 |
And we've also seen that these individual
test methods themselves usually consist
| | 00:27 |
of the three A approach.
We arrange, we act, and we assert.
| | 00:32 |
We set up some objects and values.
We do something to them, then we check
| | 00:36 |
the results.
Now what is very common is that multiple
| | 00:39 |
test methods in the same unit test class,
end up beginning with a very similar
| | 00:44 |
arrangement of data, a very similar set
up.
| | 00:47 |
Often, they're going to repeat the same
code to initialize the current object
| | 00:51 |
under test with some simple data.
Now here, I'm just creating a BankAccount
| | 00:55 |
object inside each Test method.
Well, I might be able to do it in one
| | 00:59 |
line, but often you need multiple lines
to set up an object in some meaningfully
| | 01:04 |
realistic state.
So, we know duplication is bad, so you'll
| | 01:08 |
be glad to know there is a way to
simplify this.
| | 01:10 |
X unit testing frameworks include the
idea of special methods, usually called
| | 01:15 |
set up and tear down.
So in the same unit test class we would
| | 01:20 |
add these methods.
And this is the usual method signature
| | 01:23 |
you would see using JUnit.
Now in JUnit, the method names here, set
| | 01:28 |
up and tear down, don't actually matter.
We have these annotations, at sign before
| | 01:33 |
and at sign after, that, like the at sign
test annotation we've seen already.
| | 01:39 |
These are what are telling JUnit what
roles these methods play.
| | 01:42 |
So adding these mean that the setup
method will be called before each test,
| | 01:47 |
and the tear down method is called after
each test.
| | 01:50 |
You do not need both.
You can use one or the other or both or neither.
| | 01:54 |
It is much more common to require a setup
method than it is to have at tear down method.
| | 02:00 |
So in that, I just do whatever method I
need.
| | 02:02 |
In this case, if I wanted to share the
idea of just setting up the bank account
| | 02:06 |
class and setting its initial balance,
well, first what I'm going to need is
| | 02:10 |
just to declare a bank account reference
at the class level, so I can have one
| | 02:14 |
available across multiple methods.
This still is Java.
| | 02:18 |
Then in my set up method I will
instantiate that to a balance of 100, and
| | 02:22 |
now I can just go ahead and remove that
code from all of the individual testing methods.
| | 02:27 |
Okay.
It doesn't save an awful lot here but
| | 02:29 |
with more involved setup routines helps
avoid a lot of duplication.
| | 02:34 |
Now, here's the really important idea
about setup and teardown that a lot of
| | 02:39 |
people miss the first time around.
They read these methods, as having this
| | 02:45 |
kind of effect, that if you have setup
and tear down, setup will be called at
| | 02:49 |
the start, then your testing methods will
be called and then teardown will be called.
| | 02:53 |
But really it's this.
It's before and after every single test method.
| | 02:59 |
If you have these methods, JUnit, or
whatever other testing framework that
| | 03:04 |
you're going to use, well actually call
setup before each test method and
| | 03:09 |
teardown after each test method.
And once again, I will remind you that
| | 03:13 |
your testing method should be completely
independent of each other, that JUnit or
| | 03:18 |
whatever unit testing framework you're
using will book end them with setup and
| | 03:22 |
tear down but, they should be able to run
in a completely different order and it
| | 03:26 |
wouldn't matter at all.
Now, if what you actually wanted was a
| | 03:29 |
method that would only run once at the
very start of all the test methods and/or
| | 03:34 |
once at at the end of all the test
methods, no matter how many test methods
| | 03:37 |
you had, you can create another couple of
methods.
| | 03:41 |
So, if you wanted this typical name we
would use as setup before class and
| | 03:44 |
teardown after class.
Again, in JUnit, it's all about the annotations.
| | 03:50 |
So we have the @BeforeClass annotation
and the @AfterClass annotation.
| | 03:55 |
This can be useful but out of the four
available, the setUp, tearDown,
| | 03:59 |
setUpBeforeClass, and tearDownAfterClass,
you will find that setUp is the one you
| | 04:04 |
use most often.
So I'm going to do a quick comparison of
| | 04:07 |
the other languages to show that while
the syntax may be different, the ex unit
| | 04:11 |
ideas are the same everywhere.
So, if I just over to .NET.
| | 04:16 |
If we're using the built in Microsoft
unit testing library instead of using at
| | 04:20 |
sign after an at sign before, you would
add the TestInitialize and TestCleanup
| | 04:24 |
attributes to your methods for setup and
teardown at a per test level.
| | 04:30 |
There is also class initialize and class
cleanup attributes that can be added to a method.
| | 04:35 |
Whereas, in OCUnit, in Objective C, it is
based purely on the name of the method.
| | 04:41 |
So you actually need setup and teardown
methods, but these are provided in any
| | 04:44 |
sample unit test class that you would
make.
| | 04:48 |
And likewise in Python, it is also based
purely on the name of the method.
| | 04:53 |
You would need the set-up and tear-down
methods.
| | 04:55 |
Now when you start to flush out your unit
test classes to the point where you don't
| | 04:59 |
just have a couple of test methods but
also have setup and teardown when
| | 05:03 |
necessary, you'll hear this occasionally
referred to as a test fixture.
| | 05:09 |
Now it is true that there is quite a few
terms in unit testing that almost get
| | 05:14 |
used interchangeably, just even the word
itself is sometimes a little vague.
| | 05:19 |
But you've got test case, test class,
test fixture that often seems to be used
| | 05:24 |
and doesn't really matter which one that
you're using.
| | 05:26 |
But most typically and most formally when
the term test fixture is used it refers
| | 05:32 |
to the idea that not just the individual
test methods but the entire set of tests
| | 05:36 |
for one class including any associated
set up and tear down.
| | 05:41 |
| | Collapse this transcript |
| Common questions on individual tests| 00:00 |
I want to finish up this section by going
through a few questions and issues that
| | 00:03 |
are common to hear at this time including
a couple of things I referred to earlier.
| | 00:08 |
We'll begin with the question do I need
to test things like the get and set
| | 00:13 |
methods of properties?
And this really depends if you have
| | 00:17 |
simple getters and setters that are just
the equivalent of returning or setting
| | 00:21 |
internal balances.
Or if you're using a language that
| | 00:24 |
generates or synthesizes them, then no,
these don't need testing.
| | 00:28 |
There is no point at all to creating
specific unit tests for this kind of
| | 00:33 |
stuff because there's simply nothing you
could do if it failed.
| | 00:36 |
You're trying to test everything that
could break and that you could then fix.
| | 00:41 |
You're not trying to test the language
itself, you're testing your own logic.
| | 00:46 |
So it's fine to assume that somethings
will just work, that a return statement
| | 00:50 |
will work.
That if you add two and two, you will get four.
| | 00:54 |
That's not the kind of stuff that needs
tested.
| | 00:56 |
Now if however you need a custom setter
method that contains branching logic or
| | 01:02 |
that might change an internal value and
then affect another object, well then by
| | 01:06 |
all means sure, create a test to make
sure your logic works.
| | 01:12 |
Next up, what about private methods?
Do these need to be tested?
| | 01:15 |
Well, usually no with a couple of
caveats.
| | 01:18 |
In most languages you couldn't do this
anyway.
| | 01:20 |
If your unit test is in a separate class
file, you wouldn't be allowed to test a
| | 01:24 |
purely private method of another class.
Now there is some debate on unit testing
| | 01:29 |
private methods.
And there are some x unit testing
| | 01:32 |
frameworks that allow you to test private
methods using language features like
| | 01:37 |
introspection and reflection.
But I'll admit I'm not a fan of directly
| | 01:41 |
testing private methods.
Instead directly test a public method and
| | 01:46 |
just make sure there is a test or
multiple tests that you can do to a
| | 01:50 |
public method to verify the impact of any
private method that calls.
| | 01:55 |
Next question.
Can I combine multiple test classes
| | 01:58 |
together to run everything at once?
Well, sure.
| | 02:02 |
Bundling together multiple test classes
or test cases or test fixtures, whatever
| | 02:08 |
you want to call them is usually referred
to as a Test Suite.
| | 02:11 |
And it could be done in all unit testing
frameworks that I know of.
| | 02:15 |
There is often support for it in an IDE
and in fact a couple of development
| | 02:19 |
environments will just go ahead and run
every single one of your tests by default
| | 02:24 |
when you click the Test option.
However, beyond saying yes, you can
| | 02:29 |
bundle these up, I am not going to spend
time on test suites here because early on
| | 02:34 |
these shouldn't be a major focus.
And test suites can actually be a
| | 02:38 |
distraction for people learning
test-driven development.
| | 02:41 |
It's not that bundling tests together is
a bad idea.
| | 02:44 |
But it often leads to this innocent
sounding, understandable but deceptively
| | 02:49 |
dangerous question.
How can I control the order of my unit tests?
| | 02:54 |
And you never want to enforce any order
of execution of unit tests because that
| | 02:59 |
leads to dependencies.
Or these tests only work if they come
| | 03:03 |
after this set or before this set of
tests.
| | 03:06 |
And once you introduce dependencies, you
can't then quickly add or change new
| | 03:10 |
tests without reviewing other classes
first and you simply won't do this.
| | 03:15 |
So this innocent-sounding question
answered any other way than, you don't,
| | 03:20 |
is in danger of totally derailing TDD as
a development practice.
| | 03:24 |
We need to stay focused on creating small
tests that are self contained and
| | 03:29 |
isolated that could run in any order.
And remember that when unit testing we
| | 03:34 |
are not writing tests that test the
application.
| | 03:38 |
We are testing the individual units of
code and we need to always do our best to
| | 03:43 |
minimize any dependency, minimize any
coupling between different parts of the
| | 03:48 |
application or between the application
and other systems.
| | 03:52 |
And in the next chapter what I'm going to
talk about are specific things to watch
| | 03:56 |
for and avoid and a few situations where
we're going to need to fake our results.
| | 04:00 |
| | Collapse this transcript |
|
|
5. Additional TopicsIntroducing mock objects| 00:00 |
Our entire aim in unit testing is to be
able to test pieces of code in isolation.
| | 00:05 |
We're not writing tests that attempt to
use the full application, but rather to
| | 00:09 |
end up with hundreds, even thousands of
separate unit tests, each one testnig a
| | 00:14 |
single small part of the system,
independently of the others.
| | 00:17 |
Now, when the class, the component,
whatever you'd like to call the thing
| | 00:21 |
that you're looking at.
The current unit under test.
| | 00:24 |
When that contains totally self-contained
behavior, it's quite straightforward to test.
| | 00:29 |
You can create new tests directly for
this class and its methods without caring
| | 00:33 |
about what any of the other classes do.
Or even if any other class has existed at all.
| | 00:38 |
But let's face it, you don't have classes
that exist purely in a vacuum.
| | 00:42 |
As soon as you've gone beyond the trivial
these will need to interact.
| | 00:46 |
They will interact with objects of other
class types.
| | 00:48 |
They'll interact with databases, with
websites and web services, with the file
| | 00:53 |
system and some of the things that
they'll need to interact with are difficult.
| | 00:57 |
Some are slow, some are unreliable Quite
a few are not under our control.
| | 01:01 |
They may return different values every
time they're called.
| | 01:04 |
And if we're trying to do test-driven
development and build our tests alongside
| | 01:08 |
building our application, some of these
objects may not even exist yet, they just
| | 01:12 |
haven't been written.
And in unit testing we want to minimize
| | 01:16 |
any dependencies between the unit we're
currently testing and anything else.
| | 01:21 |
I actively want to avoid testing multiple
components at the same time.
| | 01:25 |
Because if I write a test that
instantiates a dozen objects of different types.
| | 01:29 |
Loads information from the web, saves to
a database, writes to the file system,
| | 01:33 |
and I run that.
I make an assertion, and the assertion
| | 01:37 |
fails, I don't where to look.
I've introduced multiple points of failure.
| | 01:42 |
My so-called unit test is now testing
much more than just this unit.
| | 01:47 |
So what do we do?
Well, the answer is not just avoid
| | 01:50 |
testing any part of your unit that
interacts with anything else.
| | 01:53 |
We have to think about the goal here.
And what we'd like to be able to do when
| | 01:57 |
testing a unit is just assume that every
other part of this is perfect and reliable.
| | 02:03 |
So we can focus our test purely on the
current unit.
| | 02:05 |
And if a problem occurs, we know exactly
where that problem is.
| | 02:09 |
And one technique for this Is mock
objects.
| | 02:13 |
We replace usage of other objects, other
systems, these external dependencies,
| | 02:18 |
with fake or mock implementations that we
can be sure will repeatedly behave the
| | 02:23 |
way they are meant to.
That instead of passing a query to a real
| | 02:26 |
database, we pass a query to a mock
version that's just code, it's just in
| | 02:30 |
memory and will reliably return the
results we want our unit to work on.
| | 02:34 |
That we can even replace a call to an
object that doesn't exist yet with a call
| | 02:38 |
to a mock version of that object that
behaves exactly as the real one should do.
| | 02:43 |
So there's a few classic reasons to look
at a mock object.
| | 02:47 |
The first being that the real object
hasn't been written yet.
| | 02:49 |
That's the easiest one.
After that it's what you're calling, if
| | 02:53 |
it needs a UI or it has human interaction
we can't wait for somebody to interact
| | 02:58 |
with some external system if we want to
run our unit test 100 times a day so we
| | 03:03 |
could emulate what that is meant to
return, if it's slow or difficult to set up.
| | 03:08 |
One of the most common reasons for using
mock objects is if you are interacting
| | 03:12 |
with some external resource like a file
system or a data base you're loading
| | 03:16 |
something over the network.
You're trying to save results to a
| | 03:19 |
printer because these are difficult to
either test that you are intending to
| | 03:25 |
happen has happened.
Or they're not exactly repeatable.
| | 03:28 |
If we're saving things to a database and
we're trying to do that 100 times a day,
| | 03:33 |
actually changing the state of the
database, that's going to be a difficult
| | 03:37 |
thing for us to test in any kind of
lightweight fashion.
| | 03:40 |
And again, we're focusing on the current
unit.
| | 03:43 |
Yes, we might be interested at some point
that the database is working as expected
| | 03:47 |
But when we're testing a different unit,
we want to take that as a given in which
| | 03:50 |
case it's very useful to be able to mock
up some of that basic database behavior.
| | 03:55 |
And very common leads, anything with
non-deterministic behavior.
| | 03:59 |
And that could be something like calling
a web service where we might get a
| | 04:03 |
different response every time or we might
even get a network error.
| | 04:06 |
Calling something that's going to give us
some data back, that may change from
| | 04:10 |
moment to moment or day to day.
So what may this look like in a test?
| | 04:14 |
But lets say I wanted a test on my
current unit, and it's going to call a
| | 04:19 |
web service object to get a weather
forecast and then do some operations on
| | 04:23 |
the results.
Well this could be non deterministic I'm
| | 04:26 |
not sure what its going to return and it
could unexpectedly give me network errors.
| | 04:30 |
But that's what I'm interested in
testing.
| | 04:33 |
I want to take the fact that this network
service that returns a weather forecast
| | 04:37 |
will just work so I can then bring back
the result and work on those results and
| | 04:42 |
assert some behavior after the fact.
So what I could do is define a mock
| | 04:47 |
version, create a new class called
MockWeatherService.
| | 04:51 |
Then instantiate that object, writing
that class so it will return a
| | 04:55 |
repeatable, prearranged response from
this getForecast call.
| | 04:59 |
So I then go ahead and use it as if I was
using the real service, but I always get
| | 05:03 |
a reliable response.
I don't have to worry about network
| | 05:06 |
connections or anything else.
And once again, an important but subtle distinction.
| | 05:10 |
What I'm doing in this test is I'm not
interested in testing the actual weather service.
| | 05:15 |
I'm intending on taking it as successful,
taking it as a given.
| | 05:20 |
I'm interested in getting some results
back for it, and using those results.
| | 05:24 |
There's two things we often do with mock
objects.
| | 05:27 |
We want them to return expected values,
and do it quickly and repeatedly.
| | 05:31 |
But we also often want to use them to
verify that how we are calling these
| | 05:36 |
objects is correct.
That if we are going to be calling a web
| | 05:39 |
service, are we positive That we're going
to pass the right data into that.
| | 05:43 |
And one way I could do this is adding
method to my mock object class to tell it
| | 05:48 |
to expect a certain value.
So when we're getting everything
| | 05:51 |
arranged, I could tell it, you're going
to expect this zip code, 85253.
| | 05:56 |
Then later on in the test when I call be
getForecast, passing in a property of my
| | 06:01 |
current object, I could verify that this
is actually the case.
| | 06:04 |
So then by calling this getForecast
method, my mock object itself can assert
| | 06:09 |
that what was passed in was correct and
fail if it wasn't, alerting me that
| | 06:12 |
perhaps the initial state of my data in
this unit isn't what I thought it was.
| | 06:18 |
Now there's a couple of terms that you'll
hear when you start talking about mock objects.
| | 06:22 |
One is the distinction between fake
objects and mock objects.
| | 06:26 |
There are a couple of other terms like
dummy objects, but let's just cover the
| | 06:30 |
usual difference between fake and mock
when people are talking about them.
| | 06:33 |
A fake object is the simplest kind of
mock object these are dumb.
| | 06:38 |
They just have a pre-written
Implementation of the object that they
| | 06:41 |
are supposed to represent, so they have
the same method signatures returning
| | 06:46 |
pre-arranged, pre-written responses.
And if people are making a distinction
| | 06:50 |
between fake objects and mock objects,
that usually implies that some code is
| | 06:55 |
inside the mock object that doesn't just
return values.
| | 06:59 |
But also asserts that any interaction
with it is corret.
| | 07:02 |
That how we are calling this object and
what we're passing into it can be verrified.
| | 07:07 |
So, a mock object often contains
assertians that verify any input in a way
| | 07:12 |
that any fake object somtimes does not
And while you mainly use mock objects to
| | 07:17 |
return repeatable successful values, you
can also use them to simulate difficult
| | 07:23 |
to emulate situations.
In this case, I might have a way to call
| | 07:26 |
my mock weather service object that will
reliably result in an emulated network error.
| | 07:31 |
So I can test that in my unit, I will
successfully deal with that response.
| | 07:37 |
Now there is nothing that would stop you
from just writing your mock objects
| | 07:41 |
yourself as regular classes in your
programming language.
| | 07:44 |
Creating a mock or a fake object that
responds the way you need it to, and just
| | 07:48 |
instantiating and using that in your
test.
| | 07:51 |
But there are several mock object
frameworks that we can use to help in
| | 07:54 |
this process.
Now these aren't part of the unit testing
| | 07:57 |
frameworks we've been using, they're
actually seperate.
| | 08:00 |
And I'll cover a few in just a moment.
The benefits are that they provide some structure.
| | 08:04 |
They can make it easier for you to define
your mock objects, and depending on the
| | 08:08 |
framework that you'd use, sometimes they
will remove the need for you to create an
| | 08:12 |
explicit custom class, but can help you
dynamically generate what you need using
| | 08:17 |
either interfaces in the language, or
perhaps an abstract class signature.
| | 08:22 |
They can help generate method stubs or
auto-generate method stubs.
| | 08:25 |
And quite importantly they can often
provide some of the most commonly needed
| | 08:29 |
mock objects, particularly dealing with
any kind of output from your program.
| | 08:33 |
So you can direct output to a mock
network stream or a mock printer stream
| | 08:38 |
or file stream and then explicitly check
the result so you're verifying the way
| | 08:42 |
your unit is sending data out to those
objects.
| | 08:46 |
Is exactly what you expected.
Now there are several different available
| | 08:50 |
mock object frameworks and these aren't
as identical as the general x unit
| | 08:55 |
frameworks so they are worth taking a
look at indepentendly to see what they
| | 08:59 |
offer your particular project.
Java has several popular mocking
| | 09:03 |
frameworks include jmock there's easymock
framework.
| | 09:08 |
There's mockito.
Mockito is a little different from the
| | 09:12 |
others and it tries to allow you to
dynamically generate your mock objects
| | 09:16 |
rather than explicitly writing classes
for them all the time.
| | 09:20 |
Over in dot net the Microsoft Fakes
framework is actually built into visual
| | 09:25 |
studio that supplies quite a lot of these
ideas although there are other options
| | 09:29 |
you can select including mock or
mock-you.
| | 09:33 |
If I jump over to the Objective-C site,
not as many options here.
| | 09:36 |
Probably the better known one is OCMock.
And over on Python, there is a library
| | 09:42 |
called mock that is part now of the
Python standard library.
| | 09:45 |
So expect multiple options in pretty much
any language that you're working in.
| | 09:50 |
Of course, mock objects aren't for
everything.
| | 09:52 |
They do introduce some level of risk.
If you're happily using a mock object
| | 09:57 |
because the real one hadn't been written
yet, and it is then written with
| | 10:00 |
different behavior than you expected,
you're going to run into problems.
| | 10:04 |
But they are definitely a tool to make
use of when unit testing.
| | 10:08 |
| | Collapse this transcript |
| Measuring code coverage| 00:00 |
One number that's often measured when
using automatic unit test is Code Coverage.
| | 00:05 |
Simply put, this is a percentage
measurement of exactly how much of your
| | 00:08 |
application code is being successfully
hit by your unit test.
| | 00:13 |
It's certainly not a guarantee of
perfection just because you have executed
| | 00:17 |
a line doesn't mean you've tested every
possible combination of data and options
| | 00:22 |
that could have gone into that line.
But code coverage will certainly let you
| | 00:25 |
know what you're missing.
Even the most basic code coverage reports
| | 00:29 |
will typically tell you different numbers
for how many of your classes are being
| | 00:32 |
tested, and within those, how much of
your methods are being tested, and the
| | 00:36 |
blocks, and even individual lines of code
inside those methods.
| | 00:40 |
Now as you might expect, this is
something that is done with a tool that
| | 00:43 |
can perform this analysis.
And there are a lot of code coverage tools.
| | 00:48 |
Some are free, quite a lot are
commercial.
| | 00:50 |
And the options are much better in
enterprise-heavy environments, say Java
| | 00:54 |
and .NET, than they are in languages like
Objective C or Python.
| | 00:59 |
But as a quick summary what I'm looking
at right now is a code coverage report
| | 01:03 |
generated by a tool called EMMA.
EMMA is a free Java code coverage tool,
| | 01:09 |
it's very popular in the Java world.
There are also things like plugins for this.
| | 01:13 |
You can have something called, EclEMMA,
which is an Eclipse plugin, which will
| | 01:17 |
integrate that properly into Eclipse and
start showing you the visual impact of this.
| | 01:21 |
In this case, it is green lines show code
that is being hit by a unit test, red
| | 01:26 |
lines are showing code that is not being
hit by a unit test, and yellow is where
| | 01:30 |
you might have a line that's partially
being hit.
| | 01:33 |
There are also commercial tools such as
Clover from Atlassian.
| | 01:38 |
These are more involved with many more
option for reporting but they have a
| | 01:41 |
price to them.
Over on the .net side of things if you're
| | 01:44 |
using premium or ultimate editions of
Visual Studio, there are actually code
| | 01:49 |
coverage tools built into the task
manager.
| | 01:51 |
Though aside from that there are several
third party options, mainly commercial
| | 01:56 |
ones are the better known ones such as
dot cover and NCover.
| | 02:00 |
Though as you'll see from looking around
different code coverage tools are
| | 02:03 |
obviously targeted at different kinds of
audience, so take a look at this and see
| | 02:07 |
which one might suit what you're doing
best.
| | 02:09 |
Now over in Objective-C and Python, the
story is a little weaker.
| | 02:13 |
With Python, the most common is
coverage.py, which you can find from the
| | 02:17 |
Python site itself.
And this will generate you those numbers.
| | 02:21 |
There are also options in XCode to
generate code coverage files, but that
| | 02:25 |
gets a little specific and not very
useful for this course to get into.
| | 02:29 |
So take a look at our Unit Testing in
XCode course for more on that.
| | 02:34 |
Again, code coverage tools aren't a
guarantee of perfection but particularly
| | 02:38 |
if you can get one that can show you
visually which lines of code are or are
| | 02:42 |
not being hit by your unit test, they're
very worthwhile to let you know when
| | 02:46 |
there are chunks missing in exactly where
they are.
| | 02:49 |
| | Collapse this transcript |
| TDD recommendations| 00:00 |
There are a few more concepts we could
get into about test-driven development,
| | 00:04 |
but my first suggestion is not yet,
because you should be able to take what
| | 00:09 |
we've covered in this course and begin,
get started.
| | 00:12 |
Test-driven development is not something
that requires guru knowledge.
| | 00:15 |
It really is getting these few ideas down
and then jumping in, starting to develop
| | 00:20 |
the habit of writing simple tests, and
particularly, the habit of writing the
| | 00:23 |
tests first.
And we've covered all the basic aspects
| | 00:26 |
of test and development.
Sure, there may be things you need to
| | 00:29 |
add, more specific situations you'll have
to explore.
| | 00:33 |
But those are likely to more about the
unique circumstances of your application
| | 00:37 |
and your environment.
So here's a few recommendations and
| | 00:40 |
guidelines as you get started with this.
First off, numbers.
| | 00:44 |
Now, these aren't rules, but a general
expectation would be you'd have one test
| | 00:49 |
case or test fixture or test class,
whichever you prefer per regular
| | 00:54 |
application class.
And in that, 3, 4, maybe 5 test methods
| | 00:59 |
per class method.
Sure, you can do more or less as needed
| | 01:03 |
but here's the thing, if you find
yourself going way beyond this say, 38
| | 01:07 |
test methods for a single class method,
it's going to be a clue that class method
| | 01:11 |
is doing way too much and has too much
responsibility.
| | 01:14 |
It should be split up, and likewise, if
you're averaging only one test method for
| | 01:20 |
each class method.
I'd wonder where your logic is, where is
| | 01:23 |
your branching?
Where are your conditions?
| | 01:25 |
And, are you actually testing them?
And that leads us to, what to test?
| | 01:30 |
Well, as hopefully, it's becoming
obvious, the driving idea is that you
| | 01:33 |
test every single path through the code.
And yes, that means a separate test for
| | 01:38 |
every branch of an if statement.
Every if, else, and, or, every case statement.
| | 01:44 |
A test for every for and while, and do
loop in a method.
| | 01:48 |
And a test for every use of polymorphism,
where it's being used to achieve
| | 01:52 |
different results.
And that's the real answer to the early
| | 01:55 |
question, well, how many tests should I
have, is how many do you need to test all
| | 01:59 |
the paths through the code.
And as the phrase goes, test until fear
| | 02:03 |
turns to boredom, 'til you're confident
that all your paths are being tested.
| | 02:08 |
And use code coverage tools to verify
that what you think you are testing has
| | 02:12 |
some bearing on the actual reality of
what you are testing.
| | 02:15 |
Now, what to avoid?
Always think small, self-contained,
| | 02:20 |
isolated, and repeatable.
So unit tests, as a rule, should not A,
| | 02:26 |
interact with a real database or a file
system.
| | 02:29 |
That's going to interfere with repeating.
It's going to rely on or change external
| | 02:34 |
state and we want to avoid that wherever
possible.
| | 02:37 |
Use mock objects when necessary.
Now, here's the thing.
| | 02:40 |
If you're feeling this resistance,
thinking well, surely, there are times to
| | 02:43 |
test the database.
Yes, absolutely there are.
| | 02:46 |
But that is functional testing, or
integration testing, or regression testing.
| | 02:50 |
This is not unit testing.
Next, they should not require any
| | 02:55 |
nontrivial network communication, that
will be another dependency, mark this out
| | 02:59 |
if necessary, you are testing this unit.
You are not testing the network.
| | 03:04 |
Unit test should not require any
environment changes.
| | 03:07 |
If you need to change configuration files
back and forth when you're running you're tests.
| | 03:12 |
Well, there's two problems here.
A, you're not likely to continue to do
| | 03:16 |
this so you won't run your test as often
as you should, And be, again you would be
| | 03:20 |
relying on some kind of external state
affecting your unit test.
| | 03:25 |
And again, I'll go back to the idea of
independent and isolated unit test should
| | 03:30 |
not have and certainly not require
dependencies on the state of any external system.
| | 03:36 |
Your unit tests shouldn't call any
complex, any non-trivial collaborator objects.
| | 03:41 |
Again, this is all about clarity on what
you're testing.
| | 03:43 |
If those objects need tested, the unit
test should be for those objects.
| | 03:48 |
Here, we're testing this unit, not this
unit and a bunch of others at the same time.
| | 03:53 |
Much of these recommendations come back
to one core idea, unit testing is not
| | 03:59 |
like other kinds of testing.
Don't let your unit tests slowly decay
| | 04:03 |
into or become confused with integration
tests or functional tests or application
| | 04:09 |
level tests.
There is a place for those.
| | 04:11 |
But that is a very different mindset and
a different approach from the day-to-day
| | 04:16 |
test-driven development routine we want
here.
| | 04:19 |
Now, if you're working with an existing
code mix, a project written without unit
| | 04:23 |
tests, and you're now intending to add
TDD practices to that Now there's a
| | 04:28 |
couple of ways you could go about this.
Approach number 1 would be to try and add
| | 04:32 |
a complete set of unit tests.
So you could decide to go for 100% code
| | 04:38 |
coverage right out of the gate and write
all of your unit tests in one go.
| | 04:42 |
But in a large project, writing nothing
but unit tests for weeks, is a totally
| | 04:47 |
soul sucking death march, and this never
works well, simply because the code
| | 04:52 |
wasn't written to be tested, and that
matters.
| | 04:55 |
As you're beginning to see, test-driven
development is not primary about a
| | 05:01 |
testing process.
This is a design process.
| | 05:04 |
TDD changes the way you think about and
the way you write your application code
| | 05:09 |
not just your testing code,so you can't
just come along, drop a bunch of unit
| | 05:13 |
test onto existing code and call it test
driven development...
| | 05:17 |
So brick number 2, a better idea at unit
test as you need them.
| | 05:21 |
This is a much more workable plan when
adding to an existing legacy code base,
| | 05:26 |
particularly as you do any refactoring
for intended addition.
| | 05:30 |
So if you're attempting to work on an
existing class, you first add a few unit
| | 05:34 |
test that will attempt to prove and
validate existing functionality so that
| | 05:38 |
you know if you break anything, and once
you got that in place in the current unit.
| | 05:42 |
Start the normal red green refactor
cycle.
| | 05:46 |
Beginning by adding a failing test for
the new functionality you want to add.
| | 05:51 |
Sure, this way is going to take a long
time to get to a significant level of
| | 05:55 |
code coverage, but it's a much more
realistic and manageable approach for
| | 05:59 |
existing projects.
| | 06:00 |
| | Collapse this transcript |
|
|
ConclusionNext steps| 00:00 |
While I've been keeping this course as
generic as I possibly can, we can only
| | 00:04 |
apply these ideas in some specific
language, some specific environment.
| | 00:09 |
So I'm going to cover a few resources for
moving forward using a particular
| | 00:13 |
language if you haven't already been
doing that.
| | 00:15 |
Now these recommendations obviously pale
into insignificance if you're working in
| | 00:20 |
an environment that already has some test
driven development or at least automated
| | 00:24 |
test processes in place.
So, getting started with Java.
| | 00:29 |
Well, with Java, the 400 pound gorilla of
unit testing is still JUnit.
| | 00:33 |
And JUnit.org has a very useful and wiki
and reference that really does cover
| | 00:38 |
almost everything that you would need on
a day to day basis, when creating an
| | 00:42 |
using tests.
It starts off with things like quick
| | 00:45 |
references for the available assertion
methods.
| | 00:49 |
With the example shown here, where
there're optional error messages that you
| | 00:52 |
can add.
There's information about test runners,
| | 00:56 |
how to actually run these tests.
Although, if you're using most common
| | 00:59 |
IDE's, running your JUnit tests is built
directly into the program.
| | 01:04 |
And it continues on to go through things
like exception testing that we've already covered.
| | 01:09 |
And there's a few advanced and
Java-specific sections, things like how
| | 01:12 |
to use Java with Maven, the Java build
manager, and so on.
| | 01:16 |
Now, if you're using Visual Studio 2012,
the best single place to get started is
| | 01:22 |
the page on verifying code review unit
tests in the MSDN library.
| | 01:26 |
This is a great resource because it
actually expects that you are comfortable
| | 01:30 |
with the ideas that we have covered in
this course.
| | 01:32 |
And then just takes you through using
these ideas in visual studio with C Sharp.
| | 01:37 |
So there's a walkthrough down here on
creating and running basic unit tests,
| | 01:41 |
there's also sections on using
Microsoft's Visual Studio test explorer.
| | 01:46 |
There's information on code coverage
tools, and even on using the Microsoft,
| | 01:51 |
fakes framework, which is the equivalent
of creating mock objects.
| | 01:55 |
Jumping over to Objective C, well, for
this, I'm actually just going to point
| | 01:58 |
you to Ron Lisle's course, Unit Testing
iOS Applications here in the lynda.com library.
| | 02:04 |
And most of the ideas here work for both
iOS and Cocoa applications.
| | 02:08 |
And this course covers not just the
OCUnit framework that's built into Xcode,
| | 02:13 |
but also the GHUnit alternative framework
many apple developers prefer.
| | 02:18 |
Now with Python, the best to bookmark is
simply the unit test section of the
| | 02:23 |
Python docks, as it's build into the
standard library.
| | 02:26 |
In this single page covers 99% of
everything you'd ever need to know when
| | 02:31 |
doing unit testing and Python, including
some very straight forward examples and
| | 02:36 |
there's a useful link right at the top of
the page that takes you directly to the
| | 02:40 |
list of Python Assert methods.
Now those were the languages that I'd
| | 02:44 |
explored in this course, but just one
other.
| | 02:47 |
If you are using Ruby, a language that I
haven't really talked about here.
| | 02:51 |
You know that there was an X Unit style
testing framework called Test Unit
| | 02:55 |
bundled into the language for a long time
up to Ruby 1.8.
| | 02:59 |
Although with Ruby 1.9 that was replaced
by another unit testing framework called minitest.
| | 03:05 |
And I'm looking here at the Ruby toolbox
website, which is showing the popularity
| | 03:09 |
currently, of unit test frameworks.
We can see test unit, which is a fairly
| | 03:13 |
common XUnit-style framework, and
minitest, which does include XUnit-style ideas.
| | 03:18 |
But, it's worth pointing out that
currently the most popular testing
| | 03:22 |
framework with Ruby is not an x-unit
style framework.
| | 03:26 |
It's a framework called RSpec that
supports something they call
| | 03:29 |
Behavior-Driven Development or BDD rather
than Test-Driven Development or TDD.
| | 03:36 |
Although, know that if you are a Ruby
person who had been watching this course,
| | 03:39 |
most of the ideas in RSpec in
Behavior-Driven Development are
| | 03:44 |
extensions of, or reactions to things in
test-driven development.
| | 03:48 |
So you should still find everything in
this course useful if you decide to jump
| | 03:53 |
into looking at RSpec.
And finally, whatever language you are
| | 03:56 |
using, I would recommend taking a look at
my Foundations of Programming:
| | 04:00 |
Refactoring course here at lynda.com, as
refactoring and test-driven development
| | 04:05 |
are two programming practices that really
do go hand in hand.
| | 04:09 |
So thanks for joining me for Foundations
of Programming, Test-Driven Development.
| | 04:14 |
May your tests go red, and then green,
and stay green.
| | 04:18 |
See you next time.
| | 04:19 |
| | Collapse this transcript |
|
|