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

Elegant?? Unit Testing (Droidcon Spain 2015)

Elegant?? Unit Testing (Droidcon 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.

3c2bdd16c0ea8511dc254b8497a06f78?s=128

Pablo Guardiola

April 24, 2015
Tweet

Transcript

  1. ELEGANT?? UNIT TESTING by Pablo Guardiola @Guardiola31337

  2. TWITTER @Guardiola31337 BLOG pguardiola.com/blog

  3. Connected Car O2 Car Connection_ www.o2online.de/apps-services/ apps-entertainment/car-connection/

  4. 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
  5. On what are they all AGREED?

  6. PASSES its tests!

  7. Have you ever asked yourself, WHY? What MOTIVATES you to

    write tests?
  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
  9. Types of Tests STATE VERIFICATION BEHAVIOR VERIFICATION

  10. HYBRID

  11. Unit Test SOLITARY SOCIABLE 1. Never cross boundaries 2.The Class

    Under Test should be the only concrete class found in a test
  12. FIRST FAST INDEPENDENT REPEATABLE SELF-VALIDATING TIMELY

  13. Test Doubles DUMMY STUB SPY MOCK FAKE

  14. Dummy public class DummyAuthorizer implements Authorizer {
 @Override
 public Boolean

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

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

    = false;
 
 public Boolean authorize(String username, String password) {
 authorizeWasCalled = true;
 return true;
 }
 }
  17. 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;
 }
 }
  18. Fake public class AcceptingAuthorizerFake implements Authorizer {
 public Boolean authorize(String

    username, String password) {
 return username.equals("Bob");
 }
 }
  19. AAA ARRANGE ACT ASSERT

  20. What about ANDROID?

  21. ANDROID Unit Testing Java Module MVP CLEAN Architecture AS 1.1

    + Android Gradle Plugin MVVM KOR Rosie? Mosby (Hannes Dorfmann)
  22. DECOUPLED Architecture

  23. Where do I START?

  24. public class FooTest {
 
 @Test
 public void sampleTest() throws

    Exception {
 assertEquals(expected, actual);
 }
 } JUnit
  25. 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("DroidCon 2015");
 droidCon.setName(name);
 when(mockContactsBddDataSource.obtain("DroidCon MD5")).thenReturn(droidCon);
 
 Contact contact = contactsRepository.obtain("DroidCon MD5");
 
 assertEquals("DroidCon 2015", contact.getName().getFirst());
 }
  26. 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));
 }
  27. How do I IMPROVE my tests? DAMP

  28. 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());
 }
  29. ANNOYING to have to look at the STACKTRACE to know

    what’s FAILING Have NO INFORMATION about REMAINING TESTS
  30. 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();
 }
  31. 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
  32. 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());
 }
  33. READABILITY LITERALS will REFLECT the examples from the BUSINESS

  34. Value Objects vs Expect Literals CONVERT VALUE OBJECT to a

    LITERAL
  35. 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);
 }
  36. READABILITY Avoid CODE DUPLICATION? BUILDERS

  37. 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());
 }
  38. Separating The Solitary From The Sociable 1. Can be slow

    and nondeterministic 2. Are more susceptible to cascading failures Sociable Unit Tests
  39. Questionable Tests Testing Language Features or Standard Library Classes Testing

    Framework Features or Classes
  40. 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
  41. “Practise makes perfect.”

  42. Thank you! @Guardiola31337 pguardiola.com guardiola31337@gmail.com

  43. 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