4. Safety Warning
• This presentation contains code
– No guarantee that it actually compiles
• This presentation may contain bugs
– Avoid if suffering from entomophobia
5. Based on true stories
• In different countries
• In different projects
• With different teams
• Using different (programming) languages
9. Context
• Global company
• Large public web application
• Mission critical, 24/7
• Major revenue source for the company
• First agile project for this team
• I coach the team
• We need to modify and extend a small section
of the application
23. Who can spot the problem?
boolean refundAllowed(Product product) {
Datetime now = Datetime.now;
Datetime final = Datetime.parse("yyyy-MM-dd“,
product.deliveryAt());
return now <= final ;
}
31. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. ...
32. A new test
void testRefundGivenWhenDeliveryLaterToday() {
Datetime now = DateTime.now ;
String endofDay = now.strftime(“yyyy-MM-dd")
+ " 23:59" ;
Product product = ...
product.deliveryAt(endOfDay) ;
BusinessRule businessRule = ...
bool refund = businessRule.refundAllowed(product);
assertTrue(refund,“Refund allowed until delivery,
even on the day of delivery") ;
}
33. A new test
void testRefundGivenWhenDeliveryLaterToday() {
Datetime now = DateTime.now ;
String endofDay = now.strftime(“yyyy-MM-dd")
+ " 23:59" ;
Product product = ...
product.deliveryAt(endOfDay) ;
BusinessRule businessRule = ...
bool refund = businessRule.refundAllowed(product);
assertTrue(refund,“Refund allowed until delivery,
even on the day of delivery") ;
}
35. We finally fix the bug
boolean refundAllowed(Product product) {
Datetime now = Datetime.now;
Datetime final = Datetime.parse("yyyy-MM-dd
HH:MM”,
product.deliveryAt());
return now <= final ;
}
36. Rerun the test
void testRefundGivenWhenDeliveryLaterToday() {
Datetime now = DateTime.now ;
String endofDay = now.strftime(“yyyy-MM-dd")
+ " 23:59" ;
Product product = ...
product.deliveryAt(endOfDay) ;
BusinessRule businessRule = ...
bool refund = businessRule.refundAllowed(product);
assertTrue(refund,“Refund allowed until delivery,
even on the day of delivery") ;
}
37. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. ...
38. “This agile thing is going to be very slow if
we do this for every bug!”
“Yes, but at least now we have some
confidence that the bug is fixed correctly
and that we haven’t broken anything else.”
39. “We’ve really applied our team value of
‘quality without compromise’. We took
the time to do it right, even if no
customer has complained yet.”
40. “We should contact the team that’s responsible for
this code and inform them of our correction.”
“There may have been customer complaints already.
We should contact the customer support people to
see if there are complaints and inform them of the
existing problem”
41. TIPS
• Define and make the team values visible
at all times
• Keep a list of things to do after the Root
Cause Analysis (RCA)
• Language:
– “We should...” => “We will...”
42. WE WILL...
• Contact the development team responsible
for this code
• Inform the customer support team
43. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. PERFORM THE ACTIONS OF THE RCA
8. ...
48. Scene 4:
After the fix
The tester joins the developers and
architect
49. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. PERFORM THE ACTIONS OF THE RCA
8. IMPROVE YOUR TESTS
9. ...
50. How can we improve our tests?
We should have found this bug
sooner
51. How can we improve our tests?
We should have will fouind this type
of bug sooner
52. How can we improve our tests?
We will find this type of bug sooner
53. Context (2)
• Almost 80% code coverage with automated
unit tests in the whole application
• This module has 100% test coverage
• But still contains (at least) one bug
• Why?
• Let’s look at the tests...
54. Who can spot the problem?
void testRefundGiven() {
Product product = ...
product.deliveryAt(“2050-12-31 19:00”) ;
BusinessRule businessRule = ...
bool allowed =
businessRule.refundAllowed(product)
}
56. How can we improve our tests?
• There’s no ASSERT !
– It’s easy to get 100% code coverage that way
• Why 2050?
– What happens on January 1st 2051?
• We need at least 4 tests
– Delivery before today
– Delivery today before now
– Delivery today after now
– Delivery after today
57. Why?
• Developers don’t know how to test date and
time (and timezone!)-related code
– Lots of tests use dates in 2050
• Few developers with unit testing experience
• Agile coaching in the past did not include
technical practices
58. We will...
• Contact the development team responsible
for this code
• Inform the customer support team
• Add more tests about dates that can serve as
examples
• Show our example tests to other teams
59. Developers: “we have a lot to learn about unit
testing”
Architect: “I’ve always had doubts about our
automated tests. Now I know why.”
Tester: “If you want, I can help you to define and
improve tests”
60. Let’s dig deeper...
Why tests without ASSERT?
• Goal: “increase code coverage of automated
tests” instead of “increase quality”
• Pressure to “do more with less (money and
time)”
• Not much experience with unit testing
• TEST LAST development instead of Test First
• No training or coaching on technical practices
• Not all Agile coaches in the company have
experience with technical practices
61. We will...
• Contact the development team responsible for
this code
• Inform the customer support team
• Add more tests about dates that can serve as
examples
• Show our example tests to other teams
• Apply TDD by pairing with the coach and tester
• Raise « lack of technical practice coaching » risk
at coach meeting
63. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. PERFORM THE ACTIONS OF THE RCA
8. IMPROVE YOUR TESTS
9. IMPROVE THE WAY YOU WRITE TESTS
10. ...
70. Let’s search the code...
• We find 10 cases where this datetime is
parsed
– 5 times with “yyyy-MM-dd HH:MM”
– 5 times with “yyyy-MM-dd”
• Each developer analyses one case
• Result: two more bugs
75. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. PERFORM THE ACTIONS OF THE RCA
8. IMPROVE YOUR TESTS
9. IMPROVE THE WAY YOU WRITE TESTS
10. LOOK FOR SIMILAR PROBLEMS. GOTO 2
11. ...
76.
77. “Quality without compromise”. Easy to
say, hard to do
“Writing tests and correcting problems
is starting to become routine. It goes
faster each time we do it.”
82. Digging deeper...
Why did we introduce the bug?
• We aren’t aware that there’s a date+time
• We have 10x the same parsing code
• => 10 opportunities to make a mistake
• Let’s remove the duplication that leads to
mistakes
83. Improving Product
class Product {
...
// Deprecated: Remove when obsolete
String deliveryAt() ;
// New: gradually refactor all clients
DateTime deliveryAtDateTime() ;
...
}
From “stringly typed” to “strongly typed”
84. 11 steps to perfect code
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. PERFORM THE ACTIONS OF THE RCA
8. IMPROVE YOUR TESTS
9. IMPROVE THE WAY YOU WRITE TESTS
10. LOOK FOR SIMILAR PROBLEMS. GOTO 2
11. MAKE THIS TYPE OF PROBLEM IMPOSSIBLE
85. TIP
• If you think you have to comment your
code, think again
86. With comments
class A {
void methodA() ;
// Call methodA before calling these
void methodB() ;
void methodC() ;
}
...
a.methodB() ; // ERROR
a.methodA() ; // ERROR!!
87. Without comment
class A {
B methodA() ;
}
class B {
void methodB() ;
void methodC() ;
}
a.methodA().methodB() ;
89. The application
ABCDEFGHIJKLMNO
ABCDEFGHIJKLMNO
System A
ABCDEFGHIJKLMNO
ABCDEFGHIJKLMNO
Application
ABCDEFGHIJKLMNO
ABCDEFGHIJKLMNO
ABCDEFGHIJKLMNO ABCDEFGHIJKLMNO
System B
93. We will...
• Contact the development team responsible for this
code
• Inform the customer support team
• Add more tests about dates that can serve as examples
• Show our example tests to other teams
• Apply TDD by pairing with the coach and tester
• Raise « lack of technical practice coaching » risk at
coach meeting
• Encapsulate data coming from outside
100. Looking back
1. 7 team members + one coach have spent all
afternoon to correct a 6-character bug? Is
this reasonable?
2. In the end, there were a lot less bugs found
in test than on “normal” projects. Is there a
link?
3. This project was delivered in 5 months
instead of the 8 that were estimated. How
can you finish faster by going slower?
116. TIPS
• Once you run out of reported bugs...
Apply IDD™
Irritation Driven Development
Contact me if you want to become a Certifiable Irritating Person
117. TIPS
• Pair with the bottleneck
– ToC calls this “subordinating”
• Walk a mile in their shoes
– Carefully observe and note irritations
– Quietly remove the irritations
• Example: pair-installing dev-ops
119. 11 steps to a life with less stress
1. SPOT A PROBLEM
2. THANK THE REPORTER
3. REPRODUCE THE PROBLEM
4. ADD (AT LEAST) ONE FAILING TEST
5. CORRECT THE PROBLEM
6. AND RERUN ALL TESTS UNTIL THEY PASS
7. PERFORM THE ACTIONS OF THE RCA
8. IMPROVE YOUR TESTS
9. IMPROVE THE WAY YOU WRITE TESTS
10. LOOK FOR SIMILAR PROBLEMS. GOTO 2
11. MAKE THIS TYPE OF PROBLEM IMPOSSIBLE
125. Thank you, Dank u, Merci, Danke, Tak,
Kiitos, Gracias, Grazie, Tack, Obrigado
Consults
Programs
Manages projects
Creates Games
Organises conferences
NAYIMA
We make play work
http://www.nayima.be
http://www.agilecoach.net
Notas del editor
Portia and Pascal introduce themselves by sharing a bit about their background.
Portia and Pascal introduce themselves by sharing a bit about their background.