英文原文:
http://www.scalatest.org/user_guide/selecting_a_style
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. |