Scala 为什么Specs2以随机顺序运行这些“顺序”测试?
有一个旧的数据库测试套件,我正试图从规范迁移到它。然而,Specs2以一种奇怪的顺序运行测试(在我看来),这会破坏测试,因为它们会更改数据库状态,并运行某些代码两次 下面是测试的简化版本。据我所知,测试应该按以下顺序运行:(因为我指定了顺序):Scala 为什么Specs2以随机顺序运行这些“顺序”测试?,scala,integration-testing,specs2,playframework-2.1,Scala,Integration Testing,Specs2,Playframework 2.1,有一个旧的数据库测试套件,我正试图从规范迁移到它。然而,Specs2以一种奇怪的顺序运行测试(在我看来),这会破坏测试,因为它们会更改数据库状态,并运行某些代码两次 下面是测试的简化版本。据我所知,测试应该按以下顺序运行:(因为我指定了顺序): !222,!333,!444 然而,实际发生的是,它们是按以下顺序执行的: !333,!222,!444 以下是测试: object IncludedSpec extends Specification { sequential println(
!222
,!333
,!444
然而,实际发生的是,它们是按以下顺序执行的:
!333
,!222
,!444
以下是测试:
object IncludedSpec extends Specification {
sequential
println("sssstart")
"IncludedSpec" should {
println("..222")
"context free block" >> {
println("....! 222 the first test")
1 === 1
}
var variableN = 0
"block with context" >> {
println("....333")
"using one variable" >> {
println("......! 333 doing some tests and setting variableN")
variableN = 123
}
println("....444")
"using it again" >> {
println("......! 444 testing variableN")
variableN === 123
}
println("....555")
}
}
println("eeeend")
}
以下是所有println
输出:
sssstart
eeeend
sssstart
eeeend
..222
....333
......! 333 doing some tests and setting variableN
....444
....555
....! 222 the first test
......! 444 testing variableN
还有我的两个问题:
!222
先执行吗ssssstart eeend
如何可能输出两次?等级库是一个对象,不会创建两次吗ok
替换测试体-测试将以正确的顺序运行
版本详细信息:我正在使用Paly Framework 2.1-SNAPSHOT(2012年10月28日的203df0e版本)和Scala 2.10.0-RC1运行这些测试。我认为与Play捆绑在一起的Specs2版本是1.12版,因为inline
方法是可用的,并且它是在1.12(-SNAPSHOT)中添加的,请参阅,没有更高的Specs2版本
(哦,如果你认为我应该完全重写测试,那就看看这个问题:)(更新:这并不适用于我真正的相当大的规格。它仍然按看似随机的顺序执行,SPECs2似乎开始在中间某个地方。-但是,当我用下面的10个或20个例子做了一个小规格的替换时,它确实导致了规范执行的正确顺序。奇怪)
这里有一个局部解决方法,但不是真正的答案:
在测试片段之前,在中使用,而不是>
。然后按照正确的顺序执行测试。(但是ssstart eeend
仍然会发生两次。)
因此,这是预期的:(我在
中用替换了某些
)
我的困惑如下:
一,
我认为
中的和>
之间的区别在于:
中的只能出现在测试片段之前(即,{…x必须\==y…}
块)。但是
>
既可以出现在整个示例(带有嵌套测试片段)之前,也可以出现在测试片段之前
因此,当我在编写>
时,Specs2并不直接知道会发生什么。但我不知道为什么这会改变测试执行顺序。除非Specs2需要…在{…}
块中执行一些代码来找出答案?但是Specs2不使用反射吗?这感觉很奇怪
二,
如果测试完全没有副作用(在这种情况下,更新no sharedvar
s)。或者,如果所有测试都有副作用。那么,据我所知,它们是按照正确的顺序执行的。但是,如果有些测试没有副作用,除了读取共享的var
,那么它们似乎是在写入var
的测试之后执行的(如果使用>
而不是中的)这也让人觉得很奇怪。无论如何,我想很快我就会开始将我的测试移植到Specs2,并将>
替换为中的:-)最初,在Specs2中,您可以创建以下内容:
1-在{1 must.==1}
中带有的示例:“这是一个示例”
2-带有>
的示例:“这是一个示例”>{1 must==1}
3-带有>>
"this system should" >> {
"do something" >> ok
"do something else" >> ok
}
重要的是,
中的仅用于示例,并接受任何可以转换为结果的内容。另一方面,>
可用于示例和示例组(具有统一的嵌套样式),因此它接受类型为Example
或Result
的值
现在,当您想执行以下操作时,事情开始变得有点复杂:
1-使用foreach
创建一组示例
"this group has 5 examples" in {
(1 to 5) foreach { i => "example "+i >> ok }
}
2-使用foreach
创建一组期望值
"this example has 5 expectations" in {
(1 to 5) foreach { i => i must_== i }
}
问题是,这两个带有foreach
的表达式都具有类型Unit
。但是他们在做两件完全不同的事情!第一个是构建示例,因此需要立即计算此表达式以构建规范
。第二个是创建示例的主体,稍后将执行(或者如果示例被过滤掉,则可能永远不会执行)。有两件事,同一个操作符不能工作
因此决定>>(block:=>Unit)
表示“这通过副作用构建了一组示例”,而in(expectations:=>Unit)
表示“这构建了一个示例的主体
可能具有副作用的预期
现在,当这更好地解释了为什么打印语句会出现奇怪的顺序时:
..222
....333
......! 333 doing some tests and setting variableN
....444
....555
首先打印,因为它们包含在类型为Unit
的块中,被解释为一组示例
以及:
因为它们是在类型为MatchResult[\u]
的块中打印的,也就是说,它们被视为示例的主体
我同意这是令人困惑的,我希望这一解释能从某种角度解释为什么事情是这样的。当然,另一个教训是“副作用是偷偷的,因为它们不会告诉你它们到底在做什么”
因此,一般的specs2技巧是始终以适当的值结束块(除非使用foreach
构造,如我的示例abo所示)
..222
....333
......! 333 doing some tests and setting variableN
....444
....555
....! 222 the first test
......! 444 testing variableN