• Stars
    star
    218
  • Rank 181,805 (Top 4 %)
  • Language
    Java
  • Created over 8 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Android tool which helps to synchronise application behaviours with test thread in automation tests.

ConditionWatcher

Article explaining

Simple class created in order to make Android automation testing easier, faster, cleaner and more intuitive. It synchronizes operations that might occur on any thread - with test thread. ConditionWatcher can be used as a replacement to Espresso's IdlingResources or it can work in parallel with them.

When we started our adventure with Android Espresso, we came across with various problems connected to IdlingResources. Before we were able to understand how Espresso works on lower layer and explain behaviour of IdlingResources, we created our own tool beforehand and based tests on it. As we can see now principle of operation is very similar, yet we would like present to you perks of ConditionWatcher as they might become useful to you.

Related article: Wait for it… IdlingResource and ConditionWatcher

Quick Start

If you want to check how ConditionWatcher works by yourself, you can run tests included in sample project.

  1. Pull ConditionWatcher project from GitHub

  2. Connect Android device or start AVD.

  3. Run test examples included in sample project by:

    a) Android Studio - locate test files: ConditionWatcherExampleTests.java and IdlingResourceExampleTests.java. Select test class that you want to launch. Choose Run task from menu that appears after right-clicking it.

    TestPackage

    b) Command line - open terminal and change directory to the root of the ConditionWatcher project. Execute ./gradlew sample:connectedCheck to run whole test suite.

Usage

ConditionWatcher doesn't need any setup. After classes are added to your project you are ready to go.

ConditionWatcher.java - performs wait

Singleton which is automatically created after call to any of it's methods. It is meant to be destroyed along with test process. To make test code wait, you need to call waitForCondition(Instruction instruction) method. ConditionWatcher will check if the expected state is achieved with 250ms interval and throw timeout exception after 60 seconds. Those values can be easly changed and each wait case can be handled separately.

Instruction.java - informs what to wait for

It provides ConditionWatcher with information what should be scanned and when conditions are met. ConditionWatcher will keep calling Instrucion's checkCondition() method with interval until it returns true. Furthermore Instruction contains getDescription() method where you can place additional logs (for example dump of elements connected to your current wait).

ConditionWatcher in test code looks like that:

@Test
public void shouldDisplayServerDetails_conditionWatcher() throws Exception {
    List<Server> servers = DataProvider.generateServerList();
    Server thirdServer = servers.get(2);

    // SplashActivity
    ConditionWatcher.waitForCondition(new BtnStartAnimationInstruction());
    onView(withId(R.id.btnStart)).perform(click());

    // ListActivity
    ConditionWatcher.waitForCondition(new ServerListLoadingInstruction());
    onData(anything()).inAdapterView(withId(R.id.lvList)).atPosition(2).perform(click());

    // DetailsActivity
    ConditionWatcher.waitForCondition(new LoadingDialogInstruction());
    onView(withText(thirdServer.getName())).check(matches(isDisplayed()));
    onView(withText(thirdServer.getAddress())).check(matches(isDisplayed()));
    onView(withText(thirdServer.getPort())).check(matches(isDisplayed()));
}
    

Example of one instruction which waits until loading dialog disappear from view hierarchy:

public class LoadingDialogInstruction extends Instruction {
    @Override
    public String getDescription() {
        return "Loading dialog shouldn't be in view hierarchy";
    }

    @Override
    public boolean checkCondition() {
        Activity activity = ((TestApplication)
                InstrumentationRegistry.getTargetContext().getApplicationContext()).getCurrentActivity();
        if (activity == null) return false;

        DialogFragment f = 
            (DialogFragment) activity.getFragmentManager().findFragmentByTag(LoadingDialog.TAG);
        return f == null;
    }
}

Full code can be found in provided sample project. It also contains the same test created with usage of IdlingResources with exactly the same logic to pinpoint the differences.

Why ConditionWatcher?

- It is fast! - save time on synchronization

You are provided with setWatchInterval() method which allows you to change interval with which ConditionWatcher checks if all conditions are met and if test can continue. In comparison to IdlingResource if method isIdleNow() returns false, framework waits 5 seconds before it checks your condition again. It doesn't only limits your options but also forces test to wait without real need.

- It is clean! - reduce number of lines in your code

ConditionWatcher's wait Instruction objects are reusable. Consequently you don't need to unregister them before next usage. IdlingResource is added to List stored in IdlingResourceRegistry class. That List can't store two objects with the same name. Furthermore once IdlingResource is idled, it becomes unusable until you unregister it and register again.

- Less restrictions! - you are the master of your own test

