空闲资源忙时测试 UI

Posted

技术标签:

【中文标题】空闲资源忙时测试 UI【英文标题】:Test UI while idling resource is busy 【发布时间】:2016-10-14 12:31:39 【问题描述】:

我是 android 测试的新手,我遇到了问题。我正在使用 RxJava 并测试我正在使用 IdlingResource 的 UI。空闲资源很忙时,我无法测试 UI。

例如:我有一个按钮。 onClick 我正在做一个请求。请求按钮禁用时。请求后,按钮处于启用状态。我想测试以下 3 个步骤:

    按钮在请求之前启用 请求时按钮被禁用 (onCLick) 请求结束并返回响应消息时启用按钮

如果你能在这个问题上帮助我,我会非常非常高兴......

如果您需要有关我的问题的更多信息,请告诉我。我会编辑我的帖子

【问题讨论】:

【参考方案1】:

据我了解,您正在尝试测试您的 UI。如果是这样,请确保您以正确的方式进行操作:

1)。你没有提出REAL要求。

请理解,您的测试在类似情况下必须始终具有相同的行为。换句话说,它必须给出相同的结果,您传递的是相同的输入参数。 您现在的输入参数: 1.1)。按钮在请求之前启用 1.2)。在请求期间禁用按钮 1.3)。请求后启用的按钮

正如您从这个列表中看到的,您不需要提出真正的请求。对您而言,什么服务器会返回您(错误或成功)并不重要。您甚至不需要服务器。您所需要的只是“某物”,它的行为就像一个真正的服务器。换句话说,您必须模拟您的 API 客户端。

我想你正在使用改造。如果不是,您必须为您的客户创建 interface 包装器。如果你使用改造,你只需要模拟你的interface

假设,你有下一个interface

public interface ApiClient
    @GET("/items")
    Observable<MyResponse> doSomeRequest();

您通常如何创建您的 API 客户端:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

ApiClient service = retrofit.create(ApiClient.class);

你应该如何在测试中做到这一点:

import static org.mockito.Mockito.*;

在测试方法中:

ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest())
                .thenReturn(Observable.just(fakeResponse));

ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest())
                .thenReturn(Observable.defer(new Func0<Observable<MyResponse>>() 
                        @Override
                        public Observable<MyResponse> call() 
                            try
                                Thread.sleep(2 * 1000) //2 seconds
                            catch(Exception e)
                                return Observable.error(e);
                            
                            return Observable.just(fakeResponse);
                        
                    ));

P.S. Retrofit 默认将.subscribeOn(Schedulers.io()) 添加到所有Observable 中。这个模拟对象不这样做。所以,请不要忘记在您的代码中添加.subscribeOn(Schedulers.io()),或将其应用于Observable.defer(...)的结果 在上面的代码中,它看起来像:

when(apiMock.doSomeRequest())
     .thenReturn(Observable.defer(...).subscribeOn(Schedulers.io()));

您应该将apiMock 传递给您尝试测试的Activity / Fragment。 怎么做? 参见#2

2). 使用 DI(依赖注入)

我不会写太多关于它的。 我只是建议你阅读http://google.github.io/dagger/上的文档

尤其是,如何组织项目,何时可以使用真实实现进行生产,并使用模拟实现进行测试:

http://google.github.io/dagger/testing.html

换句话说,当您要构建应用程序以供使用时,您提供了真正的依赖项(在您的情况下,它将是 ApiClient 的真正实现),并且当您要测试一些 UI 或业务逻辑时,您传递模拟依赖项,这些依赖项具有您在测试之前指定的行为。

这就是我想告诉你的一切。希望这对您有所帮助,如果您有任何其他问题,请告诉我。

【讨论】:

【参考方案2】:

对Alexander's answer 的小补充。我会使用 Subject 来“模拟”api。这允许您控制执行。

//setup your test 
Subject<Response,Response> stubResponse = AsyncSubject.create();
ApiClient apiMock = mock(ApiClient.class);
when(apiMock.doSomeRequest()).thenReturn(stubResponse.asObservable());
//check first condition that button is enabled before executing action
//click on button
//test your second condition that button is disabled while waiting for response
stubResponse.onNext(fakeResponse); //return fake response
stubResponse.onCompleted();
//test your third condition that button is enabled when you get response back

备注。切勿在测试中使用sleep。它会减慢你的测试并增加片状。

【讨论】:

以上是关于空闲资源忙时测试 UI的主要内容,如果未能解决你的问题,请参考以下文章

又到每年最忙时,测试们准备好了吗?

XCTestCase:等待应用空闲

性能测试中 空闲内存如何计算

app性能测试指标

UI 测试不再适用于 Xcode 7.3

jakewharton Espresso 空闲资源不会导入