Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elegant?? Unit Testing (Codemotion Spain 2015)

Elegant?? Unit Testing (Codemotion Spain 2015)

In this session we will learn the basics of Unit Testing and its importance. We will define what a Unit Test is, what type of Unit Tests there are and then talk about Test Doubles. Finally, we will focus on how to write new tests and improve existing ones by reviewing some Android Github projects.

Can you sleep soundly without writing tests? Really???

Pablo Guardiola

December 01, 2015
Tweet

More Decks by Pablo Guardiola

Other Decks in Programming

Transcript

  1. 4 rules of simple design 1. Runs all the Tests

    2. Reveals all the intention
  2. 4 rules of simple design 1. Runs all the Tests

    2. Reveals all the intention 3. No duplication
  3. 4 rules of simple design 1. Runs all the Tests

    2. Reveals all the intention 3. No duplication 4. Fewest number of classes or methods
  4. Testing motivators Validate the System Code Coverage Enable Refactoring Document

    the Behaviour of the System Your Manager Told You To
  5. Testing motivators Validate the System Code Coverage Enable Refactoring Document

    the Behaviour of the System Your Manager Told You To Test Driven Development
  6. Testing motivators Validate the System Code Coverage Enable Refactoring Document

    the Behaviour of the System Your Manager Told You To Test Driven Development Customer Acceptance
  7. Testing motivators Validate the System Code Coverage Enable Refactoring Document

    the Behaviour of the System Your Manager Told You To Test Driven Development Customer Acceptance Ping-Pong Pair Programming
  8. Testing motivators Validate the System Code Coverage Enable Refactoring Document

    the Behaviour of the System Your Manager Told You To Test Driven Development Customer Acceptance Ping-Pong Pair Programming Flow
  9. Unit Test SOLITARY 1. Never cross boundaries 2.The Class Under

    Test should be the only concrete class found in a test
  10. Unit Test SOLITARY SOCIABLE 1. Never cross boundaries 2.The Class

    Under Test should be the only concrete class found in a test
  11. Dummy public class DummyAuthorizer implements Authorizer {
 @Override
 public Boolean

    authorize(String username, String password) {
 return null;
 }
 }
  12. Stub public class AcceptingAuthorizerStub implements Authorizer {
 @Override
 public Boolean

    authorize(String username, String password) {
 return true;
 }
 }
  13. Spy public class AcceptingAuthorizerSpy implements Authorizer {
 public boolean authorizeWasCalled

    = false;
 
 public Boolean authorize(String username, String password) {
 authorizeWasCalled = true;
 return true;
 }
 }
  14. Mock public class AcceptingAuthorizerVerificationMock implements Authorizer {
 public boolean authorizeWasCalled

    = false;
 
 public Boolean authorize(String username, String password) {
 authorizeWasCalled = true;
 return true;
 }
 
 public boolean verify() {
 return authorizeWasCalled;
 }
 }
  15. Fake public class AcceptingAuthorizerFake implements Authorizer {
 public Boolean authorize(String

    username, String password) {
 return username.equals("Bob");
 }
 }
  16. ANDROID Unit Testing Java Module MVP CLEAN Architecture AS 1.1

    + Android Gradle Plugin MVVM KOR Mosby (Hannes Dorfmann)
  17. ANDROID Unit Testing Java Module MVP CLEAN Architecture AS 1.1

    + Android Gradle Plugin MVVM KOR Catan Architecture Mosby (Hannes Dorfmann)
  18. ANDROID Unit Testing Java Module MVP CLEAN Architecture AS 1.1

    + Android Gradle Plugin MVVM KOR Catan Architecture Mosby (Hannes Dorfmann) Rosie?
  19. public class FooTest {
 
 @Test
 public void sampleTest() throws

    Exception {
 assertEquals(expected, actual);
 }
 } JUnit
  20. Clean Contacts @Test public void obtainContactFirstNameFromRepo() throws Exception {
 ContactsBddDataSource

    mockContactsBddDataSource = mock(ContactsBddDataSource.class);
 ContactsNetworkDataSource mockContactsNetworkDataSource = mock(ContactsNetworkDataSource.class);
 ContactsRepositoryImp contactsRepository =
 new ContactsRepositoryImp(mockContactsNetworkDataSource, mockContactsBddDataSource);
 Contact droidCon = new Contact();
 Name name = new Name();
 name.setFirst("Codemotion 2015");
 droidCon.setName(name);
 when(mockContactsBddDataSource.obtain("Codemotion MD5")).thenReturn(droidCon);
 
 Contact contact = contactsRepository.obtain("Codemotion MD5");
 
 assertEquals("Codemotion 2015", contact.getName().getFirst());
 }
  21. Clean Contacts @Test public void contactsInteractorExecutedWhenResumed() throws Exception {
 InteractorInvoker

    interactorInvoker = mock(InteractorInvoker.class);
 GetContactsInteractor getContactsInteractor = mock(GetContactsInteractor.class);
 final ListMapper<Contact, PresentationContact> listMapper = mock(ListMapper.class);
 ThreadSpec mainThreadSpec = mock(ThreadSpec.class);
 MainPresenter mainPresenter =
 new MainPresenter(interactorInvoker, getContactsInteractor, listMapper, mainThreadSpec);
 
 mainPresenter.onResume();
 
 verify(interactorInvoker).execute(Mockito.eq(getContactsInteractor), Mockito.any(InteractorOutputImp.class));
 }
  22. One Assertion Per Test (State Verification) @Test public void shouldCreateVerboseTraceFromStringTrace()

    throws Exception {
 Trace trace = Trace.fromString(VERBOSE_TRACE);
 
 assertEquals(TraceLevel.VERBOSE, trace.getLevel());
 assertEquals(ANY_TRACE_DATE + " " + VERBOSE_TRACE_MESSAGE, trace.getMessage());
 }
  23. ANNOYING to have to look at the STACKTRACE to know

    what’s FAILING Have NO INFORMATION about REMAINING TESTS
  24. One Assertion Per Test (Behavior Verification) @Test public void shouldNotUpdateFilterIfPresenterIsNotInitialized()

    {
 presenter.updateFilter(ANY_FILTER);
 
 verify(lynx, never()).setConfig(any(LynxConfig.class));
 verify(lynx, never()).restart();
 }
  25. 1. If your test has an assertion, do not add

    any mock verifications Rule of thumb
  26. 1. If your test has an assertion, do not add

    any mock verifications 2. If your test verifies a mock, do not add any assertions Rule of thumb
  27. 1. If your test has an assertion, do not add

    any mock verifications 2. If your test verifies a mock, do not add any assertions 3. At most, 1 assertion per test Rule of thumb
  28. 1. If your test has an assertion, do not add

    any mock verifications 2. If your test verifies a mock, do not add any assertions 3. At most, 1 assertion per test 4. At most, 1 mock verification per test Rule of thumb
  29. Expect Literals @Test
 public void testSaveAllNextLevel() throws Exception {
 doReturn(Boolean.TRUE).when(repository).hasNextLevel();


    
 assertEquals(elements.size(), repository.saveAll(elements).size());
 verify(nextLevel, times(1)).saveAll(anyCollection());
 }
  30. Expect Literals @Test
 public void testSaveAllNextLevel() throws Exception {
 doReturn(Boolean.TRUE).when(repository).hasNextLevel();


    
 assertEquals(3, repository.saveAll(elements).size());
 verify(nextLevel, times(1)).saveAll(anyCollection());
 }
  31. Inline Setup @Before
 public void setUp() throws Exception {
 initMocks(this);


    
 elements.add(mockedElement1);
 elements.add(mockedElement2);
 elements.add(mockedElement3);
 
 ids.add(EXPECTED_FIRST_ID);
 ids.add(EXPECTED_SECOND_ID);
 ids.add(EXPECTED_THIRD_ID);
 
 repository = new BaseFastRepositoryImpl(currentLevel, null);
 }
  32. Don’t test your stubs @Test
 public void doNotTestYourStubs() throws Exception

    {
 Name name = mock(Name.class);
 // blah blah blah...
 when(name.getFullName()).thenReturn("Don't test your stubs, please!");
 // 27 lines of stuff...
 assertEquals("Don't test your stubs, please!", name.getFullName());
 }
  33. Separating The Solitary From The Sociable 1. Can be slow

    and nondeterministic Sociable Unit Tests
  34. Separating The Solitary From The Sociable 1. Can be slow

    and nondeterministic 2. Are more susceptible to cascading failures Sociable Unit Tests
  35. Should we even bother writing Unit Tests? “The key is

    to test the areas that you are most worried about going wrong. That way you get the most benefit for your testing effort.” Martin Fowler, Refactoring
  36. Extreme Programming Explained: Embrace Change, Kent Beck, AddisonWesley. Working Effectively

    with Unit Tests by Jay Fields Bibliography Mocks Aren’t Stubs (www.martinfowler.com/articles/mocksArentStubs.html) The Little Mocker (blog.8thlight.com/uncle-bob/2014/05/14/TheLittleMocker.html) https://github.com/PaNaVTEC/Clean-Contacts https://github.com/pedrovgs/Lynx https://github.com/Sefford/kor Ted Mosby - Software Architect (http://hannesdorfmann.com/android/mosby) Responsible Design for Android by J. B. Rainsberger Clean Code: A handbook of Agile Software Craftsmanship, Robert C. Martin Software Craftsmanship by Sandro Mancuso