↑Top Model (Kolkata) Call Girls Howrah ⟟ 8250192130 ⟟ High Class Call Girl In...
Using tests and mocks to drive the design of software
1. Test Driven Design
Using tests and mocks to drive the design of software
Attila Magyar
Microsec Plc
2012
2. ● End to End
– Real environment
● Integration
rd
– Against 3 party API
● Unit
– Isolated
3. Feedback
12
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
4. Feedback
External Quality
12
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
5. Feedback
External Quality
12
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
6. Feedback
External Quality
12
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
7. Feedback
External Quality
12
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
8. Bad design:
● Rigidity
● Fragility
● Immobility
Feedback
External Quality
12 Code Quality
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
9. Bad design:
● Rigidity
● Fragility
● Immobility
Feedback
External Quality
12 Code Quality
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
10. Bad design:
● Rigidity
● Fragility
● Immobility
Feedback
External Quality
12 Code Quality
10
Feedback about Quality
8
6
4
2
0
Unit test Integration test End to end test
Growing object-oriented software guided by tests: Steve Freeman, Nat Pryce
11. End to End vs Unit tests
● End to End: ● Unit tests:
● Slow execution and feedback ● Fast execution and feedback
● Sometimes unreliable ● Always deterministic
● Difficult and time-consuming to ● Easy to write and automate
write ● Easy to localize bugs
● Difficult to localize bugs ● Verifies basic correctness
● Verifies configuration, integration,
environment
13. Unit tests:
state based testing
public class Light { // Test
private boolean on;
light.switchOn();
public void switchOn(){
on = true; assertTrue(light.isOn());
}
public void switchOff(){
on = false; light.switchOff();
}
public boolean isOn(){ assertFalse(light.isOn())
return on;
}
}
14. Ticket Machine
class TrainTicketMachine implements TicketMachine {
private List<Integer> pressedButtons = new ArrayList<Integer>();
[...]
public void press(int buttonNumber) {
pressedButtons.add(buttonNumber);
}
public void enter() {
ticketReserver.reserve(new ArrayList<Integer>(pressedButtons));
}
}
16. Ticket Persister
Ticket Machine
DB
public interface TicketReserver {
void reserve(List<Integer> ticketCode);
}
Ticket Reserver
17. Messages=[
reserve(1,2,3),
Ticket Machine reserve(4,5,6)]
Has received 123?
Ticket Reserver
18. public class Spy implements TicketReserver {
private List<Integer> received = new ArrayList<Integer>();
@Override
public void reserve(List<Integer> codes) {
received.addAll(codes);
}
public void assertReceived(List<Integer> codes) {
assertThat(received, equalTo(codes));
}
}
@Test
public void reservesTicketUsingEnteredCodes() {
// Given
Spy spy = new Spy();
ticketMachine = new TrainTicketMachine(spy);
// When
ticketMachine.press(1);
ticketMachine.press(2);
ticketMachine.enter();
// Then
spy.assertReceived(Arrays.asList(1, 2));
}
19. @RunWith(MockitoJUnitRunner.class)
public class TrainTickerReserverTest {
TrainTicketMachine ticketMachine;
@Mock TicketReserver reserver;
@Test
public void reservesTicketUsingEnteredCodes() {
// Given
ticketMachine = new TrainTicketMachine(reserver);
(spyito)
// When
ticketMachine.press(1); ticketMachine.press(2);
ticketMachine.enter();
// Then
verify(reserver).reserve(Arrays.asList(1, 2));
}
}
@RunWith(JMock.class)
public class TrainTickerReserverTest {
@Mock TicketReserver reserver;
Mockery context = new JUnit4Mockery();
TrainTicketMachine ticketMachine;
@Test
public void reservesTicketUsingEnteredCodes() {
context.checking(new Expectations() {{
oneOf(reserver).reserve(Arrays.asList(1, 2));
}});
ticketMachine = new TrainTicketMachine(reserver);
ticketMachine.press(1); ticketMachine.press(2);
ticketMachine.enter();
}
}
42. rd
3 party API mocking
public class Greetings {
[...]
public void greetUsers() throws SQLException {
Statement stmt = connection.createStatement();
sayHelloTo(stmt.executeQuery("select name from users where type=1 or type=2"));
}
}
@Test
public void saysHelloToUsers() throws SQLException {
when(conn.createStatement()).thenReturn(stmt);
when(stmt.executeQuery("select name from users where type=1 or type=2")).thenReturn(users);
movies.greetUsers();
[...]
}
43. rd
3 party API mocking
public class Greetings {
[...]
public void greetUsers() throws SQLException {
Statement stmt = connection.createStatement();
sayHelloTo(stmt.executeQuery("select name from users where type=1 or type=2"));
}
}
Duplication
@Test
public void saysHelloToUsers() throws SQLException {
when(conn.createStatement()).thenReturn(stmt);
when(stmt.executeQuery("select name from users where type=1 or type=2")).thenReturn(users);
movies.greetUsers();
[...]
}
49. Test smells
Difficult to instantiate SUT
● Hidden dependency (e.g.: Singleton)
● Insufficient domain separation
50. rd
3rd party
3 party
Application domain
Adapter
Adapter
msg
BL
BL
Adapter
BL
Domain of the outside world 3rd party
Object must send messages to it peers in terms of its domain language.
51. Application wiring
rd
3 party - „new” and „set”
3rd party
Application domain
Adapter
Adapter
msg
BL
BL
Adapter
BL
- Main method
- Spring/Guice
- XML/Annotations
Domain of the outside world 3rd party
52. Application wiring
rd
3 party - „new” and „set”
3rd party
Application domain
MOCK
Unit test MOCK
SUT
MOCK
Adapter
BL
- Main method
- Spring/Guice
- XML/Annotations
Domain of the outside world 3rd party
53. Application wiring
rd
3 party - „new” and „set”
Real
Integration
Application domain
SUT
Adapter
BL
BL
Adapter
BL
- Main method
- Spring/Guice
- XML/Annotations
Domain of the outside world 3rd party
54. Application wiring
End to end test rd
3 party - „new” and „set”
rd
3 party
Application domain
Adapter
Adapter
BL
BL
Adapter
BL
- Main method
- Spring/Guice
- XML/Annotations
Domain of the outside world 3rd party
56. How does it work?
A
● Write a failing test
for A
57. How does it work?
Interface discovery
A B
● Write a failing test
for A
● Introduce the
interface of a
collaborator B
58. How does it work?
Interface discovery
A B
● Write a failing test
for A
● Introduce the
interface of a
collaborator B
● Mock the interface
● Use the mock to
Finish A
59. How does it work?
Interface discovery Interface discovery
A B C
● Write a failing test ● Write a failing test ● C is an adapter
for A for B ● Use integration
● Introduce the ● Introduce the test for this
interface of a B interface of C
● Mock the interface ● Mock the interface
● Use the mock to ● "Ensure contract
compliance"
finish A between A and B
● Use the mock to
finish B
60. Benefits
● Early design feedback (SRP, DIP, OCP, etc..)
● Mocks encourage the use of „Tell Don't Ask” principle
→ Well encapsulated code
● Outside-In approach
● Simpler interface, (and implementation)
● No dead code
● Less debugging
● More coverage →
● Higher confidence in code and refactoring
● Less post-release bugs
62. Jersey/Apache
CommandListener
Http client
Command
REST
Translator Command
Catalog
Money Product
Product Entered
Sale Started
Catalog
Sale Ended
Product
java.awt.print
e
ric
tP
uc
od Barcode
pr
SaleEventListener
Receipt
Printer
priceCalculated Receiver
CashRegister
63. References
● Growing Object-Oriented Software Guided by Tests
● Steve Freeman, Nat Pryce
● Why You Don't Get Mock Objects
● Gregory Moeck, rubyconf 2011
● Using Mocks And Tests To Design Role-Based Objects
● Isaiah Perumalla
● Mock Roles, not Objects
● Steve Freeman, Nat Pryce, Tim Mackinnon, Joe Walnes, High Holborn
● The Deep Synergy Between Testability and Good Design
● Michael Feathers
● Surely the Mars Rover Needed Integrated Tests! (Maybe Not?)
● J. B. Rainsberger
● Joey Devilla SOLID principle posters