[scala斷言專欄]--選擇專案的測試樣式
英文原文:
ScalaTest支援不同風格的測試,每種測試都旨在滿足特定的需求。為了幫助您找到適合您專案的最佳樣式,本頁將介紹每個選項的預期用例。
我們建議您為每個專案選擇一組測試樣式,然後鼓勵在專案上工作的所有人使用所選擇的樣式。這允許測試樣式適合團隊,同時保持專案程式碼庫的一致性。我們建議您選擇一種主要樣式進行單元測試,另一種用於驗收測試。使用不同的樣式進行單元和驗收測試可以幫助開發人員在低階單元測試與高階驗收測試之間進行“切換”。您也可以選擇在特殊情況下使用的特定樣式,例如 PropSpec
用於測試矩陣。我們通常編寫整合測試 - 涉及子系統(例如資料庫)的測試 - 與單元測試相同的風格。
簡而言之,ScalaTest的靈活性並不是為了使個別開發人員能夠在同一個專案中使用不同的測試樣式。相反,它旨在使專案負責人為團隊選擇最適合的風格或風格。如果您在執行所選樣式時遇到問題,可以在構建中
你所選擇的風格只會指示你的測試的宣告。ScalaTest-assertions,matchers ,mixin traits 等中的其他一切 - 無論您選擇什麼樣式,工作始終如一。
如果你不喜歡購物
如果您寧願被告知採用哪種方法,而不是選擇一種方法,我們建議您使用 FlatSpec
單元和整合測試以及 FeatureSpec
驗收測試。我們建議FlatSpec
作為預設選擇,因為它是平面(不需要的)像大多數開發人員熟悉的XUnit測試,但是會引導您使用描述性的規範樣式名稱編寫集中的測試。
風格特質用例
如果您寧願做出自己的選擇,該表格可以快速概述每種風格特徵的優缺點。有關更多資訊和示例,請單擊連結:
樣式舉例和描述 |
---|
FunSuite(個人非常推薦使用)For teams coming from xUnit,
and generates specification-like output that can facilitate communication among stakeholders. 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
}
}
}
|
FlatSpecA good first step for teams wishing to move from xUnit to BDD, so simple and familiar, but the test names must be written in a specification style: "X should Y," "A must B," etc. import org.scalatest.FlatSpec
class SetSpec extends FlatSpec {
"An empty Set" should "have size 0" in {
assert(Set.empty.size == 0)
}
it should "produce NoSuchElementException when head is invoked" in {
assertThrows[NoSuchElementException] {
Set.empty.head
}
}
}
|
FunSpecFor teams coming from Ruby's RSpec tool,
provides an excellent general-purpose choice for writing specification-style tests. import org.scalatest.FunSpec
class SetSpec extends FunSpec {
describe("A Set") {
describe("when empty") {
it("should have size 0") {
assert(Set.empty.size == 0)
}
it("should produce NoSuchElementException when head is invoked") {
assertThrows[NoSuchElementException] {
Set.empty.head
}
}
}
}
}
|
WordSpecFor teams coming from specs or specs2,
specification text. 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
}
}
}
}
}
|
FreeSpecBecause it gives absolute freedom (and no guidance) on how specification text should be written,
import org.scalatest.FreeSpec
class SetSpec extends FreeSpec {
"A Set" - {
"when empty" - {
"should have size 0" in {
assert(Set.empty.size == 0)
}
"should produce NoSuchElementException when head is invoked" in {
assertThrows[NoSuchElementException] {
Set.empty.head
}
}
}
}
}
|
PropSpecPropSpec is perfect for teams that want to write tests exclusively in terms of property checks; also a good choice for writing the occasional test matrix when a different style trait is chosen as the main unit testing style. import org.scalatest._
import prop._
import scala.collection.immutable._
class SetSpec extends PropSpec with TableDrivenPropertyChecks with Matchers {
val examples =
Table(
"set",
BitSet.empty,
HashSet.empty[Int],
TreeSet.empty[Int]
)
property("an empty Set should have size 0") {
forAll(examples) { set =>
set.size should be (0)
}
}
property("invoking head on an empty set should produce NoSuchElementException") {
forAll(examples) { set =>
a [NoSuchElementException] should be thrownBy { set.head }
}
}
}
|
FeatureSpecTrait alongside non-programmers to define the acceptance requirements. import org.scalatest._
class TVSet {
private var on: Boolean = false
def isOn: Boolean = on
def pressPowerButton() {
on = !on
}
}
class TVSetSpec extends FeatureSpec with GivenWhenThen {
info("As a TV set owner")
info("I want to be able to turn the TV on and off")
info("So I can watch TV when I want")
info("And save energy when I'm not watching TV")
feature("TV power button") {
scenario("User presses power button when TV is off") {
Given("a TV set that is switched off")
val tv = new TVSet
assert(!tv.isOn)
When("the power button is pressed")
tv.pressPowerButton()
Then("the TV should switch on")
assert(tv.isOn)
}
scenario("User presses power button when TV is on") {
Given("a TV set that is switched on")
val tv = new TVSet
tv.pressPowerButton()
assert(tv.isOn)
When("the power button is pressed")
tv.pressPowerButton()
Then("the TV should switch off")
assert(!tv.isOn)
}
}
}
|
RefSpec (JVM only)
Fewer function literals translates into faster compile times and fewer generated class files, which can help minimize build times. As a result, using generating large numbers of tests programatically via static code generators. import org.scalatest.refspec.RefSpec
class SetSpec extends RefSpec {
object `A Set` {
object `when empty` {
def `should have size 0` {
assert(Set.empty.size == 0)
}
def `should produce NoSuchElementException when head is invoked` {
assertThrows[NoSuchElementException] {
Set.empty.head
}
}
}
}
}
Note: The " this class is not available on Scala.js. |