Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

7 stages of unit testing

1,983 views

Published on

My experiences on Unit Testing in the Android environment. I hope they are useful to you too.
A brief tour about how to make Android Studio run your unit tests (logical and instrumentation) and how to start creating tests for your app.

Published in: Technology

7 stages of unit testing

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

×