7 stages of unit testing

46
7 Stages of Unit Testing in Android Jorge D. Ortiz Fuentes @jdortiz #7SUnitTest

Transcript of 7 stages of unit testing

Page 1: 7 stages of unit testing

7 Stages of Unit Testing in Android

Jorge D. Ortiz Fuentes @jdortiz

#7SUnitTest

Page 2: 7 stages of unit testing

A POWWAU production

#7SUnitTest

Page 3: 7 stages of unit testing

#7SUnitTest

Daring as a fool

★Speaking from the shoulders of giants. Look up here!

★This is not UnitTesting 101, but complementary to it

Page 4: 7 stages of unit testing

1.

Page 5: 7 stages of unit testing

Shock & Disbelief

Page 6: 7 stages of unit testing

But my code is always awesome!

Page 7: 7 stages of unit testing

#7SUnitTest

Unit Tests★Prove correctness of different aspects of the

public interface.

• Prove instead of intuition

• Define contract and assumptions

• Document the code

• Easier refactoring or change

★Reusable code = code + tests

Page 8: 7 stages of unit testing

#7SUnitTest

Use Unit Testing Incrementally

★You don’t have to write every unit test

★Start with the classes that take care of the logic

• If mixed apply SOLID

★The easier entry point are bugs

Page 9: 7 stages of unit testing

2.

Page 10: 7 stages of unit testing

Denial

Page 11: 7 stages of unit testing

C’mon, it takes ages to write

tests!

Page 12: 7 stages of unit testing

Time writing tests < Time debugging

Page 13: 7 stages of unit testing

#7SUnitTest

Good & Bad News★Most things are already available in Android Studio

★Projects are created with

• test package

• ApplicationTest class

★ It requires some tweaking

★Google docs are for Eclipse

• modules instead of projects

• different UI…

Page 14: 7 stages of unit testing

OTS functionality

JUnit

AssertTestCase

AndroidTestCase

TestSuite

ApplicationTestCase

InstrumentationTestCase

ActivityInstrumentationTestCase2

junit.framework

Page 15: 7 stages of unit testing

Run from IDE

Run in (V)Device

Page 16: 7 stages of unit testing

3.

Page 17: 7 stages of unit testing

Anger

Page 18: 7 stages of unit testing

How do I write those f***ing

tests?

Page 19: 7 stages of unit testing

#7SUnitTest

Types of Unit Tests

★Test return value

★Test state

★Test behavior

Page 20: 7 stages of unit testing

public class TaskTests extends TestCase { final static String TASK_NAME = "First task"; final static String TASK_DONE_STRING = "First task: Done"; final static String TASK_NOT_DONE_STRING = "First task: NOT done"; Task mTask; @Override public void setUp() throws Exception { super.setUp(); mTask = new Task(); } @Override public void tearDown() throws Exception { super.tearDown(); mTask = null; } public void testDoneStatusIsDisplayedProperly() throws Exception { mTask.setName(TASK_NAME); mTask.setDone(true); String taskString = mTask.toString(); assertEquals("String must be \"taskname: Done\"", TASK_DONE_STRING, taskString); } public void testNotDoneStatusIsDisplayedProperly() throws Exception { mTask.setName(TASK_NAME); mTask.setDone(false); assertEquals("String must be \"taskname: NOT done\"", TASK_NOT_DONE_STRING, mTask.toString()); } }

Examplepublic class Task { private String mName; private Boolean mDone; public String getName() { return mName; } public void setName(String name) { mName = name; } } public Boolean getDone() { return mDone; } public void setDone(Boolean done) { mDone = done; } @Override public String toString() { return mName + ": " + (mDone?"Done":"NOT done"); } }

Page 21: 7 stages of unit testing

public class ModelAndLogicTestSuite extends TestSuite { public static Test suite() { return new TestSuiteBuilder(ModelAndLogicTestSuite.class) .includePackages(“com.powwau.app.interactor”, “com.powwau.app.data”) .build(); }

public ModelAndLogicTestSuite() { super(); } }

Running more than one TestCase

