自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

變異測(cè)試:基于故障的試驗(yàn)

開發(fā) 測(cè)試
基于 .NET 的 xUnit.net 測(cè)試框架,開發(fā)一款自動(dòng)貓門的邏輯,讓門在白天開放,夜間鎖定。

[[280217]]

基于 .NET 的 xUnit.net 測(cè)試框架,開發(fā)一款自動(dòng)貓門的邏輯,讓門在白天開放,夜間鎖定。

在本系列的第一篇文章中,我演示了如何使用設(shè)計(jì)的故障來確保代碼中的預(yù)期結(jié)果。在第二篇文章中,我將繼續(xù)開發(fā)示例項(xiàng)目:一款自動(dòng)貓門,該門在白天開放,夜間鎖定。

在此提醒一下,你可以按照此處的說明使用 .NET 的 xUnit.net 測(cè)試框架。

關(guān)于白天時(shí)間

回想一下,測(cè)試驅(qū)動(dòng)開發(fā)(TDD)圍繞著大量的單元測(cè)試。

第一篇文章中實(shí)現(xiàn)了滿足 Given7pmReturnNighttime 單元測(cè)試期望的邏輯。但還沒有完,現(xiàn)在,你需要描述當(dāng)前時(shí)間大于 7 點(diǎn)時(shí)期望發(fā)生的結(jié)果。這是新的單元測(cè)試,稱為 Given7amReturnDaylight

  1. [Fact]
  2. public void Given7amReturnDaylight()
  3. {
  4. var expected = "Daylight";
  5. var actual = dayOrNightUtility.GetDayOrNight();
  6. Assert.Equal(expected, actual);
  7. }

現(xiàn)在,新的單元測(cè)試失敗了(越早失敗越好?。?/p>

  1. Starting test execution, please wait...
  2. [Xunit.net 00:00:01.23] unittest.UnitTest1.Given7amReturnDaylight [FAIL]
  3. Failed unittest.UnitTest1.Given7amReturnDaylight
  4. [...]

期望接收到字符串值是 Daylight,但實(shí)際接收到的值是 Nighttime。

分析失敗的測(cè)試用例

經(jīng)過仔細(xì)檢查,代碼本身似乎已經(jīng)出現(xiàn)問題。 事實(shí)證明,GetDayOrNight 方法的實(shí)現(xiàn)是不可測(cè)試的!

看看我們面臨的核心挑戰(zhàn):

  1. GetDayOrNight 依賴隱藏輸入。

    dayOrNight 的值取決于隱藏輸入(它從內(nèi)置系統(tǒng)時(shí)鐘中獲取一天的時(shí)間值)。

  2. GetDayOrNight 包含非確定性行為。

    從系統(tǒng)時(shí)鐘中獲取到的時(shí)間值是不確定的。(因?yàn)椋┰摃r(shí)間取決于你運(yùn)行代碼的時(shí)間點(diǎn),而這一點(diǎn)我們認(rèn)為這是不可預(yù)測(cè)的。

  3. GetDayOrNight API 的質(zhì)量差。

    該 API 與具體的數(shù)據(jù)源(系統(tǒng) DateTime)緊密耦合。

  4. GetDayOrNight 違反了單一責(zé)任原則。

    該方法實(shí)現(xiàn)同時(shí)使用和處理信息。優(yōu)良作法是一種方法應(yīng)負(fù)責(zé)執(zhí)行一項(xiàng)職責(zé)。

  5. GetDayOrNight 有多個(gè)更改原因。

    可以想象內(nèi)部時(shí)間源可能會(huì)更改的情況。同樣,很容易想象處理邏輯也將改變。這些變化的不同原因必須相互隔離。

  6. 當(dāng)(我們)嘗試了解 GetDayOrNight 行為時(shí),會(huì)發(fā)現(xiàn)它的 API 簽名不足。

    最理想的做法就是通過簡單的查看 API 的簽名,就能了解 API 預(yù)期的行為類型。

  7. GetDayOrNight 取決于全局共享可變狀態(tài)。

    要不惜一切代價(jià)避免共享的可變狀態(tài)!

  8. 即使在閱讀源代碼之后,也無法預(yù)測(cè) GetDayOrNight 方法的行為。

    這是一個(gè)嚴(yán)重的問題。通過閱讀源代碼,應(yīng)該始終非常清晰,系統(tǒng)一旦開始運(yùn)行,便可以預(yù)測(cè)出其行為。

失敗背后的原則

每當(dāng)你遇到工程問題時(shí),建議使用久經(jīng)考驗(yàn)的分而治之divide and conquer策略。在這種情況下,遵循關(guān)注點(diǎn)分離separation of concerns的原則是一種可行的方法。

關(guān)注點(diǎn)分離(SoC)是一種用于將計(jì)算機(jī)程序分為不同模塊的設(shè)計(jì)原理,以便每個(gè)模塊都可以解決一個(gè)關(guān)注點(diǎn)。關(guān)注點(diǎn)是影響計(jì)算機(jī)程序代碼的一組信息。關(guān)注點(diǎn)可以和要優(yōu)化代碼的硬件的細(xì)節(jié)一樣概括,也可以和要實(shí)例化的類的名稱一樣具體。完美體現(xiàn) SoC 的程序稱為模塊化程序。

出處

GetDayOrNight 方法應(yīng)僅與確定日期和時(shí)間值表示白天還是夜晚有關(guān)。它不應(yīng)該與尋找該值的來源有關(guān)。該問題應(yīng)留給調(diào)用客戶端。

必須將這個(gè)問題留給調(diào)用客戶端,以獲取當(dāng)前時(shí)間。這種方法符合另一個(gè)有價(jià)值的工程原理——控制反轉(zhuǎn)inversion of control。Martin Fowler 在這里詳細(xì)探討了這一概念。

框架的一個(gè)重要特征是用戶定義的用于定制框架的方法通常來自于框架本身,而不是從用戶的應(yīng)用程序代碼調(diào)用來的。該框架通常在協(xié)調(diào)和排序應(yīng)用程序活動(dòng)中扮演主程序的角色。控制權(quán)的這種反轉(zhuǎn)使框架有能力充當(dāng)可擴(kuò)展的框架。用戶提供的方法為框架中的特定應(yīng)用程序量身制定泛化算法。

Ralph Johnson and Brian Foote

重構(gòu)測(cè)試用例

因此,代碼需要重構(gòu)。擺脫對(duì)內(nèi)部時(shí)鐘的依賴(DateTime 系統(tǒng)實(shí)用程序):

  1. DateTime time = new DateTime();

刪除上述代碼(在你的文件中應(yīng)該是第 7 行)。通過將輸入?yún)?shù) DateTime 時(shí)間添加到 GetDayOrNight 方法,進(jìn)一步重構(gòu)代碼。

