Successfully reported this slideshow.   ×

# Basic TDD moves

When learning the game of Chess, people usually start by learning the basic moves individual pieces can perform. Later, to master the game, one must develop the skill to combine those small, basic moves into larger strategies. If we think about Test Driven Development in similar terms, what would those “basic TDD moves” be?

When learning the game of Chess, people usually start by learning the basic moves individual pieces can perform. Later, to master the game, one must develop the skill to combine those small, basic moves into larger strategies. If we think about Test Driven Development in similar terms, what would those “basic TDD moves” be?

### Basic TDD moves

1. 1. Basic TDD Moves Heuristics beyond “Red/Green/Refactor”
2. 2. About me… Developer since 1994 (C++ used to be my friend…) Agile Coach since 2009 fernando.a.cuenca@gmail.com @fer_cuenca
3. 3. Big Thanks to our Sponsors! http://lighthouselabs.ca     http://devhub.ca
4. 4. Agenda   Basic TDD Moves   Practice Session 1 + Debrief   BREAK   Practice Session 2 + Debrief
5. 5. Start Here TDD Write a failing test Make it pass Improve the Design
6. 6. The Three Laws of TDD 1.  You are not allowed to write any production code unless it is to make a failing unit test pass. 2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures. 3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test. http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd Robert “Uncle Bob” Martin
7. 7. 1, 2, , 4, , , 7, 8, , , 11, , 13, 14, , 16, 17, …
8. 8. String result = ""; if((number % 3) == 0) result = "fizz"; if((number % 5) == 0) result += "buzz"; if(result.isEmpty()) result = number.toString(); return result;
9. 9. public class FizzBuzzTests { @Test public void test_fizzbuzz() { fail(“niy”); } } NIY Test Step on solid ground from the very beginning
10. 10. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } } First Things First Start by writing an assertion
11. 11. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } } public class FizzBuzz { public static int of(int number) { return 1; } }
12. 12. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is(2)); } } public class FizzBuzz { public static int of(int number) { return number; } } Uncle Bob’s 3 Laws Start with Failing Test Sufficient enough to fail Uncle Bob’s 3 Laws Sufficient enough code to pass the test Triangulation Approximate with examples
13. 13. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is(2)); } @Test public void test_fizzbuzz_3() { assertThat(FizzBuzz.of(3), is(“fizz”)); } } public class FizzBuzz { public static int of(int number) { return number; } } Type mismatch! Design is wrong! We need to go here… TDD Write a failing test Make it pass Improve the Design But we’re here!
14. 14. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is(2)); } //@Test public void test_fizzbuzz_3() //{ // assertThat(FizzBuzz.of(3), is(“fizz”)); //} } public class FizzBuzz { public static int of(int number) { return number; } } Better Green than Sorry Refactor only when tests are passing;
15. 15. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is(2)); } //@Test public void test_fizzbuzz_3() //{ // assertThat(FizzBuzz.of(3), is(“fizz”)); //} } public class FizzBuzz { public static of( number) { return number; } } Better Green than Sorry Keep all test passing while refactoring
16. 16. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(1)); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is(2)); } //@Test public void test_fizzbuzz_3() //{ // assertThat(FizzBuzz.of(3), is(“fizz”)); //} } public class FizzBuzz { public static of(Integer number) { return (); } } Predictable Failure Refactoring against the Red Bar
17. 17. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is( )); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is( )); } //@Test public void test_fizzbuzz_3() //{ // assertThat(FizzBuzz.of(3), is(“fizz”)); //} } public class FizzBuzz { public static String of(Integer number) { return number.toString(); } } Better Green than Sorry Run all the tests, all the time The House is in Order All tests must pass before writing the next test
18. 18. public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(“1”)); } @Test public void test_fizzbuzz_2() { assertThat(FizzBuzz.of(2), is(“2”)); } @Test public void test_fizzbuzz_3() { assertThat(FizzBuzz.of(3), is(“fizz”)); } @Test public void test_fizzbuzz_6() { assertThat(FizzBuzz.of(6), is(“fizz”)); } @Test public void test_fizzbuzz_5() { assertThat(FizzBuzz.of(5), is(“buzz”)); } @Test public void test_fizzbuzz_10() { assertThat(FizzBuzz.of(10), is(“buzz”)); } @Test public void test_fizzbuzz_15() { assertThat(FizzBuzz.of(15), is(“fizzbuzz”)); } } public class FizzBuzz { public static String of(Integer number) { String result = ""; if((number % 3) == 0) result = "fizz"; if((number % 5) == 0) result += "buzz"; if(result.isEmpty()) result = number.toString(); return result; } } public class FizzBuzzTests { @Test public void test_fizzbuzz() { assertThat(FizzBuzz.of(1), is(“1”)); assertThat(FizzBuzz.of(2), is(“2”)); assertThat(FizzBuzz.of(3), is(“fizz”)); assertThat(FizzBuzz.of(6), is(“fizz”)); assertThat(FizzBuzz.of(5), is(“buzz”)); assertThat(FizzBuzz.of(10), is(“buzz”)); assertThat(FizzBuzz.of(15), is(“fizzbuzz”)); } }
19. 19. public class FizzBuzzTests { @Test public void returns_fizz_for_multiples_of_3() { assertThat(FizzBuzz.of(3), is("fizz")); assertThat(FizzBuzz.of(6), is("fizz")); } @Test public void returns_buzz_for_multiples_of_5() { assertThat(FizzBuzz.of(5), is("buzz")); assertThat(FizzBuzz.of(10), is("buzz")); } @Test public void returns_fizzbuzz_for_multiples_of_both_3_and_5() { assertThat(FizzBuzz.of(15), is("fizzbuzz")); assertThat(FizzBuzz.of(30), is("fizzbuzz")); } @Test public void returns_number_as_is_for_other_numbers() { assertThat(FizzBuzz.of(1), is("1")); assertThat(FizzBuzz.of(2), is(“2")); int bigNumber= 2 * 4 * 7 * 11 * 23; assertThat(FizzBuzz.of(bigNumber), is(Integer.toString(bigNumber))); } } No Guessing Games Test Names Reflect Intent Assertive Minimalist Test only “one thing”
20. 20. public class FizzBuzzTests { public void returns_fizz_for_multiples_of_3() {…} public void returns_buzz_for_multiples_of_5() {…} public void returns_fizzbuzz_for_multiples_of_both_3_and_5() {…} public void returns_number_as_is_for_other_numbers() {…} } Kevlin Henney “Programming with GUTS” “Test Smells & Fragrances”
21. 21. public class FizzBuzzTests { @Test public void returns_fizz_for_multiples_of_3() { assertThat(FizzBuzz.of(3), is("fizz")); assertThat(FizzBuzz.of(6), is("fizz")); } @Test public void returns_buzz_for_multiples_of_5() { assertThat(FizzBuzz.of(5), is("buzz")); assertThat(FizzBuzz.of(10), is("buzz")); } @Test public void returns_fizzbuzz_for_multiples_of_both_3_and_5() { assertThat(FizzBuzz.of(15), is("fizzbuzz")); assertThat(FizzBuzz.of(30), is("fizzbuzz")); } @Test public void returns_number_as_is_for_other_numbers() { assertThat(FizzBuzz.of(1), is("1")); assertThat(FizzBuzz.of(2), is(“2")); int bigNumber= 2 * 4 * 7 * 11 * 23; assertThat(FizzBuzz.of(bigNumber), is(Integer.toString(bigNumber))); } }
22. 22. public class FizzBuzzTests { @Test public void returns_fizz_for_multiples_of_3() { assertThatFizzbuzzForNumbersIs(“fizz”, 3, 6); } @Test public void returns_buzz_for_multiples_of_5() { assertThatFizzbuzzForNumbersIs(“buzz”, 5, 10); } @Test public void returns_fizzbuzz_for_multiples_of_both_3_and_5() { assertThatFizzbuzzForNumbersIs(“fizzbuzz”, 15, 35); } @Test public void returns_number_as_is_for_other_numbers() { int bigNumber= 2 * 4 * 7 * 11 * 23; assertThatNumbersRemainAsIs(1, 2, bigNumber); } } /* Custom Assertions */ private void assertThatFizzbuzForNumbersIs( String expectedResult, int... numbers) { for(int n: numbers) { assertThat( FizzBuzz.of(n), is(expectedResult)); } } private void assertThatNumbersRemainAsIs( int... numbers) { for(Integer n: numbers) { assertThat( FizzBuzz.of(n), is(n.toString())); } } Duplication Fighter No duplication in production or test code
24. 24. 2 Practice Sessions on the “String Calculator Kata”   We need to choose a common Programming Language   Find a partner (we’ll switch for Session 2)   Log in to Cyber-Dojo: http://cyber-­‐dojo.org
25. 25. Practice Session 1: Basic TDD “Moves” Uncle Bob’s Three Laws Start with a failing test Write enough of a test to fail Write only the code that is sufficient to make the failing test pass NIY Test Start on solid ground from the very beginning First Things First Start the test by writing an assertion Triangulation Approximate with examples Keep the House in Order All tests must pass before moving on to the next test Duplication Fighter Remove duplication after a test passes Keep the tests clean and free of duplication Better Green than Sorry Refactor only when all tests are passing Re-run all tests after every refactoring No Guessing Games Test names reflect intent Assertive Minimalist Minimize the number of assertions (test "one thing”) Predictable Failure Refactoring against the Red Bar
26. 26. Debrief: What was it like?   What are most important insights you gained from the session?   What was helpful / not-helpful?   What will you do differently in the next session?
27. 27. Practice Session 2: Extreme Baby Steps 1.  Setup source control repository. 2.  Setup a timer for 2 minutes interval when you start. 3.  Write exactly one test 1. If the timer rings and the test is red then revert and start over. 2. If the test is green before timer rings then commit. 4. Restart timer (no discussions in between timers) 5. Refactor 1. If the timer rings and the refactoring is not complete then revert and start over. 2. If the refactoring is complete before the timer rings then commit. 6. Restart the timer (no discussions in between timers) 7. Go to 3. http://blog.adrianbolboaca.ro/2013/03/taking-­‐baby-­‐steps
28. 28. Debrief: What was it like?   What are most important insights you gained from this session?   What was the overall feeling?   How does the result compares to what you initially thought the outcome might be?   How/Where could this approach be useful?   What will you do differently tomorrow, back in the office?
29. 29. Learning more Kevlin Henney Presentations Programming with GUTS https://www.infoq.com/presentations/testing-communication Test Smells & Fragrances https://www.youtube.com/watch?v=wCx_6kOo99M
30. 30. Thank you! And please, complete the feedback forms!!
31. 31. Image Credits   “Chess”, by John Croudy / used under CC   Scales image from Wikipedia   “Feedback”, buy Jurgen Appelo / used under CC

### Editor's Notes

• This is the code you know you need to write
• We know that the final implementation can’t return hard-coded values.
What test can I write that pushes the design in that direction?