diff --git a/translated/tech/20161227 The Dos and Donts of Writing Test cases in Android.md b/translated/tech/20161227 The Dos and Donts of Writing Test cases in Android.md index 73ac7a1680..d6df221b5d 100644 --- a/translated/tech/20161227 The Dos and Donts of Writing Test cases in Android.md +++ b/translated/tech/20161227 The Dos and Donts of Writing Test cases in Android.md @@ -1,20 +1,17 @@ -编写android测试单元应该做的和不应该做的. +编写 android 测试单元该做的和不该做的事 ============================================================ -在本文中, 根据我的实际经验我将为大家阐述一个测试用例.在本文中我将使用Espresso编码, 但是它们可以用到单元测试当中. 基于以上目的, 我们来研究一个新闻程序. +在本文中, 我将根据我的实际经验,为大家阐述一个编写测试用例的最佳实践。在本文中我将使用 Espresso 编码, 但是它们可以用到单元和 instrumentation 测试当中。基于以上目的, 我们来研究一个新闻程序. -> 以下内容纯属虚构,如有雷同纯属巧合:P +> 以下内容纯属虚构,如有雷同纯属巧合:P -一个新闻APP应该会有以下几个工作流. +一个新闻 APP 应该会有以下这些 活动activities。 +*   语言选择 - 当用户第一次打开软件, 他必须至少选择一种语言。选择后,选项保存在共享偏好中,用户跳转到新闻列表 activity。 +*   新闻列表 - 当用户来到新闻列表 activity,将发送一个包含语言参数的请求到服务器,并将服务器返回的内容显示在 recycler view 上(包含有新闻列表的 id _news_list_)。 如果共享偏好中未存语言参数,或者服务器没有返回一个成功消息, 就会弹出一个错误对话框并且 recycler view 将不可见。如果用户只选择了一种语言,新闻列表 activity 有个 “Change your Language” 的按钮,或者如果用户选择多种语言,则按钮为 “Change your Languages” 。 ( 我对天发誓这是一个虚构的 APP 软件) +*   新闻细节 - 如同名字所述, 当用户点选新闻列表项时将启动这个 activity。 -* 语言选择页面- 当用户第一次打开软件, 他必须至少选择一种语言. 当选择一个或者多个语言, 用shared preferences保存选项,用户跳转到新闻列表页面. -* 新闻列表页面- 当用户来到新闻列表页面, 将发送一个包含语言参数的请求到服务器,并将服务器返回的内容显示在recycler view上(包含有新闻列表的 id?_news_list_). 如果语言参数不存在在shared preferences或者服务器没有返回一个成功消息, 就会弹出一个错误对话框并且recycler view将不可见. 新闻列表页面有个名叫 “Change your Language” 的按钮,如果用户选择了一种语言 或者用户选择多种语言“Change your Languages” 永远是可见的. ( 我对天发誓这是一个虚构的APP软件) -* 新闻详细内容-如同名字所述, 当用户点选新闻列表项将启动这个页面. - - -这个APP已经研究的足够了,让我们深入新闻列表页面编写测试用例. 这是我第一次写的代码. - +这个 APP 功能已经足够,,让我们深入研究下为新闻列表 activity 编写的测试用例。 这是我第一次写的代码。 ``` /* @@ -42,9 +39,10 @@ } ?} ``` -#### 仔细想想测试什么. -我们首先来测试新闻列表项的点击_?testClickOnAnyNewsItem()_, 如果服务器没有返回成功信息, 测试用例将会返回失败,因为recycler view是不可见的. 但是这个测试用例的通过或者失败并不是我们所期望的结果, 它要求不管什么原因recycler view都是可见的, 如果recycler view不可见,将返回失败信息. 正确的测试代码应该像下面这个样子. +#### 仔细想想测试什么。 + +在第一个测试用例 _testClickOnAnyNewsItem()_, 如果服务器没有返回成功信息,测试用例将会返回失败,因为 recycler view 是不可见的。但是这个测试用例的目的并非如此。 **不管该用例为 PASS 还是 FAIL,它的最低要求是 recycler view 总是可见的,** 如果因某种原因,recycler view 不可见,那么测试用例不应视为 FAILED。正确的测试代码应该像下面这个样子。 ``` /* @@ -66,8 +64,8 @@ } catch (AssertionFailedError e) { return; } - //Here we are sure, that the news_list recyclerview is visible to the user. - onView(allOf(withId(R.id.news_list), isDisplayed())).perform(RecyclerViewActions +    //在这里我们确信,news_list的 recyclerview 对用户是可见的。 +    onView(allOf(withId(R.id.news_list), isDisplayed())).perform(RecyclerViewActions .actionOnItemAtPosition(1, click())); intended(hasComponent(NewsDetailsActivity.class.getName())); } @@ -76,13 +74,15 @@ ``` #### 一个测试用例本身应该是完整的 -当我开始测试, 我通常按如下顺序测试 +当我开始测试, 我通常按如下顺序测试 activities: -* 语音选择页面 -* 新闻列表页面 -* 新闻详细内容 +* 语音选择 -当我开始测试语音选择页面, 总有一种语音已经是选择好了的. 但是当我测试新闻列表页面, 测试用例开始返回错误信息. 原因很简单- 没有选择语音,recycler view讲不会显示出来.因此, 测试用例的执行顺序不能影响测试结果. 因此在运行测试用例之前, 语言选项必须是保存的. 在本例中,测试用例独立与语言选择页面单独运行. +* 新闻列表 + +*   新闻细节 + +因为我首先测试语音选择 activity,在测试 NewsList activity 之前,总有一种语音已经是选择好了的。但是当我先测试新闻列表 activity 时,测试用例开始返回错误信息。原因很简单 - 没有选择语言,recycler view 不会显示。**注意, 测试用例的执行顺序不能影响测试结果。** 因此在运行测试用例之前, 语言选项必须是保存在共享偏好中的。在本例中,测试用例独立于语言选择 activity 的测试。 ``` @Rule @@ -111,9 +111,9 @@ intended(hasComponent(NewsDetailsActivity.class.getName())); ?} ``` -#### 在测试用例中避免使用条件代码. +#### 在测试用例中避免使用条件代码。 -现在在第二个测试用例_testChangeLanguageFeature()_, 我们获取到用户选择语言个数, 我们写了if-else条件来进行测试 . 但是 if-else 条件应该写在你的代码当中, 不是测试代码里. 每一个条件应该单独测试. 因此, 在本例中, 我们将写如下两个测试用例. +现在在第二个测试用例 _testChangeLanguageFeature()_中,我们获取到用户选择语言的个数, 基于这个数目,我们写了 if-else 条件来进行测试。 但是 if-else 条件应该写在你的代码当中,而不是测试代码里。每一个条件应该单独测试。 因此, 在本例中, 不是只写一条测试用例,而是要写如下两个测试用例。 ``` /** @@ -143,16 +143,16 @@ ``` #### 测试用例应该独立于外部因素 -在大多数APP中, 我们与外部网络或者数据库进行交互.一个测试用例可以向服务器发送一个请求并获取返回信息. 但是当获取失败信息以后, 我们不能认为测试用例没有通过.试想一下如果测试用例没有通过, 然后我们修改客户端代码,测试用例通过. 但是在本文中, 我们有在客户端进行任何更改吗?-没有. +在大多数应用中,我们与外部网络或者数据库进行交互。一个测试用例运行时可以向服务器发送一个请求,并获取成功或失败的返回信息。但是不能因从服务器获取到失败信息,就认为测试用例没有通过。这样想这个问题 - 如果测试用例失败,然后我们修改客户端代码,以便测试用例通过。 但是在本例中, 我们要在客户端进行任何更改吗?- **NO**。 -但是你应该也无法避免要测试网络请求和响应. 由于服务器是一个外部代理, 我们可以设想一个场景,发送一些可能导致程序崩溃的错误请求. 因此, 你写的测试用例应该覆盖所有可能来自服务器的响应,通过这种方式来保证你的代码不会崩溃. +但是你应该也无法完全避免要测试网络请求和响应。由于服务器是一个外部代理,我们可以设想一个场景,发送一些可能导致程序崩溃的错误响应。因此, 你写的测试用例应该覆盖所有可能来自服务器的响应,甚至包括服务器决不会发出的响应。这样可以覆盖所有代码,并能保证应用可以处理所有响应,而不会崩溃。 -> 正确的编写测试用例非常重要的. -感谢你阅读此文章。你可以联系我[LinkedIn][1]. 你还可以阅读我的其他文章[here][2]. +> 正确的编写测试用例与编写这些测试代码同等重要。 -获取更多资讯请关注?_[_Mindorks_][3]_?, 你将获得我们的最新信息. +感谢你阅读此文章。希望对测试用例写的更好有所帮助。你可以在 [LinkedIn][1] 上联系我。还可以[在这里][2]阅读我的其他文章。 +获取更多资讯请关注_[Mindorks][3]_, 我们发新文章时您将获得通知。 --------------------------------------------------------------------------------