public class FullTestSuite extends TestSuite { public static Test suite() { return new TestSuiteBuilder(FullTestSuite.class) .includeAllPackagesUnderHere() .build(); }

public FullTestSuite() { super(); } }

Page 22: 7 stages of unit testing

Instrumentation Testspublic class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { Activity mActivity; public MainActivityUnitTest() { super(MainActivity.class); } @Override public void setUp() throws Exception { super.setUp(); mActivity = getActivity(); } public void testHelloIsDisplayed() throws Exception { onView(withText(“Hello world!")).check(ViewAssertions.matches(isDisplayed())); } public void testSalutationChangesWithButtonClick() throws Exception { onView(withText("Touch Me")).perform(click()); onView(withText("Bye bye, Moon!”)).check(ViewAssertions.matches(isDisplayed())); } }

Page 23: 7 stages of unit testing

4.

Page 24: 7 stages of unit testing

Bargain

Page 25: 7 stages of unit testing

Ok, I’ll write some tests, but

make my life simpler

Page 26: 7 stages of unit testing

#7SUnitTest

Dependency Injection

★Control behavior of the dependencies

• Constructor

• Method overwriting

• Property injection:Lazy instantiation

★Or use a DI framework: Dagger 2

Page 27: 7 stages of unit testing

Dependency Injection for Poor Developers

public void preserveUserName(String name) { SharedPreferences prefs = getPreferences(“appPrefs”, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putString(USER_NAME_KEY, name); editor.commit(); }

Page 28: 7 stages of unit testing

Dependency Injection for Poor Developers

public void preserveUserName(String name) { SharedPreferences prefs = getAppPrefs(); SharedPreferences.Editor editor = prefs.edit(); editor.putString(USER_NAME_KEY, name); editor.commit(); }

SharedPreferences getAppPrefs() { if (mAppPrefs == null) { mAppPrefs = getPreferences(“appPrefs”, Context.MODE_PRIVATE); } return mAppPrefs; }

Page 29: 7 stages of unit testing

DataRepo dataRepoMock = mock(DataRepo.class); when(dataRepoMock.existsObjWithId(23)).thenReturn(true); verify(dataRepoMock).deleteObjWithId(23);

Simulating and Testing Behavior

★Stubs & Mocks

• Both are fake objects

• Stubs provide desired responses to the SUT

• Mocks also expect certain behaviors

Page 30: 7 stages of unit testing

5.

Page 31: 7 stages of unit testing

Guilt

Page 32: 7 stages of unit testing

But this ain’t state of the art

Page 33: 7 stages of unit testing

#7SUnitTest

Problems so far

★Tests run in (v)device: slow

★Unreliable behavior:

• Command line

• Integration with mocking

Page 34: 7 stages of unit testing

6.

Page 35: 7 stages of unit testing

Depression

Page 36: 7 stages of unit testing

My tests are never good

enough!

Page 37: 7 stages of unit testing

#7SUnitTest

Use JUnit 4★Don’t extend TestCase

★Don’t start with test (@Test instead)

★@Before & @After instead of setUp and tearDown. Also for the class

★@ignore

★Exceptions & timeouts (@Test params)

★@Theory & @DataPoints

Page 38: 7 stages of unit testing

Gradle configsourceSets { test.setRoot(“src/test”) } dependencies { testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.9.5' androidTestCompile 'junit:junit:4.12' androidTestCompile 'org.mockito:mockito-core:1.9.5' }

Page 39: 7 stages of unit testing

How to Use JUnit 4

Page 40: 7 stages of unit testing

#7SUnitTest

CLI-aware Also

★ ./gradlew check

• lint

• test

★Open app/build/reports/tests/debug/index.html

Page 41: 7 stages of unit testing

7.

Page 42: 7 stages of unit testing

Acceptance & Hope

Page 43: 7 stages of unit testing

No tests, no fun

Page 44: 7 stages of unit testing

#7SUnitTest

Evolve

★Clean Architecture

★TDD

★Functional tests :monkeyrunner

★CI (Jenkins)

Page 45: 7 stages of unit testing

Thank you!

Page 46: 7 stages of unit testing

@jdortiz #7SUnitTest