跳到主要內容

發表文章

目前顯示的是 3月, 2018的文章

[TDD之路] 隔離的單元測試

寫程式常常會有很多難以隔離的邏輯,這邊舉一個關於時間的例子。 如果要你寫一個判斷是不是聖誕節的簡單程式你會怎麼寫? public bool IsTodayXmas() { var today = DateTime.Today; if (today.Month == 12 && today.Day == 16) { return true; } else { return false; } } . 上面的邏輯正確且簡單,唯一的缺點是不好測試。為什麼呢? 試著寫一段 Unit Test 看看,你可能會像下面這樣寫 [TestMethod] public void TodayIsXmas() { var checker = new XmasChecker(); var result = checker.IsTodayXmas(); Assert.AreEqual(true, result); } . 這個測試這樣寫的話,只有在聖誕節當天才會 Pass. 所以困難的地方在於怎麼把變動的邏輯給隔離開來。 下面提供幾個作法,在不影響已發佈的使用下來讓程式可以測次,各有優缺點 首先都是先將 DateTime.Today; 這個邏輯提取方法 GetToday(),然後 透過新的建構子 透過新的屬性 透過新的方法 使用繼承,變更 GetToday() 的存取範圍為 Protected virtual 大概是這幾種方法,前三種作法都差不多,GetToday() 邏輯如下 private DateTime? _today = null; private DateTime GetToday() { return _today ?? Dat

[TDD之路] 與資源檔案相依時導致 CI 測試失敗

CI 上跑測試專案的指令如下 "MSTest.exe /testcontainer:.\bin\Debug\TargetTests.dll /resultsfile:TestResults.trx" 在本機測試都 all pass, 但是在 CI 上面卻失敗。主要原因是測試的物件中有一個跟Bitmap有關的 Image 找不到圖檔導致錯誤。 程式碼如下: public static string ImagePath = Directory.GetCurrentDirectory() + "\\img\\"; public static Image ClockRed = new Bitmap(ImagePath + "Clockred.png"); 看起來ImagePath就是取得當前位置,然後從當前位置的 img 資料夾中找出 Clockred.png 來產生 Bipmap 物件存到 Image裡面。 local 建置與測試一切正常。但執行了 CI 就吐錯誤。 為什麼呢? 主要原因是雖然已經有將 img\Clockred.png copy 到 output 資料夾(bin\debug),但是實際上MSTest.exe執行的目錄卻是在 .\bin\Debug\TestResults\kyo_TI02BT43 2018-03-07 23_46_45\Out 的資料夾。且裡面是沒有 img\Clockred.png 的。 為了解決這個問題,我嘗試了很多取得當前目錄的方法。但問題不在取得目錄,其實目錄是對的,錯的是檔案並不存在。因次找到了一個 deploy 資源檔案到 deploy out 目錄的方法。 就是 DeploymentItem 這個 attribute, 用法可以寫在 [TestClass] 下方 或是 [TestMethod] 下方。 [TestClass] [DeploymentItem(@"img\Clockgraypanel.png", "img")] 就這樣我的測試就可以在 CI 伺服器上跑過了。