4

我的團隊最近的一場辯論讓我感到驚訝。基本的主題是功能/集成測試應該包括多少和什麼內容(當然,它們不是一樣的,但是這個例子在沒有關係的情況下是假的)。集成測試,但多少?

比方說,你有一個「控制器」類類似:

public class SomeController { 
    @Autowired Validator val; 
    @Autowired DataAccess da; 
    @Autowired SomeTransformer tr; 
    @Autowired Calculator calc; 

    public boolean doCheck(Input input) { 
     if (val.validate(input)) { 
      return false; 
     } 

     List<Stuff> stuffs = da.loadStuffs(input); 
     if (stuffs.isEmpty()) { 
      return false; 
     } 

     BusinessStuff businessStuff = tr.transform(stuffs); 
     if (null == businessStuff) { 
      return false; 
     } 

     return calc.check(businessStuff); 
    } 
} 

我們需要很多的單元測試是肯定的(例如,如果驗證失敗,或在DB沒有數據,...),這是沒有問題的。

我們的主要問題,並就我們不能同意的是,有多少集成測試應覆蓋它:-)

我在,我們應少集成測試(測試金字塔)瞄準的一側。從這裏我將介紹的僅僅是一條從最後一行返回執行的快樂不快樂的路徑,只是爲了看看我是否將這些東西放在一起,它不會炸燬。

問題是,說明爲什麼測試結果是錯誤的,這使得一些人對此感到不安(例如,如果我們只檢查返回值,它是隱藏的該測試是綠色的,因爲有人更改了驗證,並返回false)。當然,是的,我們可以涵蓋所有的情況,但這將是一個沉重的矯枉過正的事情。

有沒有人有這種問題的經驗法則?還是推薦?讀?談論?博客文章?有關該主題的任何內容?

非常感謝!

PS:Sry爲醜陋的例子,但它很難將特定的代碼部分翻譯爲一個例子。是的,人們可以爭論拋出異常/使用不同的返回類型/等。但由於外部依賴性,我們的手或多或少地受到約束。

+0

我正在投票結束這個題目,因爲這屬於http://softwareengineering.stackexchange.com/。然而,這是一個很好的問題! – Freiheit

+0

我不同意擱置,因爲我詢問了一些參考資料(文章,隱藏在Google上的神奇馬丁福勒卷軸,關於上述情況的具體着作等)。無論如何,我會將問題添加到se.so.com並將鏈接留在此處。 – rlegendi

回答

2

這很容易找出其中,如果你遵循這些規則的測試應位於:

  • 我們檢查邏輯的單元測試水平,我們檢查邏輯調用的組件或系統水平。
  • 我們不使用模擬框架(mockito,jmock等)。

讓我們深入,但首先讓我們對術語達成一致:

  • 單元測試 - 檢查的方法,一類或隔離
  • 組件測試他們幾個 - 初始化一塊應用程序但不會將其部署到App Server。例子可能是 - 在測試中初始化Spring上下文。
  • 系統測試 - 需要在App Server上完整部署。示例可能是:將HTTP REST請求發送到遠程服務器。

如果我們構建了一個平衡金字塔,我們將在單元和組件級別進行大多數測試,其中很少會留給系統測試。這是很好的,因爲較低級別的測試更快更簡單。要做到這一點:

  • 我們應該儘可能降低業務邏輯(最好在域模型中),因爲這樣可以讓我們輕鬆地單獨測試它。每次你瀏覽一組對象並在那裏放置條件時 - 理想情況下應該去領域模型。
  • 但是,邏輯工作的事實並不意味着它被正確調用。這就是你需要組件測試的地方。初始化您的控制器以及服務和DAO,然後調用它一次或兩次以查看是否調用邏輯。

例如:用戶名不能超過50個符號,只能有拉丁文以及一些特殊符號。

  • 單元測試 - 創建一個正確和錯誤的用戶名的用戶,請檢查拋出異常,反之亦然 - 有效的名稱是經過
  • 組件測試 - 檢查,當你傳遞一個非有效用戶的控制器(如果你使用Spring MVC - 你可以使用MockMVC來實現),它會拋出錯誤。在這裏,您只需要傳遞一個用戶 - 所有的規則現在都已經被檢查過了,在這裏您只需要知道是否調用了這些規則。
  • 系統測試 - 你可能不需要,對於這種情況其實..

你如何實現平衡金字塔Here is a more elaborate example

+0

感謝您的示例,我將閱讀鏈接的博客文章。 – rlegendi

1

一般來說,我們在應用程序的每個起點(比方說每個控制器)編寫一個集成測試。我們驗證了一些快樂的流程和一些錯誤流程,有幾個斷言給我們一些安心,我們沒有破壞任何東西。

但是,我們還會在較低級別編寫測試以迴應迴歸或多個類涉及複雜行爲。

我們使用集成主要測試趕上以下類型的迴歸:

  1. 重構錯誤(沒有單元測試捕獲)。

對於重構問題,幾個IT測試打擊了你的應用程序的很大一部分是綽綽有餘的。重構通常會碰到很大一部分類,所以這些測試會暴露諸如在某個地方使用錯誤的類或參數的情況。

  • 早期檢測的注入問題(上下文不加載,彈簧)
  • 注射問題經常發生,因爲在XML配置缺少註釋或錯誤。運行和設置整個上下文(除了嘲笑後端)的第一個集成測試每次都會捕獲這些測試。

  • 錯誤在超級複雜的邏輯是幾乎不可能測試而不控制所有輸入
  • 有時你具有被分佈在幾個類代碼,需要濾波,變換等等,有時沒有人真正理解正在發生的事情。更糟糕的是,在實時系統上測試幾乎是不可能的,因爲底層數據源無法輕鬆提供觸發錯誤的確切場景。

    對於這些情況(一旦發現),我們添加一個新的集成測試,在這裏我們向系統提供導致錯誤的輸入,然後驗證它是否按預期執行。在廣泛的代碼更改之後,這給了很多安心。

    +0

    是的,我們在同一條軌道上。神奇的詞是「驗證一些快樂的流動和一些錯誤流動」。我相信這是我們集成測試的主要用法,他們不應該涵蓋所有的角落案例。他們太貴了。謝謝。 – rlegendi

    +1

    同意,您不需要測試所有角落案例 - 將角落案例添加到集成測試的唯一原因是,它經常會導致迴歸 – john16384