Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

7 stages of unit testing

  1. 7 Stages of Unit Testing in Android Jorge D. Ortiz Fuentes @jdortiz #7SUnitTest
  2. A POWWAU production #7SUnitTest
  3. #7SUnitTest Daring as a fool ★ Speaking from the shoulders of giants. Look up here! ★ This is not UnitTesting 101, but complementary to it
  4. 1.
  5. Shock & Disbelief
  6. But my code is always awesome!
  7. #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
  8. #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
  9. 2.
  10. Denial
  11. C’mon, it takes ages to write tests!
  12. Time writing tests < Time debugging
  13. #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…
  14. OTS functionality JUnit AssertTestCase AndroidTestCase TestSuite ApplicationTestCase InstrumentationTes tCase ActivityInstrumenta tionTestCase2 junit.framework
  15. Run from IDE Run in (V)Device
  16. 3.
  17. Anger
  18. How do I write those f***ing tests?
  19. #7SUnitTest Types of Unit Tests ★ Test return value ★ Test state ★ Test behavior
  20. 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()); } } Example public 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"); } }
  21. public class ModelAndLogicTestSuite extends TestSuite { public static Test suite() { return new TestSuiteBuilder(ModelAndLogicTestS uite.class) .includePackages(“c om.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.cl ass) .includeAllPackag esUnderHere() .build(); } public FullTestSuite() { super(); } }
  22. Instrumentation Tests public 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())); } }
  23. 4.
  24. Bargain
  25. Ok, I’ll write some tests, but make my life simpler
  26. #7SUnitTest Dependency Injection ★ Control behavior of the dependencies • Constructor • Method overwriting • Property injection:Lazy instantiation ★ Or use a DI framework: Dagger 2
  27. 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(); }
  28. 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; }
  29. 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
  30. 5.
  31. Guilt
  32. But this ain’t state of the art
  33. #7SUnitTest Problems so far ★ Tests run in (v)device: slow ★ Unreliable behavior: • Command line • Integration with mocking
  34. 6.
  35. Depression
  36. My tests are never good enough!
  37. #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
  38. Gradle config sourceSets { 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' }
  39. How to Use JUnit 4
  40. #7SUnitTest CLI-aware Also ★ ./gradlew check • lint • test ★ Open app/build/reports/tests/debug/ index.html
  41. 7.
  42. Acceptance & Hope
  43. No tests, no fun
  44. #7SUnitTest Evolve ★ Clean Architecture ★ TDD ★ Functional tests :monkeyrunner ★ CI (Jenkins)
  45. Thank you!
  46. @jdortiz #7SUnitTest
Advertisement