IdlingResource after registered within IdlingResourceRegistry starts to wait for app's idle state only after Espresso method was called within test. So you have to use either perform() or check() to wait for idle. ConditionWatcher is not connected to Espresso framework. It uses simple Thread.sleep() method which makes your test thread to wait until condition is met. You can decide what to wait for, how and when.

- It is easy! - be creative, modify the way you like

ConditionWatcher consists of 51 lines of code. It is very easy to understand and you can adjust it to your needs. Each app is different after all.

- It is intuitive! - there is no black box part

You don't have to be worried of unexpected behaviours. ConditionWatcher will stop waiting for your condition instantly after method checkCondition() returns true. If you haven't noticed it yet, IdlingResource's method isIdleNow() is still being called a few times (with ~1ms interval) after it returns true.

Download

Library dependency

dependencies {
  androidTestImplementation 'com.azimolabs.conditionwatcher:conditionwatcher:0.2'
}

Java code

If you don't want to add another dependency to your project, just copy ConditionWatcher.java and Instruction.java classes to your source directory.

License

Copyright (C) 2016 Azimo

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Towards financial services available to all

We’re working throughout the company to create faster, cheaper, and more available financial services all over the world, and here are some of the techniques that we’re utilizing. There’s still a long way ahead of us, and if you’d like to be part of that journey, check out our careers page.

More Repositories

1

AndroidKeyboardWatcher

Software keyboard open/close watcher for Android.
Java
845
star
2

MaskFormatter

Add text masking functionality to Android EditText. It will prevent user from inserting not allowed signs, and format input as well.
Java
160
star
3

Review-Reporter

Bot for reporting Google Play Reviews on Slack with possibility to fast reply and creating Jira issues from low rating reviews.
Java
135
star
4

fastlane-plugin-automated-test-emulator-run

Plugin dedicated for Android platform. Wraps gradle task/shell command used for launching instrumented tests. Provides start of as many AVDs with various configs as needed before test run, waits for boot, kills emulators and deletes them from hdd after tests are finished or disturbed.
Ruby
112
star
5

apple-sign-in-php-sdk

PHP library to verify and validate Apple IdentityToken and authenticate a user with Apple ID.
PHP
89
star
6

Language-Switcher-Tile

An android plugin that allows you to easily change your device language.
Java
78
star
7

Api-Error-Handler

Declare expected errors of your API and generate implementing code automatically.
Java
67
star
8

AutomationTestSupervisor

Python tool for launching and managing Android Virtual Devices and Android Automation Tests. It provides elastic configurations, test and launch profiles, test video recording, html log generation and more.
Python
42
star
9

SMFloatingLabelTextField

A subclass of UITextField that displays floating placeholder
Swift
37
star
10

RxTesting

Application with examples of test cases for Android Rx code.
Java
31
star
11

WebViewTester

Android tool to automate interaction with web pages displayed in Android WebViews. Could be especially helpful in testing UI with Espresso.
Java
29
star
12

kafka-to-avro-writer

Kafka to Avro Writer based on Apache Beam. It's a generic solution that reads data from multiple kafka topics and stores it on in cloud storage in Avro format.
Java
25
star
13

scala-updatable-config

Library based on pure-config for getting updates from Consul or Vault backend.
Scala
23
star
14

CustomScrollActions

Sample project presenting how to deal with NestedScrollView in UiAutomation tests done with Espresso framework.
Java
18
star
15

AzimoTestKit

Supporting framework for writing unit tests in Swift
Swift
16
star
16

SMSecureTaskSwitcher

Use custom view for application preview in iOS Task Switcher
Objective-C
13
star
17

SimpleBDD

Simple library for tests in BDD style, written with Objective-C.
Objective-C
10
star
18

braze-templates-cli

Simple CLI tool written in Deno for creating a back-up of Braze templates and content blocks.
TypeScript
7
star
19

AzimoNote

Very simple small app that allows you to register users and store message notes bound to their profiles. Created in order to show how to setup AutomationTestSupervisor with real Android project.
Java
6
star
20

service-homescreen-aggregator

Based on our homescreen aggregator project we are showing examples for various implementation mechanisms like DynamoDB polymorphic model or rules engine etc.
Java
3
star
21

MobileInternshipTask

Programming task for mobile internship candidates
3
star
22

AppStoreConnectAPIClient

Swift
3
star
23

DecisionEngine

Example project showing basics behind our Decision Engine, built on top of Shapeless and Scala.
Scala
2
star
24

avro-rewriter

Reads, transforms and writes avro files written on Google Cloud Storage with use of Generic Avro Records.
Java
2
star
25

paloalto-gsuite

GlobalProtect authentication using SAML from G Suite
Shell
2
star
26

extend-camunda-dmn-juel-with-java-functions

This example contains ready to run Spring Boot application with Camunda where JUEL expression language is extended.
Java
1
star
27

daggerextensions

Java
1
star