Crafting Code: @sandromancuso @codurance
Crafting Code: @sandromancuso @codurance
[email protected]
@sandromancuso
@codurance h/p://codurance.com
Introductions
Who are you?
Which languages do you use?
What’s your experience with TDD?
Why this course?
Forget what you know…
… but just for today
Red
Refactor Green
do_something_interesting() {
Start with
a verb. }
Tests should clearly specify the behaviour of the class under test.
Avoid technical terms.
Test method structure
public class BankAccountShould{
assertThat(bankAccount.balance(), is(0));
}
when bankAccount.deposit(10);
}
Test creation order
Step 1: Name the class
}
Step 3: Define what you are testing
}
test_deposit_works() {…}
test_deposit_works_correctly() {…}
test_deposit() {…}
check_balance_after_deposit() {…}
Bad naming used on tests
If it is a bank account,
call it “bankAccount”
test_deposit_works() {…}
test_deposit_works_correctly() {…}
test_deposit() {…}
check_balance_after_deposit() {…}
Test methods should
indicate the expected
behaviour
increase_the_balance_after_a_deposit()
Tip for professional TDDers: Split your screen
} }
Don’t rush.
Write code you are proud of.
E.1 – TDD lifecycle & naming
Objective
- Introduce naming convention
- Create production code from test
- Start from assertion
- Tip for deciding the first test to write: The simplest possible.
Problem description: Stack
Implement a Stack class with the following public methods:
+ void push(Object object)
+ Object pop()
Stack should throw an exception if popped when empty.
Stack demo
E.2 – Test-Driving Algorithms
Objective
- Grow an algorithm bit by bit
- Delay treating exceptions (in this case, because they are more complex)
- Intentionally cause duplication
- Focus on simple structures first
UT UT
UT
B C
B C
D UT
D
E.4 – Mocking
Problem descrip4on: Payment service
Given a user wants to buy her selected items
When she submits her payment details
Then we should process her payment
Acceptance criteria:
- If the user is not valid, an excepDon should be thrown.
- Payment should be sent to the payment gateway.
Create a class with the following signature:
B’’
DB
UT UT
UT
B’ C
B’’ C A
B’’ IT
B’’ IMDB
E.6 – Outside-In TDD with Acceptance Tests
Objec4ve:
Learn and pracDce the double loop of TDD
Test applicaDon from outside, according to side effect
Problem descrip4on: Bank kata
Create a simple bank applicaDon with the following features:
- Deposit into Account
- Withdraw from an Account
- Print a bank statement to the console.
Acceptance criteria
Statement should have the following the format:
DATE | AMOUNT | BALANCE
10/04/2014 | 500.00 | 1400.00
02/04/2014 | -100.00 | 900.00
01/04/2014 | 1000.00 | 1000.00
Note: Start with an acceptance test
Account Service
}
E.6 – Outside-In TDD with Acceptance Tests
Proposed acceptance test star4ng point;
@RunWith(MockitoJUntiRunner.class)
public class PrintStatementFeature {
accountService.deposit(1000);
accountService.withdraw(100);
accountService.deposit(500);
accountService.printStatement();
<<Singleton>>
UserSession
+getInstance() : UserSession
+getLoggedUser() : User
TripService
+findTripsByUser(User) : List<Trip>
TripDAO
+findTripsByUser(User) : List<Trip>
Have fun!!!
https://github.com/sandromancuso/trip-service-kata/
Trip Service Kata Tips
You will need the following three tests
• validate_logged_in_user // throws UserNotLoggedInException
• does_not_return_any_trips_when_users_are_not_friends
• return_trips_when_users_are_friends
TIPS
• Create Seams to isolate dependencies
• When refactoring, ask yourself if the behaviour belongs to the TripService
• There are design issues that must be fixed. Dependencies should be injected.
• As you fix the design, tests become simpler
DEMO
What did we cover
Day 1
• Introduction to TDD
• TDD Lifecycle and Naming
• Test-Driving algorithms
• Expressing business rules
• Mocking
Day 2
• Expressive Tests with Builders
• Outside-In TDD with Acceptance Tests
• Testing and Refactoring Legacy Code
Summary of the last 2 days
h/p://codurance.com