单元测试系列之六Espresso
之前介绍的都是逻辑测试,不用运行在模拟器或者真机上,做Android开发测试,免不了要进行UI测试,而大部分的UI更新都是异步的,这时候要进行单元测试就需要想别的方法了。这里介绍一下框架,espresso,体积小,运行快。
对同步更新UI的方法进行测试并不难,比如点击按钮,点击后改变Textview
的内容,这很简单。但是更多时候我们用到的是异步更新UI。如果直接进行测试,大概率会报错,因为在执行测试代码来测试数据是否展示在UI上时,异步数据很有可能还没有获取到。针对这个问题,我们借助espresso,使用框架中的SimpleCountingIdlingResource
和EspressoIdlingResourceManager
可以实现异步更新UI的测试。
首先在activity中添加这样一个方法,这个方法是给测试时提供获取IdlingResource的接口
@VisibleForTesting public SimpleCountingIdlingResource getCountingIdlingResource() { return EspressoIdlingResourceManager.getIdlingResource(); }复制代码
当我们开始异步请求前,将IdlingResource的标记加一,这就意味着已经开始异步了
//在开始异步请求前添加这行代码,意味着开始了异步 EspressoIdlingResourceManager.increment();复制代码
当请求结束,我们再添加这行代码,说明网络请求结束:
//异步加载成功,结束异步 if (!EspressoIdlingResourceManager.getIdlingResource().isIdleNow()) { EspressoIdlingResourceManager.decrement(); }复制代码
然后回到测试类中,添加如下测试代码:
private IdlingResource idlingresource; @Test public void testAsync2() throws Exception { //调用Activity中我们已经设置好的getIdlingresource()方法,获取Idlingresource对象 idlingresource = ((MainActivity) activityTestRule.getActivity()).getCountingIdlingResource(); // 操作:点击Button onView(withId(R.id.async_btn)) .perform(click()); //注册异步监听,当该idlingresource中的counter标记值为0时才进行接下来的测试代码 Espresso.registerIdlingResources(idlingresource); // 未注册idlingResource时,立即进行test,此时异步并未结束,报错(tests failed) onView(withId(R.id.textview)) .check(matches(withText("异步测试结果显示"))) .check(matches(isDisplayed())); //我们在测试结束后取消注册,释放资源 Espresso.unregisterIdlingResources(idlingresource); }复制代码
上面提到了两个类的源码如下:
EspressoIdlingResourceManager.class
public class EspressoIdlingResourceManager { private static final String RESOURCE = "GLOBAL"; private static SimpleCountingIdlingResource mCountingIdlingResource = new SimpleCountingIdlingResource(RESOURCE); public static void increment() { mCountingIdlingResource.increment(); } public static void decrement() { mCountingIdlingResource.decrement(); } public static SimpleCountingIdlingResource getIdlingResource() { return mCountingIdlingResource; } }复制代码
SimpleCountingIdlingResource.class
public final class SimpleCountingIdlingResource implements IdlingResource { private final String mResourceName; //这个counter值就像一个标记,默认为0 private final AtomicInteger counter = new AtomicInteger(0); private volatile ResourceCallback resourceCallback; public SimpleCountingIdlingResource(String resourceName) { mResourceName = resourceName; } @Override public String getName() { return mResourceName; } @Override public boolean isIdleNow() { return counter.get() == 0; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } //每当我们开始异步请求,把counter值+1 public void increment() { counter.getAndIncrement(); } //当我们获取到网络数据后,counter值-1; public void decrement() { int counterVal = counter.decrementAndGet(); //如果这时counter == 0,说明异步结束,执行回调。 if (counterVal == 0) { // if (null != resourceCallback) { resourceCallback.onTransitionToIdle(); } } if (counterVal < 0) { //如果小于0,抛出异常 throw new IllegalArgumentException("Counter has been corrupted!"); } } }复制代码
这样,我们就完成了异步更新UI的测试。
作者:大师傅姑爷
链接:https://juejin.cn/post/7019602711867818020