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

Espresso, Beyond the basics @ 360AnDev

Espresso, Beyond the basics @ 360AnDev

Iñaki Villar

July 14, 2017
Tweet

More Decks by Iñaki Villar

Other Decks in Technology

Transcript

  1. boolean isIdleNow() { if (!pool.getQueue().isEmpty()) { return false; } else

    { int activeCount = pool.getActiveCount(); if (0 != activeCount) { if (monitor.get() == null) { activeCount = activeCount - activeBarrierChecks.get(); } } return 0 == activeCount; } } AsyncTaskPoolMonitor
  2. UiController boolean injectMotionEvent(MotionEvent event) throws InjectEventSecurityException; boolean injectKeyEvent(KeyEvent event) throws

    InjectEventSecurityException; boolean injectString(String str) throws InjectEventSecurityException;
  3. UiController boolean injectMotionEvent(MotionEvent event) throws InjectEventSecurityException; boolean injectKeyEvent(KeyEvent event) throws

    InjectEventSecurityException; boolean injectString(String str) throws InjectEventSecurityException; EventInjector AsyncTaskMonitor IdlingResourceRegistry
  4. UiController boolean injectMotionEvent(MotionEvent event) throws InjectEventSecurityException; boolean injectKeyEvent(KeyEvent event) throws

    InjectEventSecurityException; boolean injectString(String str) throws InjectEventSecurityException; EventInjector AsyncTaskMonitor IdlingResourceRegistry boolean allResourcesAreIdle()
  5. ViewInteractionModule Matcher<Root> ViewFinder Matcher<View> View ViewInteractionComponent public static ViewInteraction onView(final

    Matcher<View> viewMatcher) { return BASE.plus(new ViewInteractionModule(viewMatcher)).viewInteraction(); }
  6. 
 perform(click());
 new GeneralClickAction(Tap.SINGLE, VISIBLE_CENTER, Press.FINGER)); 
 MotionEvents.sendDown(uiController, coordinates, precision);


    
 uiController.injectMotionEvent(motionEvent);
 
 MainActivityTest
 
 ViewActions
 
 Tapper
 
 MotionEvents

  7. @Override
 public void loopMainThreadUntilIdle() {
 do {
 if (!asyncTaskMonitor.isIdleNow()) {


    asyncTaskMonitor.notifyWhenIdle(…);
 condChecks.add(IdleCondition.ASYNC_TASKS_HAVE_IDLED);
 }
 
 if (!compatTaskMonitor.isIdleNow()) {
 compatTaskMonitor.notifyWhenIdle(…);
 condChecks.add(IdleCondition.COMPAT_TASKS_HAVE_IDLED);
 }
 
 if (!idlingResourceRegistry.allResourcesAreIdle()) {
 idlingResourceRegistry.notifyWhenAllResourcesAreIdle(…);
 condChecks.add(IdleCondition.DYNAMIC_TASKS_HAVE_IDLED);
 }
 
 loopUntil(condChecks);
 } while (!sIdleNow()); }
  8. @Override
 public void loopMainThreadUntilIdle() {
 do {
 if (!asyncTaskMonitor.isIdleNow()) {


    asyncTaskMonitor.notifyWhenIdle(…);
 condChecks.add(IdleCondition.ASYNC_TASKS_HAVE_IDLED);
 }
 
 if (!compatTaskMonitor.isIdleNow()) {
 compatTaskMonitor.notifyWhenIdle(…);
 condChecks.add(IdleCondition.COMPAT_TASKS_HAVE_IDLED);
 }
 
 if (!idlingResourceRegistry.allResourcesAreIdle()) {
 idlingResourceRegistry.notifyWhenAllResourcesAreIdle(…);
 condChecks.add(IdleCondition.DYNAMIC_TASKS_HAVE_IDLED);
 }
 
 loopUntil(condChecks); } while (!sIdleNow()); }
  9. abstract class WrappingES(delegate: ExecutorService) : ExecutorService { val delegate: ExecutorService

    = checkNotNull(delegate) abstract fun <T> wrapTask(callable: Callable<T>): Callable<T> fun wrapTask(command: Runnable): Runnable { val wrapped = wrapTask(Executors.callable<Any>(command, null)) return Runnable { try { wrapped.call() } catch (e: Exception) { throw RuntimeException(e) } } }
  10. abstract class WrappingES(delegate: ExecutorService) : ExecutorService { val delegate: ExecutorService

    = checkNotNull(delegate) abstract fun <T> wrapTask(callable: Callable<T>): Callable<T> fun wrapTask(command: Runnable): Runnable { val wrapped = wrapTask(Executors.callable<Any>(command, null)) return Runnable { try { wrapped.call() } catch (e: Exception) { throw RuntimeException(e) } } }
  11. abstract class WrappingES(delegate: ExecutorService) : ExecutorService { val delegate: ExecutorService

    = checkNotNull(delegate) abstract fun <T> wrapTask(callable: Callable<T>): Callable<T> fun wrapTask(command: Runnable): Runnable { val wrapped = wrapTask(Executors.callable<Any>(command, null)) return Runnable { try { wrapped.call() } catch (e: Exception) { throw RuntimeException(e) } } }
  12. override fun execute(command: Runnable) { delegate.execute(wrapTask(command)) } override fun <T>

    submit(task: Callable<T>): Future<T> { return delegate.submit(wrapTask(checkNotNull(task))) } override fun submit(task: Runnable): Future<*> { return delegate.submit(wrapTask(task)) } override fun <T> submit(task: Runnable, result: T): Future<T> { return delegate.submit(wrapTask(task), result) }
  13. class IdlingResourceExecutorService(delegate: ExecutorService, val mIdlingResource: CountingIdlingResource) : GuavaWrappingExecutorService(delegate) { override

    fun <T> wrapTask(callable: Callable<T>): Callable<T> { return WrappedCallable(callable) } private inner class WrappedCallable<T>(private val delegate: Callable<T>) : Callable<T> { @Throws(Exception::class) override fun call(): T { mIdlingResource.increment() val call: T try { call = delegate.call() } finally { mIdlingResource.decrement() } return call } } } 
 }
  14. class IdlingResourceExecutorService(delegate: ExecutorService, val mIdlingResource: CountingIdlingResource) : GuavaWrappingExecutorService(delegate) { override

    fun <T> wrapTask(callable: Callable<T>): Callable<T> { return WrappedCallable(callable) } private inner class WrappedCallable<T>(private val delegate: Callable<T>) : Callable<T> { @Throws(Exception::class) override fun call(): T { mIdlingResource.increment() val call: T try { call = delegate.call() } finally { mIdlingResource.decrement() } return call } } } 
 }
  15. class IdlingResourceExecutorService(delegate: ExecutorService, val mIdlingResource: CountingIdlingResource) : GuavaWrappingExecutorService(delegate) { override

    fun <T> wrapTask(callable: Callable<T>): Callable<T> { return WrappedCallable(callable) } inner class WrappedCallable<T>(val delegate: Callable<T>) : Callable<T> { @Throws(Exception::class) override fun call(): T { mIdlingResource.increment() val call: T try { call = delegate.call() } finally { mIdlingResource.decrement() } return call } } } 
 }
  16. public class RxSchedulerHook extends RxJavaSchedulersHook {
 
 private Scheduler customScheduler;


    private CountingIdlingResource idling;
 private static RxSchedulerHook sInstance;
 public RxSchedulerHook(CountingIdlingResource countingIdlingResource) {
 FailedTest watcher = new FailedTest();
 idling = countingIdlingResource;
 customScheduler = new Scheduler() {
 @Override public Scheduler.Worker createWorker() {
 return new CustomWorker();
 }
 };
 }

  17. @Override public Subscription schedule(final Action0 action, final long delayTime, TimeUnit

    unit) {
 return super.schedule(new Action0() {
 @Override public void call() {
 
 action.call();
 }
 }, delayTime, unit);
 }
 
 @Override public Subscription schedule(final Action0 action) {
 return super.schedule(new Action0() {
 @Override public void call() {
 idling.increment();
 try {
 action.call();
 } finally {
 idling.decrement();
 }
 }
 });
 }
  18. @Rule public ActivityTestRule<Main> activityTestRule = new ActivityTestRule<>(Main){
 @Override
 protected void

    beforeActivityLaunched() {
 super.beforeActivityLaunched();
 }
 
 @Override
 protected void afterActivityLaunched() {
 super.afterActivityLaunched();
 }
 
 @Override
 protected void afterActivityFinished() {
 super.afterActivityFinished();
 }
 };
  19. @Rule public ActivityTestRule<Main> activityTestRule = new ActivityTestRule<>(Main){
 @Override
 protected void

    beforeActivityLaunched() {
 super.beforeActivityLaunched();
 }
 
 @Override
 protected void afterActivityLaunched() {
 super.afterActivityLaunched();
 }
 
 @Override
 protected void afterActivityFinished() {
 super.afterActivityFinished();
 }
 };
  20. @Rule public IntentTestRule<Main> activityTestRule = new IntentTestRule<>(Main) 
 
 public

    IntentsTestRule(Class<T> activityClass, boolean initialTouchMode,
 boolean launchActivity) {
 super(activityClass, initialTouchMode, launchActivity);
 }
 
 @Override
 protected void afterActivityLaunched() {
 Intents.init();
 super.afterActivityLaunched();
 }
 
 @Override
 protected void afterActivityFinished() {
 super.afterActivityFinished();
 Intents.release();
 }
 
 

  21. public interface TestRule {
 Statement apply(Statement base, Description description);
 }

    public class UiThreadTestRule implements TestRule {
 private static final String LOG_TAG = "UiThreadTestRule";
 
 @Override
 public Statement apply(final Statement base, Description description) {
 return new UiThreadStatement(base, shouldRunOnUiThread(description));
 }
 
 protected boolean shouldRunOnUiThread(Description description) {
 return description.getAnnotation(UiThreadTest.class) != null;
 } }
  22. private class ActivityStatement extends Statement {
 
 private final Statement

    mBase;
 
 public ActivityStatement(Statement base) {
 mBase = base;
 }
 
 @Override
 public void evaluate() throws Throwable {
 try {
 if (mLaunchActivity) {
 act = launchActivity(getActivityIntent());
 }
 mBase.evaluate();
 } finally {
 finishActivity();
 }
 }
 }
  23. public class TraceTestRule implements TestRule {
 
 private Trace trace;


    
 @Override
 public Statement apply(final Statement base, Description description) {
 return new Statement() {
 @Override
 public void evaluate() throws Throwable {
 try {
 trace.start();
 base.evaluate();
 } finally {
 trace.end();
 }
 }
 };
 }
 }
  24. public class TraceTestRule implements TestRule {
 
 private Trace trace;


    
 @Override
 public Statement apply(final Statement base, Description description) {
 return new Statement() {
 @Override
 public void evaluate() throws Throwable {
 try {
 trace.start();
 base.evaluate();
 } finally {
 trace.end();
 }
 }
 };
 }
 } @Rule
 public TraceTestRule traceTestRule = new TraceTestRule(getTargetContext());

  25. return new Statement() {
 @Override
 public void evaluate() throws Throwable

    {
 List<Throwable> errors = new ArrayList<Throwable>();
 
 startingQuietly(description, errors);
 try {
 base.evaluate();
 succeededQuietly(description, errors);
 } catch (AssumptionViolatedException e) {
 errors.add(e);
 skippedQuietly(e, description, errors);
 } catch (Throwable e) {
 errors.add(e);
 failedQuietly(e, description, errors);
 } finally {
 finishedQuietly(description, errors);
 }
 
 MultipleFailureException.assertEmpty(errors);
 }
 }; public abstract class TestWatcher implements TestRule
  26. return new Statement() {
 @Override
 public void evaluate() throws Throwable

    {
 List<Throwable> errors = new ArrayList<Throwable>();
 
 startingQuietly(description, errors);
 try {
 base.evaluate();
 succeededQuietly(description, errors);
 } catch (AssumptionViolatedException e) {
 errors.add(e);
 skippedQuietly(e, description, errors);
 } catch (Throwable e) {
 errors.add(e);
 failedQuietly(e, description, errors);
 } finally {
 finishedQuietly(description, errors);
 }
 
 MultipleFailureException.assertEmpty(errors);
 }
 }; public abstract class TestWatcher implements TestRule
  27. public class FailedTest extends TestWatcher {
 
 public FailedTest() {


    uiAutomation = UiDevice.getInstance();
 }
 
 
 @Override
 protected void failed(Throwable e, Description description) {
 super.failed(e, description);
 String fileNameBase = getFileNameWithoutExtension(description);
 saveScreenshot(fileNameBase);
 saveInfo(fileNameBase);
 }
 
 @Override
 protected void succeeded(Description description) {
 super.succeeded(description);
 }
 
 @Override
 protected void skipped(AssumptionViolatedException e, Description description) {
 super.skipped(e, description);
 }

  28. public class FailedTest extends TestWatcher {
 
 public FailedTest() {


    uiAutomation = UiDevice.getInstance();
 }
 
 
 @Override
 protected void failed(Throwable e, Description description) {
 super.failed(e, description);
 String fileNameBase = getFileNameWithoutExtension(description);
 saveScreenshot(fileNameBase);
 saveInfo(fileNameBase);
 }
 
 @Override
 protected void succeeded(Description description) {
 super.succeeded(description);
 }
 
 @Override
 protected void skipped(AssumptionViolatedException e, Description description) {
 super.skipped(e, description);
 }

  29. public class FailedTest extends TestWatcher {
 
 public FailedTest() {


    uiAutomation = UiDevice.getInstance();
 }
 
 
 @Override
 protected void failed(Throwable e, Description description) {
 super.failed(e, description);
 String fileNameBase = getFileNameWithoutExtension(description);
 saveScreenshot(fileNameBase);
 saveInfo(fileNameBase);
 }
 
 @Override
 protected void succeeded(Description description) {
 super.succeeded(description);
 }
 
 @Override
 protected void skipped(AssumptionViolatedException e, Description description) {
 super.skipped(e, description);
 }

  30. public class RuleChain implements TestRule
 public RuleChain ruleChain = RuleChain.outerRule(new

    LogRule("outer rule")
 .around(new LogRule("middle around rule")
 .around(new LogRule("inner around rule”))));
  31. public class RuleChain implements TestRule
 public RuleChain ruleChain = RuleChain.outerRule(new

    LogRule("outer rule")
 .around(new LogRule("middle around rule")
 .around(new LogRule("inner around rule”)))); Starting outer Starting middle Starting inner Finishing inner Finishing middle Finishing outer
  32. public NewActivityTestRule<Main> activityRule = new NewActivityTestRule<>(Main.class);
 
 
 @Rule
 public

    RuleChain chain = RuleChain.outerRule(new FailedTest() .around(activityRule);

  33. public NewActivityTestRule<Main> activityRule = new NewActivityTestRule<>(Main.class);
 
 
 @Rule
 public

    RuleChain chain = RuleChain.outerRule(new FailedTest() .around(activityRule);
 
 @Rule
 public RuleChain chain = RuleChain.outerRule(new FailedTest()) .around(new TraceTestRule()) .around(activityRule);