14. Create the simplest possible
test scenario using the new
elements and do a trivial
implementation.
The goal of this step is to define
the API and how the class
clients will interact with it.
15. Use parameters that will
method induce a trivial return.
Test the expected
class behavior when the class
is just created.
16. In this test scenario,
the return is the String
that is passed as the
argument.
@Test
public void simpleCamelCase(){
String s = “common“;
String r = splitCamelCase(s);
assertEquals(s,r);
}
17. @Test
public void disconnected(){
Conection c = new Connection();
assertFalse(c.isConnected());
}
When a new
Connection is
created, it is
initally disconnected.
18. After the test, the class and
methods are created with a
trivial implementation.
19. And when I don't have
a simple scenario?
Fake the implementation
returning a fixed value
expected by the test.
24. Add a test that induce a
small increment on the
current class functionality.
The goal of this step is to move
forward on the TDD session,
incrementing functionality.
25. FAKED
Previous Test
should return true
with this new
test you will need
to handle this
Next Test
should return false
26. Equivalence class partitions are
intervals where the class
behavior is similar.
should do X should
do Z
should do Y
28. @Test public void emptyStack(){
Stack s = new Stack();
assertTrue(s.isEmpty());
assertEquals(0, s.size());
}
Small increment!
@Test public void pushOneElement(){
Stack s = new Stack();
s.push("item");
assertFalse(s.isEmpty());
assertEquals(1, s.size());
}
29. Test the Test with Test with
empty class one entry multiple
entries
0 1 *
30. 0 1 *
Create Introduce Complete
class API basic flow behavior
31. A complex scenario
can be created, but
adding a single
thing in comparison
to the previous
ones.
35. Add a test that introduce an
invalid scenario and verify if
the class behaves accordingly.
The goal of this step is to add
on the class the capability to
handle exceptional situations.
39. @Test
public void addOnFullStack()
throws FullStackException {
Stack s = new Stack(10);
for(int i=0;i<10;i++) s.push(“item”+i);
try{
s.push(“overload”);
fail();
}catch(FullStackException e){}
}
Here exceptions can be thrown
before, and only the expected
point should be verified.
44. How to make sure
that
functionalities are
working together?
45. Add a test scenario in which
two or more features are
used combined.
The goal of this step is to verify if
the features already implemented
are working together.
46. Special Company
Account Account
Features Features
Company
Special
Account
47. When you are doing
this kind of step,
there is no problem
to create a tests
that are already
green.
48. @Test public void coupon(){
ShoppingCart s = new ShoppingCart();
s.addItem(“Product“,1000);
s.addCoupon(100,“23473495734957“);
assertEquals(900, s.total());
}
Different features!
@Test public void discount(){
ShoppingCart s = new ShoppingCart();
s.addItem(“Product“,1000);
s.addDiscount(0.15);
assertEquals(850, s.total());
}
49. @Test public void couponWithDiscount(){
ShoppingCart s = new ShoppingCart();
s.addItem(“Product“,1000);
s.addCoupon(100,“23473495734957“);
s.addDiscount(0.15);
assertEquals(“Coupon before discount“
765, s.total());
}
52. What can I do when
the simplest solution
is not suitable for the
next requirements?
53. Ignore temporarely the
current test and refactor the
code to a more suitable
solution.
The goal of this step is to work
internally on the class to provide a
better solution for the next
requirements.
62. Sometimes you
need to implement
a complicated
logic...
If I have an auxiliary
method or a
helper class...
63. You can also feel
that this code does
not belong to the
class that you are
developing.
64. What can I do when I
feel that an auxiliary
code would help on
the implementation?
65. Stop temporarely the current
TDD session and dive on another
TDD session to develop the
auxiliary code.
The goal of this step is to change
the focus of the TDD session to
allow the developer to work on a
code out of the current class scope.
66. Class A TDD Session STOP
I need a
function that
break strings
that use camel
case...
67. Class A TDD Session
Class B TDD Session
Now I can
explore all the
possibilities on
camel case!
68. I can relax and
continue my
TDD knowing
that camel case
is working
Class A TDD Session
Class B TDD Session
69. When you go deep, you can
focus on different scenarios,
and don`t need to include all
of them on the main class test
73. What can I do when it
is realy hard to test
something that my
class needs to do?
74. Create a test that defines a
mock object that mimic the
behavior responsible for the
complicated part.
The goal is to decouple your main
logic from the access to external
resources, defining which
functionalities you need from it.
75. Hard to test!
Test
Message Server
The tested class
Business needs to send a
Class message to a Queue.
76. Let's model this
class as with
another class that
Test sends the message
to it.
Message Server
Business Message
Class Sender
77. Now it is easy to
replace Message
Test Sender by a mock
object!
Business
Class MOCK
78. final MessageSender mock=
ctx.mock(MessageSender.class);
Business b = new Business(mock);
ctx.checking(new Expectations() {{
one(mock).send(“message“);
will(returnValue(true));
}});
boolean ret = b.businessMethod();
assertTrue(ret);
Include on the mock the
services that you need!
79. Can I mock the
APIs instead of
creating a new
class?
80. QueueConnectionFactory f = new QueueConnectionFactory();
QueueConnection conn = f.createQueueConnection();
QueueSession session = conn.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue q = new Queue("world");
QueueSender sender = session.createSender(q);
TextMessage msg = session.createTextMessage();
msg.setText(parameter);
sender.send(msg);
MOCK THIS
81. By creating a new class you
decouple your business class
and implement a perfect match
of your application needs.
83. The test for the class “hard
to test“ may be manual
You can incude the test of
this part on functional tests
If you decide to automate
the test, you will need to
handle this only once.
86. But to design a object
oriented software you need to
define relationships and
colaboration!
87. There are
dependencies
that the class
wants to hide...
… and others
that it needs
to expose.
88. How can I drive my
class using tests to
define an explicit
dependency?
89. Create a test that defines a
mock object that expects calls
according to the dependency
interface.
The goal is to model the contract
between both classes, defining
which methods are needed and
when they will be called.
90. Sometimes you know by
your architecture that you
should decouple classes.
Business Database
Rules Access
91. Authentication The class can
Service
also be composed
by different
implementations.
card fingerprint
validator validator
92. Scheduler anything
Another times, you are
defining a hotspot and
should be prepared to deal
with anything.
93. By defining the mock, you
define the API and divide
the responsibilities among
the classes.
94. final Task t = ctx.mock(Task.class);
final Scheduler s = new Scheduler();
ctx.checking(new Expectations() {{
one(t).init(s.getConfig());
one(t).execute();
}});
s.schedule(t, 100);
Thread.sleep(110);
95. final Task t = ctx.mock(Task.class);
final Scheduler s = new Scheduler();
ctx.checking(new Expectations() {{
one(t).init(s.getConfig());
exactly(2).of(t).execute();
will(onConsecutiveCalls(
throwException(new RuntimeException()),
returnValue(null));
}});
s.schedule(t, 100);
Thread.sleep(110);
100. Create a test that simulates the
bug scenario and fail because
of it. After that, fix the code to
make the test pass.
The goal is to locate the bug
using the tests and to make sure
that a similar problem will not
return in the future.
101. When a bug is found,
the first impulse is to
go straight to the
code and try to fix it!
102. If a bug appear it is
because the tests
are not covering
that scenario.
So, the first thing that you need
to do is to create the tests!
103. If you find other things wrong
on the code, do not start
digging deep to
solve all
of them !
107. to introduce a
programing element when a bug
is found
Bug
to continue Locator
API to improve
the code
Definition
Exceptional
to introduce Limit
funtionality to introduce
to define
a programing
exceptional
element
scenarios
Dive to add more Everything
Deep functionality
Differential Working
to consolidate
Test Together
features
if you need
auxiliary code
if the previous solution
is not suitable Pause for
if something is
Mock hard to test
Housekeeping
Complexity to define
dependences API
Dependence
Exposure