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