天天看點

編寫 android 測試單元該做的和不該做的事

一個新聞 app 應該會有以下這些 activity。

  語言選擇 - 當使用者第一次打開軟體, 他必須至少選擇一種語言。選擇後,選項儲存在共享偏好中,使用者跳轉到新聞清單 activity。

  新聞清單 - 當使用者來到新聞清單 activity,将發送一個包含語言參數的請求到伺服器,并将伺服器傳回的内容顯示在 recycler view 上(包含有新聞清單的 id, news_list)。 如果共享偏好中未存語言參數,或者伺服器沒有傳回一個成功消息, 就會彈出一個錯誤對話框并且 recycler view 将不可見。如果使用者隻選擇了一種語言,新聞清單 activity 有個 “change your language” 的按鈕,或者如果使用者選擇多種語言,則按鈕為 “change your languages” 。 (我對天發誓這是一個虛構的 app 軟體)

  新聞細節 - 如同名字所述, 當使用者點選新聞清單項時将啟動這個 activity。

這個 app 功能已經足夠,,讓我們深入研究下為新聞清單 activity 編寫的測試用例。 這是我第一次寫的代碼。

<code>/*</code>

<code>click on the first news item.</code>

<code>it should open newsdetailactivity</code>

<code>*/</code>

<code>@test</code>

<code>public void testclickonanynewsitem() {</code>

<code>onview(allof(withid(r.id.news_list), isdisplayed())).perform(recyclerviewactions</code>

<code>.actiononitematposition(1, click()));</code>

<code>intended(hascomponent(newsdetailsactivity.class.getname()));</code>

<code>}</code>

<code></code>

<code>/**</code>

<code>* to test the correct text on the button</code>

<code>public void testchangelanguagefeature() {</code>

<code>int count = userpreferenceutil.getselectedlanguagescount();</code>

<code>if (count == 1) {</code>

<code>onview(withtext("choose your language")).check(matches(isdisplayed()));</code>

<code>} else if (count &gt; 1) {</code>

<code>onview(withtext("choose your languages")).check(matches(isdisplayed()));</code>

<code>?}</code>

<a target="_blank"></a>

在第一個測試用例 <code>testclickonanynewsitem()</code>, 如果伺服器沒有傳回成功資訊,測試用例将會傳回失敗,因為 recycler view 是不可見的。但是這個測試用例的目的并非如此。不管該用例為 pass 還是 fail,它的最低要求是 recycler view 總是可見的, 如果因某種原因,recycler view 不可見,那麼測試用例不應視為 failed。正确的測試代碼應該像下面這個樣子。

<code>click on any news item.</code>

<code>try {</code>

<code>/*to test this case, we need to have recyclerview present. if we don't have the</code>

<code>recyclerview present either due to the presence of error_screen, then we should consider</code>

<code>this test case successful. the test case should be unsuccesful only when we click on a</code>

<code>news item and it doesn't open newsdetail activity</code>

<code>viewinteraction viewinteraction = onview(withid(r.id.news_list));</code>

<code>viewinteraction.check(matches(isdisplayed()));</code>

<code>} catch (nomatchingviewexception e) {</code>

<code>return;</code>

<code>} catch (assertionfailederror e) {</code>

<code>&amp;nbsp; &amp;nbsp;//在這裡我們确信,news_list的 recyclerview 對使用者是可見的。</code>

<code>&amp;nbsp; &amp;nbsp;onview(allof(withid(r.id.news_list), isdisplayed())).perform(recyclerviewactions</code>

當我開始測試, 我通常按如下順序測試 activity:

語言選擇

新聞清單

新聞細節

因為我首先測試語言選擇 activity,在測試 newslist activity 之前,總有一種語言已經是選擇好了的。但是當我先測試新聞清單 activity 時,測試用例開始傳回錯誤資訊。原因很簡單 - 沒有選擇語言,recycler view 不會顯示。注意, 測試用例的執行順序不能影響測試結果。 是以在運作測試用例之前, 語言選項必須是儲存在共享偏好中的。在本例中,測試用例獨立于語言選擇 activity 的測試。

<code>@rule</code>

<code>public activitytestrule activitytestrule =</code>

<code>new activitytestrule(topicsactivity.class, false, false);</code>

<code>userpreferenceutil.saveuserprimarylanguage("english");</code>

<code>intent intent = new intent();</code>

<code>activitytestrule.launchactivity(intent);</code>

現在在第二個測試用例 <code>testchangelanguagefeature()</code> 中,我們擷取到使用者選擇語言的個數,基于這個數目,我們寫了 if-else 條件來進行測試。 但是 if-else 條件應該寫在你的代碼當中,而不是測試代碼裡。每一個條件應該單獨測試。 是以,在本例中,不是隻寫一條測試用例,而是要寫如下兩個測試用例。

<code>* to test the correct text on the button when only one language is selected.</code>

<code>public void testchangelanguagefeatureforsingelanguage() {</code>

<code>//other initializations</code>

<code>userpreferenceutil.saveselectedlanguagescount(1);</code>

<code>* to test the correct text on the button when more than one language is selected.</code>

<code>public void testchangelanguagefeatureformultiplelanguages() {</code>

<code>userpreferenceutil.saveselectedlanguagescount(5); //write anything greater than 1.</code>

在大多數應用中,我們與外部網絡或者資料庫進行互動。一個測試用例運作時可以向伺服器發送一個請求,并擷取成功或失敗的傳回資訊。但是不能因從伺服器擷取到失敗資訊,就認為測試用例沒有通過。這樣想這個問題 - 如果測試用例失敗,然後我們修改用戶端代碼,以便測試用例通過。 但是在本例中, 我們要在用戶端進行任何更改嗎?- no。

但是你應該也無法完全避免要測試網絡請求和響應。由于伺服器是一個外部代理,我們可以設想一個場景,發送一些可能導緻程式崩潰的錯誤響應。是以,你寫的測試用例應該覆寫所有可能來自伺服器的響應,甚至包括伺服器決不會發出的響應。這樣可以覆寫所有代碼,并能保證應用可以處理所有響應,而不會崩潰。

正确的編寫測試用例與編寫這些測試代碼同等重要。

原文釋出時間為:2017-02-12

本文來自雲栖社群合作夥伴“linux中國”