轉載請註明原創出處,謝謝!
距離上一次發博客差不多有一年了。2018 年 10 月 至 2019 年 8 月,這一段時間待在上海負責公司的一個項目,整個人就忙了起來,在堅持寫了兩個月之後就覺得沒那麼多精力再去做其他事情了,於是就把寫博客這件事情擱了下來。中途有好幾次都是想寫但最終都沒有下定決心,然後就一直耽擱下來。回到成都後,事情沒那麼多了,是時候做一些筆記了。
其實呢,看這篇文檔是因爲工作上遇到的一個問題:Scala 單元測試如何優雅的去 assert 一個方法拋出指定異常呢?
對於 Java 來說,很簡單:
@Test(expected = YourExpectedException.class)
public void test_method() {
// method body
}
而在 Scala 裏面沒法這樣寫。在看這個文檔之前,我想到的辦法是這樣子的:
try {
// method body
} catch {
case e: Throwable =>
assert(e.isInstanceOf[YourExpectedException])
assert(e.getMessage == "your expected message")
}
通過 try ... catch
的方式實現,寫完了之後一看,寫起來很麻煩,另外有點地方不對勁:如果方法不拋異常測試也一樣能過,所以就去問了一下同事有什麼方式可以做到這件事情,同事發了我一個鏈接:http://www.scalatest.org/user_guide/using_matchers
。讀完之後發現了以下幾種方式都可以做到:
an [YourExpectedException] should be thrownBy { // Ensure a particular exception type is thrown
// method body
}
val caught = the [YourExpectedException] thrownBy { // Capturing an expected exception in a variable
// method body
}
the [YourExpectedException] thrownBy { // Inspecting an expected exception
// method body
} should have message ("your expected message")
看了上面幾種方式,瞬間覺得舒服多了,寫測試就像寫一句話一樣,讀起來非常流暢,也很明朗,極力推薦!!!
在優化了代碼之後,這篇文檔也就被我收藏了起來。why?因爲這個文檔寫的很好,簡潔易懂,並且都帶有詳細的舉例說明,是我的菜(_),沒過多久我就把它看完了,現在就分享給大家。
ScalaTest 是一位名叫 Bill Venners 開發出來的 Scala 測試框架。主要目的是爲了提高程序員的生產力。那麼,它有哪些特點呢?
1、提出了 suite 的概念
suite:0 ~ n 個測試的集合。
2、支持多種測試樣式
例如:FunSuite(BDD)樣式:
import org.scalatest.FunSuite
class SetSuite extends FunSuite {
test("An empty Set should have size 0") {
assert(Set.empty.size == 0)
}
test("Invoking head on an empty Set should produce NoSuchElementException") {
assertThrows[NoSuchElementException] {
Set.empty.head
}
}
}
WordSpec(specs or specs2)樣式:
import org.scalatest.WordSpec
class SetSpec extends WordSpec {
"A Set" when {
"empty" should {
"have size 0" in {
assert(Set.empty.size == 0)
}
"produce NoSuchElementException when head is invoked" in {
assertThrows[NoSuchElementException] {
Set.empty.head
}
}
}
}
}
…
還有驗收測試樣式等等,這裏就不一一例舉了,可以點擊這裏查看 ScalaTest 支持的所有樣式。
ScalaTest 提供這些樣式並不是爲了讓用戶每一種樣式都用,而是建議團隊爲單元測試選擇一種主要樣式,驗收測試選擇一種主要樣式,不推薦混合使用。大家可以根據自己的團隊選擇合適的風格,最適合的纔是最好的。
3、集成了主流單元測試 mock 框架
例如 EasyMock、JMock、Mockito 等 Java 主流 mock 框架。併爲這些框架提供了足夠多的語法糖。例如只要引入了 trait:MockitoSugar 之後,mock 一個類就可以這樣寫: val mockedClass = mock[YourClass]
,非常便捷。
4、語言本身提供了各種各樣的語法糖,方便編寫測試
sevenDotOh should equal (6.9 +- 0.2)
sevenDotOh should === (6.9 +- 0.2)
sevenDotOh should be (6.9 +- 0.2)
sevenDotOh shouldEqual 6.9 +- 0.2
sevenDotOh shouldBe 6.9 +- 0.2
上面代碼中出現的 should
, equal
, +-
, be
, shouldEqual
, shouldBe
就是 ScalaTest
提供的語法糖的一部分。
5、還有一些特性,不過平時一般用的比較少,如:異步測試、給測試方法打標籤 (tag)、自定義 Match 類等…
從上面的這些特點來看,可以用兩個字來形容 ScalaTest:靈活。
不同的樣式、集成主流單元測試框架,各種各樣的語法糖,使得編寫 Scala Test 非常簡單;一句話的風格讀起來也很順暢,而且淺顯易懂。
文章提到的一個理念也很有道理,在日常開發的過程中應該要時刻遵守:測試代碼應該要 簡潔、明顯,快速易懂
,使得團隊中的不同開發人員能夠通過查看彼此的測試代碼就能快速知道代碼在幹什麼。
最後引用一句原文的話概括一下:
The upshot is that ScalaTest is designed to facilitate productivity of teams by being:
easy to get into
easy to read, even by casual users
easy to remember how to write
easy to customize to address special needs
PS: 自我感覺新 Get 到了很多東西,不過學到了和用文字表達出來感覺有不是那麼一回事兒,就跟做筆記一樣,學到的肯定比寫下來的多。看來,表達能力還有待提高呀,革命尚未成功,同志仍需努力!加油!!!
參考資料:
(1)ScalaTest