Slide 1

Slide 1 text

ELEGANT?? UNIT TESTING by Pablo Guardiola @Guardiola31337

Slide 2

Slide 2 text

TWITTER @Guardiola31337 BLOG pguardiola.com/blog

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

On what are they all AGREED?

Slide 6

Slide 6 text

PASSES its tests!

Slide 7

Slide 7 text

Have you ever asked yourself, WHY? What MOTIVATES you to write tests?

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Types of Tests STATE VERIFICATION BEHAVIOR VERIFICATION

Slide 10

Slide 10 text

HYBRID

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

FIRST FAST INDEPENDENT REPEATABLE SELF-VALIDATING TIMELY

Slide 13

Slide 13 text

Test Doubles DUMMY STUB SPY MOCK FAKE

Slide 14

Slide 14 text

Dummy public class DummyAuthorizer implements Authorizer {
 @Override
 public Boolean authorize(String username, String password) {
 return null;
 }
 }

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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;
 }
 }

Slide 18

Slide 18 text

Fake public class AcceptingAuthorizerFake implements Authorizer {
 public Boolean authorize(String username, String password) {
 return username.equals("Bob");
 }
 }

Slide 19

Slide 19 text

AAA ARRANGE ACT ASSERT

Slide 20

Slide 20 text

What about ANDROID?

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

DECOUPLED Architecture

Slide 23

Slide 23 text

Where do I START?

Slide 24

Slide 24 text

public class FooTest {
 
 @Test
 public void sampleTest() throws Exception {
 assertEquals(expected, actual);
 }
 } JUnit

Slide 25

Slide 25 text

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());
 }

Slide 26

Slide 26 text

Clean Contacts @Test public void contactsInteractorExecutedWhenResumed() throws Exception {
 InteractorInvoker interactorInvoker = mock(InteractorInvoker.class);
 GetContactsInteractor getContactsInteractor = mock(GetContactsInteractor.class);
 final ListMapper 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));
 }

Slide 27

Slide 27 text

How do I IMPROVE my tests? DAMP

Slide 28

Slide 28 text

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());
 }

Slide 29

Slide 29 text

ANNOYING to have to look at the STACKTRACE to know what’s FAILING Have NO INFORMATION about REMAINING TESTS

Slide 30

Slide 30 text

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();
 }

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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());
 }

Slide 33

Slide 33 text

READABILITY LITERALS will REFLECT the examples from the BUSINESS

Slide 34

Slide 34 text

Value Objects vs Expect Literals CONVERT VALUE OBJECT to a LITERAL

Slide 35

Slide 35 text

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);
 }

Slide 36

Slide 36 text

READABILITY Avoid CODE DUPLICATION? BUILDERS

Slide 37

Slide 37 text

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());
 }

Slide 38

Slide 38 text

Separating The Solitary From The Sociable 1. Can be slow and nondeterministic 2. Are more susceptible to cascading failures Sociable Unit Tests

Slide 39

Slide 39 text

Questionable Tests Testing Language Features or Standard Library Classes Testing Framework Features or Classes

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

“Practise makes perfect.”

Slide 42

Slide 42 text

Thank you! @Guardiola31337 pguardiola.com [email protected]

Slide 43

Slide 43 text

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