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

4 rules of simple design 1. Runs all the Tests

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

What do they all AGREE on?

Slide 8

Slide 8 text

PASSES its tests!

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

Testing motivators Validate the System

Slide 11

Slide 11 text

Testing motivators Validate the System Code Coverage

Slide 12

Slide 12 text

Testing motivators Validate the System Code Coverage Enable Refactoring

Slide 13

Slide 13 text

Testing motivators Validate the System Code Coverage Enable Refactoring Document the Behaviour of the System

Slide 14

Slide 14 text

Testing motivators Validate the System Code Coverage Enable Refactoring Document the Behaviour of the System Test Driven Development

Slide 15

Slide 15 text

Testing motivators Validate the System Code Coverage Enable Refactoring Document the Behaviour of the System Test Driven Development Customer Acceptance

Slide 16

Slide 16 text

Testing motivators Validate the System Code Coverage Enable Refactoring Document the Behaviour of the System Test Driven Development Customer Acceptance …

Slide 17

Slide 17 text

Styles of Testing STATE VERIFICATION

Slide 18

Slide 18 text

Styles of Testing STATE VERIFICATION BEHAVIOR VERIFICATION

Slide 19

Slide 19 text

HYBRID

Slide 20

Slide 20 text

Unit Test SOLITARY 1. Never crosses boundaries

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

FIRST FAST

Slide 24

Slide 24 text

FIRST FAST INDEPENDENT

Slide 25

Slide 25 text

FIRST FAST INDEPENDENT REPEATABLE

Slide 26

Slide 26 text

FIRST FAST INDEPENDENT REPEATABLE SELF-VALIDATING

Slide 27

Slide 27 text

FIRST FAST INDEPENDENT REPEATABLE SELF-VALIDATING TIMELY

Slide 28

Slide 28 text

Test Doubles DUMMY

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Test Doubles DUMMY STUB

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Test Doubles DUMMY STUB SPY

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

Test Doubles DUMMY STUB SPY MOCK

Slide 35

Slide 35 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 36

Slide 36 text

Test Doubles DUMMY STUB SPY MOCK FAKE

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

AAA ARRANGE

Slide 39

Slide 39 text

AAA ARRANGE ACT

Slide 40

Slide 40 text

AAA ARRANGE ACT ASSERT

Slide 41

Slide 41 text

What about ANDROID?

Slide 42

Slide 42 text

ANDROID Unit Testing Java Module

Slide 43

Slide 43 text

ANDROID Unit Testing Java Module AS 1.1 + Android Gradle Plugin

Slide 44

Slide 44 text

ANDROID Unit Testing Java Module MVP AS 1.1 + Android Gradle Plugin

Slide 45

Slide 45 text

ANDROID Unit Testing Java Module MVP AS 1.1 + Android Gradle Plugin MVVM

Slide 46

Slide 46 text

ANDROID Unit Testing Java Module MVP CLEAN Architecture AS 1.1 + Android Gradle Plugin MVVM

Slide 47

Slide 47 text

ANDROID Unit Testing Java Module MVP CLEAN Architecture AS 1.1 + Android Gradle Plugin MVVM Catan Architecture

Slide 48

Slide 48 text

ANDROID Unit Testing Java Module Mosby MVP CLEAN Architecture AS 1.1 + Android Gradle Plugin MVVM Catan Architecture

Slide 49

Slide 49 text

ANDROID Unit Testing Java Module Rosie Mosby MVP CLEAN Architecture AS 1.1 + Android Gradle Plugin MVVM Catan Architecture

Slide 50

Slide 50 text

ANDROID Unit Testing … Java Module Rosie Mosby MVP CLEAN Architecture AS 1.1 + Android Gradle Plugin MVVM Catan Architecture

Slide 51

Slide 51 text

DECOUPLED Architecture

Slide 52

Slide 52 text

Where do I START?

Slide 53

Slide 53 text

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

Slide 54

Slide 54 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 mobilization = new Contact();
 Name name = new Name();
 name.setFirst(“Mobilization 2016");
 mobilization.setName(name);
 when(mockContactsBddDataSource.obtain(“MobilizationMD5")).thenReturn(droidCon);
 
 Contact contact = contactsRepository.obtain("MobilizationMD5");
 
 assertEquals("Mobilization 2016", contact.getName().getFirst());
 }

Slide 55

Slide 55 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 56

Slide 56 text

How do I IMPROVE my tests? DAMP

Slide 57

Slide 57 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 58

Slide 58 text

It’s ANNOYING to have to look at the STACKTRACE to know what’s FAILING

Slide 59

Slide 59 text

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

Slide 60

Slide 60 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 61

Slide 61 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 62

Slide 62 text

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

Slide 63

Slide 63 text

READABILITY LITERALS will REFLECT the examples from the BUSINESS

Slide 64

Slide 64 text

Value Objects vs Expect Literals CONVERT VALUE OBJECT into a LITERAL

Slide 65

Slide 65 text

Avoid 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 66

Slide 66 text

READABILITY Avoid CODE DUPLICATION? BUILDERS

Slide 67

Slide 67 text

Questionable Tests Testing Language Features or Standard Library Classes

Slide 68

Slide 68 text

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

Slide 69

Slide 69 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 70

Slide 70 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 71

Slide 71 text

“Practise makes perfect.”

Slide 72

Slide 72 text

ELEGANT?? UNIT TESTING @Deprecated

Slide 73

Slide 73 text

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

Slide 74

Slide 74 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/Guardiola31337/CatanArchitecture 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