高效的企业测试-单元和用例测试(2/6)
在本系列的第一部分中,我們看到了有效測試應滿足的一些普遍適用的原則和約束。 在這一部分中,我們將仔細研究代碼級單元測試以及組件或用例測試。
單元測試
單元測試驗證單個單元(通常是類)的行為,而忽略或模擬該單元外部的所有問題。 單元測試應測試各個單元的業務邏輯,而不驗證其進一步的集成或配置。
根據我的經驗,大多數企業開發人員對單元測試的構建方式都有很好的了解。 您可以在我的咖啡測試項目中查看此示例,以了解想法。 大多數項目將JUnit與Mockito結合使用以模擬依賴關系,理想情況下使用AssertJ來有效定義可讀的斷言。 我一直認為,我們可以執行單元測試而無需特殊的擴展程序或運行程序,即僅使用純JUnit運行它們。 原因很簡單:執行時間; 我們應該能夠在幾毫秒內運行數百個測試。
單元測試通常執行速度非常快,并且易于執行,并且不會對測試套件的生命周期施加任何約束,因此可以輕松支持構建復雜的測試套件或特殊的開發工作流程。
但是,具有許多模擬被測類的依賴關系的單元測試的缺點是,它們將與實現緊密結合,尤其是類結構和方法,這使得重構代碼變得困難。 換句話說,對于生產代碼中的每個重構動作,測試代碼也需要更改。 在最壞的情況下,這會導致開發人員進行較少的重構,這僅僅是因為它們變得太麻煩了,從而很快導致項目代碼質量下降。 理想情況下,開發人員應該能夠重構代碼并四處移動,只要他們不改變應用程序的行為(從用戶的角度來看)即可。 單元測試并不總是使重構生產代碼變得容易。
根據項目經驗,單元測試對于測試具有簡潔邏輯或功能的高密度代碼(例如特定算法的實現)非常有效,同時又不會與其他組件發生過多交互。 特定類中的代碼密度越小或越復雜,循環復雜性越低,或者與其他組件的交互作用越高,則測試該類的單元測試效果就越差。 尤其是在具有少量專業業務邏輯并且與外部系統的集成程度相當的微服務中,可以說,對許多單元測試的需求減少了。 除了少數例外,這些系統的各個單元通常包含很少的專用邏輯。 選擇在哪里花時間和精力進行權衡時,必須考慮到這一點。
用例測試
為了解決將測試與實現緊密耦合的問題,我們可以使用略有不同的方法來擴大測試范圍。 在我的書中 ,我描述了組件測試的概念,因為缺少更好的術語,我們也可以將其稱為用例測試。
用例測試是代碼級別的集成測試,由于測試啟動時間的原因,它們還沒有使用嵌入式容器或反射掃描。 他們驗證通常參與單個用例的一致組件的業務邏輯行為,從邊界的業務方法一直到所有涉及的組件。 與外部系統(如數據庫)的集成已被嘲笑。
在不使用更先進的技術自動建立組件連接的情況下構建此類方案聽起來很費力。 但是,我們定義了可重用的測試組件或test double ,它們通過模擬,接線和測試配置來擴展組件,以最大程度地減少重構變更的整體工作量。 目標是制定單一職責,以將變更的影響限制在測試范圍內的單個或幾個類中。 以可重復使用的方式執行此操作會限制總體所需的工作量,并且在項目規模變大時會得到回報,因為我們每個組件只需支付一次管道費用,這很快就可以攤銷。
為了獲得更好的主意,假設我們正在測試訂購咖啡的用例,其中包括兩個類CoffeeShop和OrderProcessor 。
測試雙重類CoffeeShopTestDouble和OrderProcessorTestDouble或*TD駐留在項目的測試范圍中,而它們擴展了駐留在主要范圍中的CoffeeShop和OrderProcessor組件。 測試雙打可能會設置所需的模擬和連線邏輯,并可能使用與用例相關的模擬或驗證方法來擴展類的公共接口。
下面顯示了CoffeeShop組件的測試double類:
public class CoffeeShopTestDouble extends CoffeeShop { public CoffeeShopTestDouble(OrderProcessorTestDouble orderProcessorTestDouble) { entityManager = mock(EntityManager. class ); orderProcessor = orderProcessorTestDouble; } public void verifyCreateOrder(Order order) { verify(entityManager).merge(order); } public void verifyProcessUnfinishedOrders() { verify(entityManager).createNamedQuery(Order.FIND_UNFINISHED, Order. class ); } public void answerForUnfinishedOrders(List<Order> orders) { // setup entity manager mock behavior } }測試double類可以訪問CoffeeShop基類的字段和構造函數以設置依賴項。 它使用其測試雙重形式的其他組件(例如OrderProcessorTestDouble )來能夠調用用例中包含的其他模擬或驗證方法。
測試雙重類是可重用的組件,在每個項目范圍內編寫一次,并在多個用例測試中使用 :
class CoffeeShopTest { private CoffeeShopTestDouble coffeeShop; private OrderProcessorTestDouble orderProcessor; @BeforeEach void setUp() { orderProcessor = new OrderProcessorTestDouble(); coffeeShop = new CoffeeShopTestDouble(orderProcessor); } @Test void testCreateOrder() { Order order = new Order(); coffeeShop.createOrder(order); coffeeShop.verifyCreateOrder(order); } @Test void testProcessUnfinishedOrders() { List<Order> orders = Arrays.asList(...); coffeeShop.answerForUnfinishedOrders(orders); coffeeShop.processUnfinishedOrders(); coffeeShop.verifyProcessUnfinishedOrders(); orderProcessor.verifyProcessOrders(orders); } }用例測試驗證在入口點(這里為CoffeeShop上調用的單個業務用例的處理。 這些測試變得簡短且易讀,這是因為接線和模擬發生在單個測試雙打中,并且它們還可以利用特定于用例的驗證方法,例如verifyProcessOrders() 。
如您所見,測試雙重擴展了生產范圍類,用于設置模擬和驗證行為的方法。 盡管這似乎是一些設置工作,但如果我們有多個用例可以在整個項目中重用組件,則成本將快速攤銷。 我們的項目增長得越多,這種方法的好處就越大,尤其是當我們查看測試執行時間時。 我們所有的測試用例仍然使用JUnit運行,它可以立即執行數百個測試用例。
這是這種方法的主要優點:用例測試的運行速度與普通單元測試一樣快,但由于僅需對單個或幾個組件進行更改,因此可以方便地重構生產代碼。 此外,使用針對我們領域的富有表現力的設置和驗證方法來增強測試效率,從而使我們的測試代碼更具可讀性,便于使用,并避免了測試案例中的樣板代碼。
不包含任何高級測試上下文運行程序的代碼級測試可以非常快速地執行,并且即使在非常復雜的項目中也不會為整體構建增加太多時間。 該系列的下一部分將顯示代碼級以及系統級集成測試。
翻譯自: https://www.javacodegeeks.com/2019/09/efficient-enterprise-testing-unit-use-case.html
總結
以上是生活随笔為你收集整理的高效的企业测试-单元和用例测试(2/6)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux命令删除文件夹(linux 命
- 下一篇: 入侵检测包括(入侵检测包括ddos)