原文:Test before integrate
作者:Orhan Obut
译者:lovexiaov
我们很庆幸有许多三方库,这些库可以使我们只专注于我们的业务代码。听起来理论上一切 OK,但在实践中,我们会遇到一些问题。
因为我们不知道:
- 这个库到底怎么工作?
- 它能否满足我们所有需求?
- 文档可能比较匮乏或比较完整,我们需要通过尝试来验证?
还有其他情况...
假如说我们决定在我们的产品中尝试并使用该库,以获得率先体验。以下是其中做法之一:
- 创建一个分支
- 添加依赖,在我们的产品代码中实现它并开始调试/手工测试。
- 若一切正常,则将该分支合并到主分支
- 若出现错误或该库不能满足你的需求,删掉该分支即可。
此方式有几个问题:
首先,我们希望测试该库,但我们将它和我们的产品代码混合到了一起。如果结果出现问题,我们不知道是库的问题还是我们产品代码的问题。
-
我们需要运行应用,而且可能需要执行很多步才能测到这段代码,比如:
闪屏-->登陆-->点击几下-->测试代码
即使一切正常,当该库有了新版本,而我们想要使用它时,新的版本可能会和之前的有冲突,我们可能会花费很多时间定位问题。
那么我们怎么确定该库的所有版本都稳定可用并且满足我们的需求呢?
测试先于集成
一个真实的例子:我们想使用 google places 的自动补全 API。
通过阅读文档可知,使用该 API 需要以下几步:
- 添加依赖
- 添加 API key
- 连接到 Places API
我们添加该依赖并开始写测试用例。我们希望确保我们的配置是正确的,并且能成功连接到 Google API。
第一个测试会断言连接状态。
public class GooglePlacesApiTest {
@Rule public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);
private GoogleApiClient apiClient;
@Before public void setup() throws InterruptedException {
Context context = activityTestRule.getActivity();
apiClient = new GoogleApiClient.Builder(context)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.build();
apiClient.connect();
}
@Test public void apiClientShouldConnectSuccessfully() {
assertThat(apiClient.isConnected()).isTrue();
}
}
执行该测试。
测试失败了。
我们得到如下错误,提示我们添加 API Key。
添加缺失的 API Key 之后再次运行测试。
还是失败。
GoogleApiClient
连接服务器是异步的。因此我们改变一下测试结构,在执行测试之前等待连接响应。
public class GooglePlacesApiTest {
@Rule public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);
private GoogleApiClient apiClient;
@Before public void setup() throws InterruptedException {
Context context = activityTestRule.getActivity();
final CountDownLatch latch = new CountDownLatch(1);
apiClient = new GoogleApiClient.Builder(context)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override public void onConnected(Bundle bundle) {
latch.countDown();
}
@Override public void onConnectionSuspended(int i) {
latch.countDown();
}
})
.build();
apiClient.connect();
assertThat(latch.await(3, SECONDS)).isTrue();
}
@Test public void apiClientShouldConnect() {
assertThat(apiClient.isConnected()).isTrue();
}
}
测试通过!
这样基本确认我们的配置正确了。
现在测试自动补全 API。基本上,我们会另外添加一个测试断言调用此 API 会返回成功的响应。
@Test public void shouldReturnPredictionsSuccessfully() throws Exception {
String queryToAutoComplete = "berlin";
PendingResult<AutocompletePredictionBuffer> result =
Places.GeoDataApi.getAutocompletePredictions(apiClient, queryToAutoComplete, null, null);
AutocompletePredictionBuffer predictions = result.await(3, SECONDS);
Status status = predictions.getStatus();
assertThat(status.isSuccess()).isTrue();
// more assertions
}
再次运行测试。
太棒了!所有测试都通过了。
现在我们可以深入的执行更多测试来检查该 API 是否满足我们的需求。
总结
- 断言三方库满足我们的需求
- 断言该库可用
- 书写覆盖该库未来版本修改的测试用例
- 书写当出现 bug 时会节约我们很多时间的测试用例