這是重構(gòu)的類 DayOrNightUtility.cs

  1. using System;
  2.  
  3. namespace app {
  4. public class DayOrNightUtility {
  5. public string GetDayOrNight(DateTime time) {
  6. string dayOrNight = "Nighttime";
  7. if(time.Hour >= 7 && time.Hour < 19) {
  8. dayOrNight = "Daylight";
  9. }
  10. return dayOrNight;
  11. }
  12. }
  13. }

重構(gòu)代碼需要更改單元測(cè)試。 需要準(zhǔn)備 nightHourdayHour 的測(cè)試數(shù)據(jù),并將這些值傳到GetDayOrNight 方法中。 以下是重構(gòu)的單元測(cè)試:

  1. using System;
  2. using Xunit;
  3. using app;
  4.  
  5. namespace unittest
  6. {
  7. public class UnitTest1
  8. {
  9. DayOrNightUtility dayOrNightUtility = new DayOrNightUtility();
  10. DateTime nightHour = new DateTime(2019, 08, 03, 19, 00, 00);
  11. DateTime dayHour = new DateTime(2019, 08, 03, 07, 00, 00);
  12.  
  13. [Fact]
  14. public void Given7pmReturnNighttime()
  15. {
  16. var expected = "Nighttime";
  17. var actual = dayOrNightUtility.GetDayOrNight(nightHour);
  18. Assert.Equal(expected, actual);
  19. }
  20.  
  21. [Fact]
  22. public void Given7amReturnDaylight()
  23. {
  24. var expected = "Daylight";
  25. var actual = dayOrNightUtility.GetDayOrNight(dayHour);
  26. Assert.Equal(expected, actual);
  27. }
  28.  
  29. }
  30. }

經(jīng)驗(yàn)教訓(xùn)

在繼續(xù)開發(fā)這種簡單的場景之前,請(qǐng)先回顧復(fù)習(xí)一下本次練習(xí)中所學(xué)到的東西。

運(yùn)行無法測(cè)試的代碼,很容易在不經(jīng)意間制造陷阱。從表面上看,這樣的代碼似乎可以正常工作。但是,遵循測(cè)試驅(qū)動(dòng)開發(fā)(TDD)的實(shí)踐(首先描述期望結(jié)果,然后才描述實(shí)現(xiàn)),暴露了代碼中的嚴(yán)重問題。

這表明 TDD 是確保代碼不會(huì)太凌亂的理想方法。TDD 指出了一些問題區(qū)域,例如缺乏單一責(zé)任和存在隱藏輸入。此外,TDD 有助于刪除不確定性代碼,并用行為明確的完全可測(cè)試代碼替換它。

最后,TDD 幫助交付易于閱讀、邏輯易于遵循的代碼。 

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2019-10-21 09:52:51

變異測(cè)試單元測(cè)試

2021-08-26 05:57:42

Web 安全防火墻安全工具

2016-12-05 09:50:17

2011-01-10 13:24:17

2018-08-30 14:58:12

機(jī)器學(xué)習(xí)磁盤故障

2011-08-23 14:02:17

2015-09-22 16:13:50

2011-05-16 14:13:04

模型測(cè)試

2011-07-04 18:12:09

功能測(cè)試故障模型

2010-09-01 10:57:18

vSphere服務(wù)器虛擬化VMware

2010-11-04 13:46:33

GPON網(wǎng)絡(luò)測(cè)試華為

2009-09-15 16:50:54

2016-03-28 16:46:36

城市軌道LTE-M解決華為

2020-11-06 15:05:13

物聯(lián)網(wǎng)預(yù)測(cè)性維護(hù)安全

2010-12-28 20:14:53

2009-02-09 14:04:01

2009-07-07 17:22:34

光纖鏈路測(cè)試故障

2012-11-27 16:41:42

2014-07-07 17:19:38

敏捷網(wǎng)絡(luò)華為

2023-06-25 18:00:00

人工智能ChatGPT網(wǎng)絡(luò)安全
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)