如何从 Groovy 中断言的方法或闭包打印语句

How to print statement from asserted method or closure in Groovy

是否可以通过某种方式将闭包或方法中的语句内联到断言中,以便在断言失败时打印出来?

如果我们有像 assert 10 == (20 - 11) 这样的简单语句,那么 Groovy 的 power assert 会很好地打印它:

assert 10 == (20 - 11)
          |      |
          false  9

但是,如果我们将语句提取到闭包中,例如:

def c = { arg -> arg == (20 - 11) }
assert c(10)

那么输出的信息量会少得多:

assert c(10)
       |
       false

我正在开发自定义特定测试框架,用例是将自定义断言表示为布尔闭包或方法,运行 来自一个地方的断言。

你得到这样的输出是因为 closure 正在返回布尔值并且 assert 确实在寻找 true.

方法#1:如果你想改变输出,那么你可以将两个参数传递给 closure 而不是一个参数,如下所示。当然,您可能不想在框架中将相等与静态数字进行比较,因此第二个参数有意义。

def c = { arg1, arg2 -> arg1 == arg2 }  
assert c(10, 20-11), 'comparison failed'

输出:

java.lang.AssertionError: Comparison failed. Expression: c.call(10, (20 - 11)) at Script1.run(Script1.groovy:2)

方法#2:此处适当更改了闭包名称,并在其内部进行断言。由于它的名字是 assertEqual,它不太可能被误用于其他断言,例如 ><

def assertEqual = { arg1, arg2 -> assert arg1 == arg2, "Comparison failed: ${arg1} vs ${arg2}" }  
assertEqual(10, 20-11)

输出:

java.lang.AssertionError: Comparison failed: 10 vs 9. Expression: (arg1 == arg2). Values: arg1 = 10, arg2 = 9
at Script1$_run_closure1.doCall(Script1.groovy:1)
at Script1.run(Script1.groovy:2)

你这样写更多的闭包,比如assertGreaterThanassertLessThan针对具体的操作

方法#3:在这里您甚至可以将错误消息传递给闭包。

def assertEqual = { arg1, arg2, message -> assert arg1 == arg2, message(arg1, arg2) }
assertEqual(10, 20-11) {op1, op2 -> "$op1 is not equal to $op2"}

输出:

java.lang.AssertionError: 10 is not equal to 9. Expression: (arg1 == arg2). Values: arg1 = 10, arg2 = 9
at Script1$_run_closure1.doCall(Script1.groovy:1)
at Script1.run(Script1.groovy:2)

方法 #4 用户可以传递 operation 和消息的另一种变体。您不仅可以执行 equal,还可以执行其他操作。因此,将 closure 名称更改为 myAssert

def myAssert = { arg1, arg2, expression -> expression(arg1, arg2) }
//Greater than
myAssert(10, 20-11) {op1, op2 -> assert op1 > op2, "$op1 is not greater than $op2" }
//Less than
myAssert(10, 20-11) {op1, op2 -> assert op1 < op2, "$op1 is not less than $op2" }
//Equal
myAssert(10, 20-11) {op1, op2 -> assert op1 == op2, "$op1 is not equal to $op2" }

输出:

java.lang.AssertionError: 10 is not less than 9. Expression: (op1 < op2). Values: op1 = 10, op2 = 9
at Script1$_run_closure2.doCall(Script1.groovy:2)
at Script1$_run_closure1.doCall(Script1.groovy:1)
at Script1.run(Script1.groovy:2)

如果您想采用简单的方法并只使用 equal 断言,那么 方法 #2 是正确的方法。当然,你是更好的人,选择更适合你的需要。