Reputation: 499
Is it somehow possible to inline statement from closure or method into an assertion so it can be printed when the assertion fails?
If we have simple statement like assert 10 == (20 - 11)
then Groovy's power assert prints it nicely like:
assert 10 == (20 - 11)
| |
false 9
However if we extract the statement into a closure like:
def c = { arg -> arg == (20 - 11) }
assert c(10)
then the output will be much less informative:
assert c(10)
|
false
I'm developing custom specific test framework and the use case is to have custom assertions represented as boolean closures or methods and run the assertion from one place.
Upvotes: 2
Views: 1219
Reputation: 21379
You were getting such output becuase, closure
is returning boolean and assert
does look for true
.
Approach #1 : If you want change the ouput, then may be you can pass the two arguments to closure
instead of one argument as shown below. Of course, you may not want to compare equality with static number in your framework, so the second argument make sense.
def c = { arg1, arg2 -> arg1 == arg2 }
assert c(10, 20-11), 'comparison failed'
Output:
java.lang.AssertionError: Comparison failed. Expression: c.call(10, (20 - 11)) at Script1.run(Script1.groovy:2)
Approach #2: Here changed closure name appropriately, and doing the assertion inside itself. Since its name is assertEqual
, it may unlikely misused for other assertions such as >
, <
.
def assertEqual = { arg1, arg2 -> assert arg1 == arg2, "Comparison failed: ${arg1} vs ${arg2}" }
assertEqual(10, 20-11)
Output:
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)
You write more closures in this manner, such as assertGreaterThan
assertLessThan
for specific operations.
Approach #3: Here you can even pass what should be the error message to the closure.
def assertEqual = { arg1, arg2, message -> assert arg1 == arg2, message(arg1, arg2) }
assertEqual(10, 20-11) {op1, op2 -> "$op1 is not equal to $op2"}
Output:
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)
Approach #4 Another variant where user can pass operation
, and message. You may not only do equal
, but also other operations as well. So, changing the closure
name to 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" }
Output:
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)
If you want to go with simple approach and just use equal
assert, then Approach #2 is right one. Of course, you are the better one to choose which one suits better for your need.
Upvotes: 1