I'm new to groovy and I have doubt. Lets say I have this statement:
assert "king" == "kin"
which will give me the assert failure as
Assertion failed:
assert "king" == "kin"
|
false
and stops the program. But what I want is, store the result (the failure message, if any say in GString) and proceed with the program.
Is that possible to do so?
You can catch the AssertionError exception. Something like this:
try {
assert ["hello"] == ["A"]
}
catch(AssertionError e) {
result = e.getMessage()
}
println result
This should work.
Related
Hi everyone,
I am trying to test C programs that use an user input... Like a learning app. So the avaliator(teacher) can write tests and I compile the code with a help of a docker and get back the result of the program that I send. After that I verify if one of the case tests fails..
for that I have two strings, like this:
result = "input_compiled1540323505983: /home/compiler/input/input.c:9: main: Assertion `B==2' failed. timeout: the monitored command dumped core Aborted "
and an array with case tests that is like:
caseTests = [" assert(A==3); // A must have the value of 3;", " assert(B==2); // B must have the value of 2; ", " assert(strcmp(Fulano, "Fulano")==0); //Fulano must be equal to Fulano]
I need to send back from my server something like this:
{ console: [true, true, true ] }
Where each true is the corresponding test for every test in the array of tests
So, I need to test if one string contains the part of another string... and for now I did like this:
criandoConsole = function(arrayErros, arrayResult){
var consol = arrayErros.map( function( elem ) {
var local = elem.match(/\((.*)\)/);
if(arrayResult.indexOf(local) > -1 ) {
return false;
}
else return true;
});
return consol;
}
I am wondering if there are any more efective way of doing that. I am using a nodejs as server. Does anyone know a better way?!
ps: Just do like result.contains(caseTests[0]) did not work..
I know this is changing the problem, but can you simplify the error array to only include the search terms? For example,
result = "input_compiled1540323505983: /home/compiler/input/input.c:9: main: Assertion `B==2' failed. timeout: the monitored command dumped core Aborted ";
//simplify the search patterns
caseTests = [
"A==3",
"B==2",
"strcmp(Fulano, \"Fulano\")==0"
]
criandoConsole = function(arrayErros, arrayResult){
var consol = arrayErros.map( function( elem ) {
if (arrayResult.indexOf(elem) != -1)
return false; //assert failed?
else
return true; //success?
});
return consol;
}
console.log(criandoConsole(caseTests,result));
I am running test case and asserting data using groovy. I want to print each and every failed message to html junit generate report.
Example Code
import groovy.json.JsonSlurper
def ResponseMessage = messageExchange.response.responseContent
def jsonString = new JsonSlurper().parseText(ResponseMessage)
assert !(jsonString.isEmpty())
assert jsonString.code == 200
assert jsonString.status == "success"
def accountInfo = jsonString.data
assert !(accountInfo.isEmpty())
def inc=0
//CHECKING LANGUAGES IN RESPONSE
if(accountInfo.languages.id!=null)
{
log.info("Language added successfully")
}
else
{
log.info("Language NOT added.") //want to display this in html report
inc++
}
if(accountInfo.educations!=null)
{
log.info("Educations added successfully")
}
else
{
log.info("Educations NOT added.") //want to display this in html report
inc++
}
assert inc<=0,"API unable to return all parameters, Please check logs"
Scenario
What I am doing here is , IF test condition does not match and go to ELSE, I do increment of variable inc by 1. So at the end if fail my test if inc>0.
Report
In junit style html generated report, if test failed it display only one message called API unable to return all parameters, Please check logs
But what I want is to display each IF condition message into HTML report if for any condition goes into ELSE section.
Couple of pointers:
assert stops at first failure and only this failure message is part of junit report.
having said that, user will not know if there are any further verification failures for the current response.
the messages that are part of if..else are not part of junit report
in order to achieve that, need to collect all those messages and finally show the collected error messages.
below solution uses a variable, messages and appends each failure which allows to show them at the end. this way all failures can be shown in the report if that is desirable which OP requested for.
user can also show the messages in the report using below statement apart from assert statement
if (messages) throw new Error(messages.toString())
Script Assertion
import groovy.json.JsonSlurper
//check if the response is empty
assert context.response, 'Response is empty or null'
def jsonString = new JsonSlurper().parseText(context.response)
def messages = new StringBuffer()
jsonString.code == 200 ?: messages.append("Code does not match: actual[${jsonString.code}], expected[200]\n")
jsonString.status == "success" ?: messages.append("Status does not match: actual[${jsonString.status}], expected[success]\n")
def accountInfo = jsonString.data
accountInfo ?: messages.append('AccountInfo is empty or null\n')
def inc=0
//CHECKING LANGUAGES IN RESPONSE
if(accountInfo.languages.id) {
log.info('Language added successfully')
} else {
log.error('Language NOT added.') //want to display this in html report
messages.append('Language not added.\n')
inc++
}
if(accountInfo.educations) {
log.info('Educations added successfully')
} else {
log.error('Educations NOT added.') //want to display this in html report
messages.append('Educations NOT added.\n')
inc++
}
//inc<=0 ?: messages.append('API unable to return all parameters, Please check logs.')
//if(messages.toString()) throw new Error(messages.toString())
assert inc<=0, messages.append('API unable to return all parameters, Please check logs.').toString()
I've got a switch case like this:
def someString = 'hello1234bla'
// ...
switch (someString) {
case {it.contains('1234')}:
doSomething()
break
case {it.contains('2468')}:
doSomethingElse()
break
default:
throw new Exception("ERROR: Number not found")
break
}
This seems to be quite a lot of code for something so seemingly simple. All I want is to have different functions be executed when someString contains a specific substring. Is there no simpler way to do this, apart from maybe an if-else cascade?
This is pretty close to what the comments above suggest, but I'll write out a working example with indentation etc and perhaps it will be a bit more readable:
def someString = "hello1234bla"
def found = [
'1234': { println "do something" },
'2468': { println "do something else" }
].find { pattern, action ->
if (someString.contains(pattern)) { action(); true }
else false
}
if (!found) throw new Exception("ERROR: Number not found")
this executes the first matching action and throws an exception if no matches were found. If you need to execute an action for every match, replace the find call with a findAll call.
Another way of executing code based on a pattern in the string is the groovy String eachMatch method:
def someString = "hello1234blae"
someString.eachMatch(/1234/) { println "do something" }
someString.eachMatch(/2468/) { println "do something else" }
which uses regular expressions and runs the closure (the block in the curlies after the eachMatch call) once for every match. Thus:
someString.eachMatch(/e/) { println "runs twice" }
on the above string would execute twice as there are two 'e' characters in the string.
I'm using nightwatch to check that a table cell on a page contains a number greater than 0.
To achieve this I have to use the node assert package:
const assert = require('assert');
So first, I get the table cell element text, and in the callback I parse it to an int and use assert to check it's value:
...
.getText("//table[#id='topology-summary-table']/tbody/tr/td[7]", function(el){
assert(parseInt(el.value) > 0, "Num Executors == 0!");
}).end()
...
The only problem with this is that if assert throws an AssertionError (ie: if the number in the table cell is 0), then the test halts, and .end() never gets called, thus leaving the browser process open and hanging around. Not ideal.
I have got around that fact by doing the following:
...
.getText("//table[#id='topology-summary-table']/tbody/tr/td[7]", function(el){
try {
assert(parseInt(el.value) > 0, "Num Executors == 0!");
} catch(e){
this.end();
throw e;
}
})
...
but for some reasons this makes me feel bad. :(
My question is: Is there a better way?
The nightwatch api actually extends the assert api, so there is no need to require it.
Instead, do this:
.getText("//table[#id='topology-summary-table']/tbody/tr/td[7]", function(el){
this.assert.ok(parseInt(el.value) > 0, "Num Workers == 0!");
})
Answer provided by beatfactor here: https://github.com/nightwatchjs/nightwatch/issues/1002#issuecomment-223240103
The null safe operator in Groovy is great for reducing code and making things more readable. We can go from this:
def customer = getCustomer(custNo)
if(!customer)
throw new Exception("Invalid customer: ${custNo}")
def policy = customer.getPolicy(policyNo)
if(!policy)
throw new Exception("Invalid policy: ${policyNo}")
def claim = policy.getClaim(claimNo)
if(!claim)
throw new Exception("Invalid claim: ${claimNo}")
..to this...
def claim = getCustomer(custNo)?.getPolicy(policyNo)?.getClaim(claimNo)
But nothing's for free; using null/safe navigation, if claim is null, it's not immediately obvious what caused it: either custNo, policyNo, or claimNo may be invalid.
We could go back and start checking what's null, but that's counterproductive, and actually, it's not even possible since intermediate objects are not stored in variables.
So the question is: Is it possible to identify what was null when chaining method calls using null/safe navigation?
UPDATE
I took another stab at this using dynamic method invocation. It takes an init target (usually a dao) to initialize the object (customer in this case), and a map containing method names as strings (with arguments as values). Using an iterator, invokeChain simply traverses the map (chain); if anything in the chain returns null, identifying the method that caused it becomes trivial.
def invokeChain = { initTarget, chain ->
def obj
chain.eachWithIndex{ it, idx ->
//init obj from dao on first iteration only,
//remaining iterations get from obj itself
obj = (!idx) ? initTarget."$it.key"(it.value) : obj?."$it.key"(it.value)
if(!obj)
throw new Exception("${it.key}(${it.value}) returned null")
}
obj
}
Usage
Mock a customer dao for initTarget...I've inserted null as return type for getClaim(), which should throw an exception.
def static getCustomer = { custNo ->
[ getPolicy: { p ->
[getClaim:{ c ->
null //"Claim #${c}"
}]
}]
}
..using invokeChain, easy as pie:
def claim = invokeChain(this, [getCustomer:123, getPolicy:456, getClaim:789])
...throws exception, as expected:
Exception in thread "main" java.lang.Exception: getClaim(789) returned null
I like this approach because it's compact, readable, and easy to use; what do you think?
I think there is no clear way to do so.
I can be wrong, will check sources later, but safe navigation is a syntax sugar for if statement.
As a hack you can wrap your code with interceptor, trace last method call inside, and then use that info to proide error message.
It will not be cheap, and will cost you some code to realize interception and some performance while running. But you can achieve something like
mayFail("getCusomer", "getPolicy", "getClaim") {
getCustomer(custNo)?.getPolicy(policyNo)?.getClaim(claimNo)
} == "getPolicy" // failed on second step
EDIT: As #tim_yates proved, ?. is a syntax sugar with if construction behind. Thanks Vorg van Geir for the link, I have copied it here, to an answer. He say, it's outdated, and it looks like he is right. I have managed to make ProxyMetaClass work(in Groovy 2.0.6), so given way isn't totally broken. Now I need to specify exact classes to intercept, and I can not find a way to catch inherited method calls.(to simply intercept java.lang.Object)
def logInterceptor = new TracingInterceptor()
logInterceptor.writer = new StringWriter()
def intProxy = ProxyMetaClass.getInstance(Integer)
def stringProxy = ProxyMetaClass.getInstance(String)
intProxy.setInterceptor(logInterceptor)
stringProxy.setInterceptor(logInterceptor)
intProxy.use {
stringProxy.use {
println(("Hello" + "world").size().hashCode())
} }
println(logInterceptor.writer.toString())
All that hell may be wrapped in some utility code, but I highly doubt in necessarity of this. Performance overhead will be awful and some boilerplate code will remain.
The game is not worth the candle.
What about attributions and asserts?
def policy = customer?.policy
def claim = policy?.claim
def number = claim?.number
assert customer, "Invalid customer"
assert policy, 'Invalid policy'
assert claim, 'Invalid claim'
UPDATE:
You already found the solution, but i'd like to contribute with an interceptor idea:
The mock:
def dao = [
getCustomer : { custNo ->
[ getPolicy: { p ->
[getClaim:{ c ->
null //"Claim #${c}"
}]
}]
}
]
The interceptor:
class MethodCallInterceptor {
def delegate
def invokeMethod(String method, args) {
def result = delegate.invokeMethod(method, args)
if (result == null) {
throw new RuntimeException("$method returned null")
}
else {
new MethodCallInterceptor(delegate: result)
}
}
def getProperty(String property ) {
delegate[ property ]
}
void setProperty(String property, value) {
delegate[ property ] = value
}
}
The test:
def interceptedDao = new MethodCallInterceptor(delegate: dao)
try {
interceptedDao.getCustomer(123).getPolicy(456).getClaim(789)
assert false
} catch (e) {
assert e.message.contains( 'getClaim returned null' )
}