我正在尝试在单个Spock方法的上下文中验证两个不同的输出,该方法运行when-then-where
形式的多个测试用例。出于这个原因,我在then
块使用了两个断言,如以下示例所示:
import spock.lang.*
@Unroll
class ExampleSpec extends Specification {
def "Authentication test with empty credentials"() {
when:
def reportedErrorMessage, reportedErrorCode
(reportedErrorMessage, reportedErrorCode) = userAuthentication(name, password)
then:
reportedErrorMessage == expectedErrorMessage
reportedErrorCode == expectedErrorCode
where:
name | password || expectedErrorMessage | expectedErrorCode
' ' | null || 'Empty credentials!' | 10003
' ' | ' ' || 'Empty credentials!' | 10003
}
}
代码是一个示例,其中设计要求是name
和password
是' '
或null
,那么我应该始终期望完全相同{{1 }和expectedErrorMessage = 'Empty credentials!'
。如果由于某种原因(可能是因为源代码中存在错误),我会expectedErrorCode = 10003
(或除expectedErrorMessage = Empty!
之外的任何其他内容)和'Empty credentials!'
(或expectedErrorCode = 10001
以外的任何其他内容),这不符合上述要求。
问题是如果两个断言在同一个测试中失败,我只会为第一个断言(此处为1003
)收到失败消息。是否有可能在同一测试中获知所有失败的断言?
这是一段代码,它演示了没有其他外部代码依赖性的相同问题。我理解在这种特殊情况下,将两个非常不同的测试捆绑在一起并不是一个好习惯,但我认为它仍然证明了这个问题。
reportedErrorMessage
答案 0 :(得分:1)
我认为这里有两件不同的事情。
assert
失败将引发错误,这将停止执行代码。这就是为什么在单个测试中不能有两个失败的断言。 Spock中expect
或then
块中的任何代码行都有一个隐含的assert
。鉴于这些信息,这是您的第二个示例代码,将测试分开,第二个测试中的失败方案。
@Unroll
class ExampleSpec extends Specification {
def "minimum of #a and #b is #c and maximum of #a and #b is #d - successes"() {
expect:
Math.min(a, b) == c
Math.max(a, b) == d
where:
a | b || c | d
3 | 7 || 3 | 7
9 | 9 || 9 | 9
}
def "minimum of #a and #b is #c and maximum of #a and #b is #d - failures"() {
expect:
Math.min(a, b) != c
Math.max(a, b) != d
where:
a | b || c | d
5 | 4 || 5 | 4
}
}
至于你对MongoDB测试用例的评论 - 我不确定它的意图是什么,但我猜他们正在制作几个全部通过的断言,而不是验证某些东西是否失败。
答案 1 :(得分:1)
基于OP的latest comment,看起来与我之前的答案不同的解决方案会有所帮助。我将原来的答案保留在原地,因为我觉得它仍然提供了与问题相关的有用信息(特别是将正面和负面测试分开)。
鉴于你想要查看所有失败,并且不是在第一个失败的断言失败,我建议将所有内容连接成一个布尔AND操作。不使用&&
快捷方式运算符,因为它只会运行到第一次检查不满足整个操作。我建议使用&
,以便进行所有检查,无论以前是否有任何检查失败。
鉴于上面的max
和min
示例,我会将expect
块更改为:
Math.min(a, b) == c & Math.max(a, b) == d
发生故障时,它会提供以下信息:
Math.min(a, b) == c & Math.max(a, b) == d
| | | | | | | | | | |
4 5 4 | 5 false 5 5 4 | 4
false false
这将显示失败断言的每个部分。相比之下,如果您使用&&
,它只会显示第一个失败,如下所示:
Math.min(a, b) == c && Math.max(a, b) == d
| | | | | |
4 5 4 | 5 false
false
如果你在一条线路上进行两次以上的检查,这显然会很快变得混乱 - 但这是你可以在一条线路上的所有失败信息之间进行权衡,而不是在修复每个人之后重新运行测试成分
希望这有帮助!