Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Automated Testing @Square - Droidcon NYC 2014

Dimitris
September 22, 2014

Automated Testing @Square - Droidcon NYC 2014

Scratching the surface on what appears to be a very difficult problem to get right on Android. Goals, techniques and useful tips to get started.

Dimitris

September 22, 2014
Tweet

Other Decks in Technology

Transcript

  1. Robots public class InvoiceScreenRobot extends ScreenRobot { public InvoiceScreenRobot typeTitle(String

    title) { onView(withId(R.id.title)).perform(typeText(title)); return this; } // More here... public void clickSend() { onView(withId(R.id.send)).perform(click()); } } Automated Testing
  2. Robots public void testSendInvoice() { withRobot(InvoiceScreenRobot.class) // .typeTitle("Sample Title") //

    .typeNumber("#000001") // .typeName("Square User") // .typeEmail("[email protected]") // .clickSend(); } Automated Testing
  3. Robots public void testSendInvoice() { withRobot(InvoiceScreenRobot.class) // .checkIsDisabled(R.id.send) // .typeTitle("Sample

    Title") // .typeNumber("#000001") // .typeName("Square User") // .typeEmail("[email protected]") // .checkIsEnabled(R.id.send) // .clickSend(); } Automated Testing
  4. Mock Mode @Provides @Singleton MyService provideMyService(RestAdapter adapter) { MyService real

    = restAdapter.create(MyService.class); MyService mock = new MockMyService(); return ServiceProxy.newInstance(MyService.class, mock, real); } Automated Testing
  5. Mock Mode public class ServiceProxy implements InvocationHandler { @Override public

    Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object service = mockModeOn() ? mock : real; try { return method.invoke(service, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } } Automated Testing
  6. Mock Mode public class MockMyService implements MyService { @Override public

    Response doSomething(Request request) { delay(); boolean success = true; return new Response(success); } } Automated Testing
  7. Burst Automated Testing Not @Parameterized.Parameters(name = "{0}") public static List<Object[]>

    parameters() { return Arrays.asList(new Object[] { new Factory() { @Override public BufferedSink create(Buffer data) { return data; } @Override public String toString() { return "Buffer"; } }, }, new Object[] { new Factory() { @Override public BufferedSink create(Buffer data) { return new RealBufferedSink(data); } @Override public String toString() { return "RealBufferedSink"; } } }); } @Parameterized.Parameter public Factory factory;
  8. Burst public enum Soda { COKE, PEPSI, RC_COLA } @RunWith(BurstJUnit4.class)

    public class SampleTest { @Test public void sodas(Soda soda) { // Test will run 3 times assertNotNull(soda); } } Automated Testing
  9. Burst public enum Soda { COKE, PEPSI, RC_COLA } @RunWith(BurstJUnit4.class)

    public class SampleTest { @Test public void sodasAndSnacks(Soda soda, Snack snack) { // Test will run 9 times assertNotNull(soda); assertNotNull(snack); } } public enum Snack { CHIPS, KITKAT, CANDY } Automated Testing
  10. Burst @TabletOnly public void testTabletFeature() { // This test will

    only be executed on tablets. } Automated Testing
  11. Burst @TabletOnly public void testTabletFeature() { // This test will

    only be executed on tablets. } @PhoneOnly public void testPhoneFeature() { // This test will only be executed on phones. } Automated Testing
  12. Automated Testing @TabletOnly public void testTipBringsAmountOver25() { loginAsAndStartActivity("bart"); performAuthSteps(2499L); //

    Tip withRobot(TipScreenRobot.class).clickTipOptionOne(); // Sign withRobot(SignScreenRobot.class) .performSign() .clickContinue(); // Receipt withRobot(ReceiptScreenRobot.class) .performEmailReceipt("[email protected]") .clickNewSale(); }
  13. Tips Automated Testing @Override protected void setUp() throws Exception {

    super.setUp(); setFailureHandler(new RegisterFailureHandler(this)); }
  14. Tips Automated Testing public class RegisterFailureHandler implements FailureHandler { private

    final TestCase testCase; public RegisterFailureHandler(TestCase testCase) { this.testCase = testCase; } @Override public void handle(Throwable throwable, Matcher<View> viewMatcher) { // Very useful for finding out what went wrong... takeAndUploadScreenshot(testCase.getName()); // Delegate to real failure handler here. } }
  15. Tips Automated Testing public class ScreenShotProxy implements InvocationHandler { @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Object result = method.invoke(proxy, args); takeScreenShot(); // <----- magic. return result; } catch (InvocationTargetException e) { throw e.getTargetException(); } } }