Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Test Driven Development Primer LJC Open Conference

3,899 views

Published on

Sometimes getting started with Test Driven Development is a difficult change for people to pick up. This presentation gives a brief guide to how to get started and suggests a few examples and practical points. The examples are a bit heavy in terms of they include some Spring - something I'll be looking to improve in the future

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

Test Driven Development Primer LJC Open Conference

  1. 1. Test Driven Development Primer ! Jim Gough ! twitter: @JavaJimLondon email: jpgough@gmail.com aptood: http:/ /aptood.com/6f1a22
  2. 2. Schedule Introduction Cognitive implications Mocking Legacy code
  3. 3. Who am I? 6 years developing in finance. London Java Community/JCP Panel. Strong belief in craftsmanship.
  4. 4. Disclaimer Based on personal experience. Based on what others found difficult. I probably take some shortcuts. I can definitely improve.
  5. 5. What is Test Driven Development? Write a test first. Make sure it compiles, runs and fails. Write the simplest code to pass the test. Refactor the code and if necessary the test.
  6. 6. http://www.flickr.com/photos/nocallerid_man/3638360458/
  7. 7. Cognitive Implications http://www.flickr.com/photos/aloha75/4571410233
  8. 8. Cognitive Implications http://www.flickr.com/photos/eepaul/3946701733/
  9. 9. Cognitive Implications Compose. Comprehend. Vary depending on maintenance vs new development. Rapid increase in complexity from the offset.
  10. 10. Jigsaws
  11. 11. Get the tech right
  12. 12. One Approach Controller/ UI End Point Order Controller Handler Logic Bartender Mock External Dependencies Database Mock
  13. 13. Difficult Change Reverse the way the way that you think. Start from the interactions and the spec. Asking questions. Exploring the domain. Answer the question with solutions. Take a step further in.
  14. 14. Mocking Ensure we only test one unit of code at a time. ! ! Helps us keep our goal of thinking about each part in stages. http:/ /www.flickr.com/photos/ick9s/3950547398/
  15. 15. Verifying Interaction @RunWith(MockitoJUnitRunner.class) public class TestOrderController { @Mock private BartenderService bartender; private OrderController orderController; @Before public void before() { orderController = new OrderController(); orderController. setOrderService(bartender);
  16. 16. Verifying Interaction @Test public void testOrderBeer() { orderController.order(Drink.BEER); verify(bartender).obtain(Drink.BEER); ! }
  17. 17. Verifying Interaction @Test public void testOrderTwoDrinks() { Drink[] drinks = new Drink[] { Drink.BEER, Drink.WINE }; ! orderController.order(drinks); verify(bartender, times(2)) .obtain(any(Drink.class)); ! }
  18. 18. Verifying Interaction @Test public void testOrderTwoDrinks() { Drink[] drinks = new Drink[] { Drink.BEER, Drink.WINE }; ! orderController.order(drinks); verify(bartender).obtain(Drink.BEER); verify(bartender).obtain(Drink.WINE); verifyNoMoreInteractions(bartender); ! }
  19. 19. Stubbing when(databaseBean.inStock(Drink.BEER)) .thenReturn(true); when(databaseBean.inStock(Drink.BEER)) .thenReturn(true) .thenReturn(false); when(databaseBean.inStock(any(Drink.class)) .thenReturn(true) .thenReturn(false);
  20. 20. Stubbing doThrow(new RuntimeException()).when(databaseBean).remov eStock(); when(namedParameterJdbcTemplate.update(eq( Employer.INSERT_EMPLOYER), any(SqlParameterSource.class), any(GeneratedKeyHolder.class), any(String[].class))).then(new Answer<Integer>() { ! @Override public Integer answer(InvocationOnMock invocation) throws Throwable { //Do things with arguments // Return } });
  21. 21. Customer wants to order an ale.
  22. 22. private AnnotationMethodHandlerAdapter handlerAdapter; protected MockHttpServletResponse response; @Test public void customer_orders_an_ale() { //Initialise handlerAdapter MockHttpServletRequest request = new MockHttpServletRequest(); request.setURI(“/order/ale”); request.setMethod(RequestMethod.POST); Ale ale = new Ale(“IPA”); request.setContent(mapper.writeValueAsBytes( ale)); handlerAdapter.handle(request, response, orderController); verify(bartender).orderAle(ale);
  23. 23. private Bartender bartender; @RequestMapping(value="order/ale", method=RequestMethod.POST) @RequestBody @ResponseStatus(value=HttpStatus.OK) public Drink orderAle(@RequestBody Ale ale) { return bartender.order(ale); ! ! ! }
  24. 24. @Test public void pour_ale_that_is_available() {} @Test public void ale_not_available() {}
  25. 25. @Mock private JdbcTemplate jdbcTemplate; @InjectMocks private Bartender bartender; @Test public void pour_ale_that_is_available() { Object[] params = new Object[1]; params[0] = “IPA”; when(jdbcTemplate.query(“SELECT * FROM Stock WHERE NAME = ?”, params, any(BeerMapper.class)).thenReturn(new Drink(“IPA”)); Drink drink = bartender.order(ale); verify(jdbcTemplate).query(anyString(), any(Object[].class), any(BeerMapper.class)); verify(jdbcTemplate).update(REMOVE_DRINK, params); assertThat(drink.getName(), isEqualTo(“IPA”));
  26. 26. @Mock private JdbcTemplate jdbcTemplate; @InjectMocks private Bartender bartender; @Test public void ale_not_available() { when(jdbcTemplate.query(“SELECT * FROM Stock WHERE NAME = ?”, any(Object[].class), any(BeerMapper.class)) .thenReturn(null); Drink drink = bartender.order(ale); verify(jdbcTemplate).query(anyString(), any(Object[].class), any(BeerMapper.class)); assertNull(drink);
  27. 27. private JdbcTemplate jdbcTemplate; public Drink order(Ale ale) { Object[] params = new Object[] { ale.getName() }; List<Drink> drinks = jdbcTemplate.query(SELECT_DRINK, params, beerMapper); if(drinks.size() > 0) { jdbcTemplate.update(REMOVE_DRINK, params); return drinks.get(0); } else { return null; }
  28. 28. Refactoring Legacy Code
  29. 29. Legacy Code Often following push and pray mentality. Lots of regression or hands on testing. Developer time is often wasted. Highly coupled code, changes become risker over time. Team culture can be of a fixed way.
  30. 30. Can I Use TDD? Absolutely, but there are a few new techniques to learn. Don’t change production code without a test.
  31. 31. One Approach Write tests to cover production code. Only refactor allowed are automated IDE steps. Break statics using intermediate step by identifying seams.
  32. 32. Dealing with Seams public class MyLegacyClass { public String getTimesLoggedIn() { User user = UserSession.getInstance() .getLoggedInUser(); return user.timesLoggedIn(); } }
  33. 33. Dealing with Seams public class MyLegacyClass { public String getTimesLoggedIn() { User user = UserSession.getInstance() .getLoggedInUser(); return user.timesLoggedIn(); } protected User getLoggedInUser() { return UserSession.getInstance() .getLoggedInUser(); !
  34. 34. Dealing with Seams public class MyLegacyClass { public String getTimesLoggedIn() { User user = getLoggedInUser(); return user.timesLoggedIn(); } protected User getLoggedInUser() { return UserSession.getInstance() .getLoggedInUser(); !
  35. 35. Dealing with Seams public class MyLegacyClassTest { private User loggedInUser; private class TestableMyLegacyClass extends MyLegacyClass { @Override protected User getLoggedInUser() { ! return loggedInUser; ! ! ! } ! }
  36. 36. Recommended Tutorial http:/ /www.youtube.com/watch?v=_NnElPO5BU0
  37. 37. Benefits Explore the domain, comprehend the problem. Start with meaningful requirements. Framework to solve complicated problems. High confidence in changes. Eventually, quicker more productive and accurate. Sanity.
  38. 38. Challenges Initially you have to reverse way of thinking. You sometimes have to sell it to team members. Sell the benefits to management. Less risk changes: One project, 5-6 issues per week - now 5 issues per year. Developer productivity goes up.
  39. 39. The End Get ready to test! ! Jim Gough ! twitter: @JavaJimLondon email: jpgough@gmail.com aptood: http:/ /aptood.com/6f1a22

×