[Test] public void Can_Add_Integer() { int total = Calculator.Add(1, 2); Assert.AreEqual(3, total); }上面的Assertion閱讀起來不難懂,可以理解是在測試total與3是否相等。然而對開發人員在撰寫程式碼時卻有個小問題,Assert.AreEqual(3, total)和Assert.AreEqual(total, 3)意義相同嗎?看一下NUnit提供的說明可以知道第一個參數要代入的是預期該得到的數值,而第二個參數是實際運算完後的數值。
當assertion永遠成功時,Assert.AreEqual(3, total)和Assert.AreEqual(total, 3)看起來沒什麼差別。但在assertion失敗時,意義上就不一樣了,因為NUnit提供的失敗訊息會有很大差別。如
Assert.AreEqual(3, total)
Assert.AreEqual(total, 3)
以上是NUnit提供的Classic Assert Model。事實上NUnit還有提供另一種assertion方式稱為Constraint Model,如
[Test] public void Can_Add_Integer_Using_Constraints() { int total = Calculator.Add(1, 2); Assert.That(total, Is.EqualTo(3)); }用以上方式撰寫assertion程式碼在閱讀上易讀許多。
雖然Constraint Model已提供可讀性不錯的撰寫方式,但每次要使用時還是得先Assert.That,而且有時NUnit提供的除錯訊息不是那麼清楚。基於以上因素,便出現Fluent Assertions這套函式庫來強化NUnit(或其它framework)在assertion上的不足。
將上述的assertion改以Fluent Assertions重新撰寫可以得到更簡潔的assertion
[Test] public void Can_Add_Integer_Using_FluentAssertions() { int total = Calculator.Add(1, 2); total.Should().Be(3); }寫成一行閱讀起來也很清楚,就如同說話一般
[Test] public void Can_Add_Integer_Using_FluentAssertions() { Calculator.Add(1, 2).Should().Be(3); }有時我們需要驗證功能是否有正確拋出例外,也可以Fluent Assertions來撰寫如
[Test] public void Cannot_Subtract_And_Throw_NotSupportedException() { Action action = () => Calculator.Subtract(5, 3); action.ShouldThrow<NotSupportedException>().WithMessage("Not yet implemented"); }Fluent Assertions提供的assertion很豐富也簡潔易懂,目前我所在團隊已將原本NUnit的assertion全部換成使用Fluent Assertions,效果還不錯,在撰寫assertion程式碼時速度快了許多也沒遇到太大的問題。
No comments:
Post a Comment