Unit testing, everyone talks about it and wants to do it but never gets around to actually start testing. Complex spaghetti code and time / budget pressures are often the reasons why nobody dives in and gets started with testing. But when the application breaks, and people loose money or worse it's often too late.
In this talk I will take you on a journey with real examples that will show you how you can set up your tests, how to test complex situations with legacy spaghetti code, test web services, database interactions and how to gradually build a solid foundation to safeguard the core code base and everything around it.
Don't you want to be confident when you walk out the office?
4. Excuses
not
to
test
• No
6me
• Not
in
budget
• We
don’t
know
how
-‐
valid
and
honest
answer
-‐
right,
like
that’s
going
to
happen
• We
add
unit
tests
a@er
finish
project
•…
4
8. My
example
code
• Get
this
example
from
GitHub
-‐
hQps://github.com/in2it/Utexamples
project/
src/
Utexamples/
Calculator.php
autoload.php
tests/
Utexamples/
CalculatorTest.php
8
9. Simple
example
class
• Add
by
one
-‐ adds
the
current
value
by
one
?php !
namespace Utexamples; !
!
/** !
* Class that allows us to make all sorts of calculations !
*/ !
class Calculator !
{ !
protected $_value = 0; !
!
/** !
* Adds the current value by one !
* !
* @return int The value from this method !
*/ !
public function addByOne() !
{ !
$this-_value++; !
return $this-_value; !
} !
}
9
10. Our
unit
test
?php !
namespace Utexamples; !
!
Class CalculatorTest extends PHPUnit_Framework_TestCase !
{ !
public function testCalculatorCanAddByOne() !
{ !
$calculator = new Calculator(); !
$result = $calculator-addByOne(); !
$this-assertSame(1, $result); !
} !
}
10
14. A
lot
of
parameters!
• Easily
possible
to
make
mistakes
• Every
developer
might
use
different
params
• Not
easy
for
(semi-‐)automated
tes6ng
-‐
Using
IDE
for
running
unit
tests
13
68. Some
downsides
• Tes6ng
databases
takes
6me
-‐
-‐
-‐
-‐
-‐
create
a
real
database
connec6on
reini6alise
the
database
(load
schema,
truncate
tables)
load
ini6al
state
before
test
(with
each
test)
execute
on
the
database
compare
expected
result
with
actual
result
51
70. Mock
objects
• They
replace
an
object
for
tes6ng
-‐
-‐
a
class
with
all
methods
a
class
with
a
single
method
-‐
-‐
-‐
databases
web
services
file
systems
-‐
once
you
got
everything
set
up
• Since
they
replace
“expansive”
connec6ons
• Are
quicker
and
more
reliable
to
test
53
71. Same
tests,
but
now
mocked
?php !
!
namespace UtexamplesModel; !
!
use PDO; !
use PDOStatement; !
!
class ProductMockTest extends PHPUnit_Framework_TestCase !
{ !
public function testProductsCanBeLoadedFromDatabase() !
{ !
!
} !
!
public function testProductAddToDatabase() !
{ !
!
} !
}
54
77. Why
the
extra
work?
• Your
databases
are
fully
tested,
no
need
to
do
it
yourself
again
• The
connec6ons
are
expensive
and
delay
your
tests
• Your
tes6ng
code
that
needs
to
handle
the
data
it
gets,
no
maQer
where
it
gets
it
59
86. Euh…
what
just
happened?
1) Zftest_Service_JoindinTest::testJoindinCanGetUserDetails
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
ID19/ID
last_login1303248639/last_login
+
last_login1303250271/last_login
/item
/response
67
87. And
this?
2) Zftest_Service_JoindinTest::testJoindinCanCheckStatus
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
?xml version=1.0?
response
- dtTue, 19 Apr 2011 22:26:40 +0000/dt
+ dtTue, 19 Apr 2011 22:26:41 +0000/dt
test_stringtesting unit test/test_string
/response
68