Groovy : Can I use assert in conjuction with elvis operator? - groovy

I would like to increment the values based on assert results :
def a = 1
def b = 1
def c = 0
def d = 0
(assert a==b, "Mismatch") ? (c++) : (d++)
Is it possible?

You misunderstood one important part - assert is not a function and it does not return any value. It is a Groovy's (and Java) keyword (statement) that throws an exception if the expression on the right side evaluates to false, but it does not return any result. However, you can achieve expected result using ternary operator in the way it was designed to use:
def a = 1
def b = 1
def c = 0
def d = 0
a == b ? (c++) : (d++)
println "c = ${c}, d = ${d}"
Output:
c = 1, d = 0
You can read more about using assertions in Groovy's official "Testing Guide, chapter 2.1 Power Assertions".

If you really want to "ignore" the assert and continue, you can catch the exception it throws. E.g.
def a = 1
def b = 1
def c = 0
def d = 0
try {
assert a==b, 'Mismatch'
c++
}
catch (AssertionError e) {
d++
}
println([a,b,c,d])
I'd only use tactics like that, if some foreign code dictates that on me. This is very convoluted code unless you want to abuse the power-assert to generate a nice "warning" log message for you.

Related

def vs final def in Groovy

I've written simple test in Groovy using Spock framework
class SimpleSpec extends Specification {
def "should add two numbers"() {
given:
final def a = 3
final b = 4
when:
def c = a + b
then:
c == 7
}
}
Variable a is declared using def and final keywords combination. Variable b is declared using only final keyword.
My question is: what's the difference (if any) between these two declarations? Should one approach be preffed to the other? If so, why?
User daggett ist right, final does not make a local variable final in Groovy. The keyword only has influence on class members. Here is a little illustration:
package de.scrum_master.stackoverflow
import spock.lang.Specification
class MyTest extends Specification {
def "Final local variables can be changed"() {
when:
final def a = 3
final b = 4
final int c = 5
then:
a + b + c == 12
when:
a = b = c = 11
then:
a + b + c == 33
}
final def d = 3
static final e = 4
final int f = 5
def "Class or instance members really are final"() {
expect:
d + e + f == 12
when:
// Compile errors:
// cannot modify final field 'f' outside of constructor.
// cannot modify static final field 'e' outside of static initialization block.
// cannot modify final field 'd' outside of constructor.
d = e = f = 11
then:
d + e + g == 33
}
}
When I switched one of my Spock projects to version 1.3 with Groovy 2.5 and noticed that this test no longer compiles now due to the compiler detecting the reassignment to final local variables. I.e. the inconsistency in Groovy <= 2.4 seems to be fixed.
final variables declared inside the methods are processed as usual variables in groovy
check the class below and the one generated by groovy (2.4.11)
ps: possible the given: section in spock generates code differently...

Can we write junit tests for any groovy script which does not have any class and methods? If yes then how?

I have a situation where I have to write a code for a groovy script which is not written inside a class . Its just a plain groovy script. For some reason I can't show the actual code .But it would simply like this:
def var = 10
return var
You can create an object of the class and call run() method on it. This will instantiate the class and run the method in it.
You do not have to write tests specially in the case that you mentioned.
Use in-built assert for the same.
def var = 10
var++
assert 11 == var, 'Value mismatch for var'
One style is to write micro-tests inline, using the assert feature (as mentioned elsewhere):
def reverseString = { s ->
s?.reverse()
}
// test_reverseString
assert 'cba' == reverseString('abc')
assert '' == reverseString('')
assert null == reverseString(null)
def sumList = { list ->
(list == null) ? 0 :
(list.isEmpty()) ? 0 :
list.sum()
}
// test_sumList
assert 6 == sumList([1,2,3])
assert 0 == sumList([])
assert 0 == sumList(null)
// ---- main
println reverseString('esrever')
println sumList([1,2,3,4])
It is relatively easy to modify this code so that only the tests execute (e.g. based on a command-line argument).

Groovy iterating list variables

I am working on a script to collect field names (dialogPartyASelection_* && dialogPartyBSelection_*) and then compare the two values to see check if they match. The full list(selections)of fields is being broken down into 'groups' before comparison. I can break out certain parts (IE, comparing the two field values via iteration) and test successfully, however when bringing everything together the script doesn't seem to compare correctly. I may be approaching this/setting myself up to do this wrong, (have started to toy with creating a map, with party A as the key with party B as value).
Snippet of code:
// Test Variables
PartyBSelection_Propertieshamster = 'Accepted'
PartyBSelection_Propertieszembra = 'Agreed'
PartyBSelection_Propertiesdogs = 'Agreed'
PartyBSelection_Propertiescats = 'Decision taken'
PartyASelection_Propertieshamster = 'Accepted'
PartyASelection_Propertieszembra = 'Agreed'
PartyASelection_Propertiesdogs = 'Agreed'
PartyASelection_Propertiescats = 'Decision taken'
// example of selections(there are lots of entries for A/B party) = ['dialogPartyBSelection_Communication','dialogPartyASelection_Housing','dialogPartyASelection_Income','PartyASelection_Properties']
def selectedGroup = { s -> selections.findAll { it.contains s}} // for pulling groups of questions from list
def isAgreed = { a, b -> (a in ['Agreed', 'Decision taken','Accepted'] && b in ['Agreed', 'Decision taken','Accepted']) } // for comparing values
for(questions in selectedGroup("Properties")){
{k -> percentCompleteProperties += isAgreed("PartyASelection_${k}", "PartyBSelection_${k}")? 1 : 0}
println questions
println percentCompleteProperties
}
Current output:
PartyBSelection_Propertiescats
0
PartyBSelection_Propertieshamster
0
PartyBSelection_Propertiesdogs
0
PartyBSelection_Propertieshamster
0
PartyASelection_Propertiescats
0
PartyASelection_Propertieshamster
0
PartyASelection_Propertiesdogs
0
PartyASelection_Propertieshamster
0
This is sample code.
but i had changed test data etc.
please check whether this logic is correct for your case.
// Test Variables
def testVariables = [
'PartyBSelection_PropertiesAssets':'Accepted',
'PartyBSelection_PropertiesDebts': 'Agreed',
'PartyBSelection_PropertiesMoney': 'Agreed',
'PartyBSelection_PropertiesSpecialGoods':'Decision taken',
'PartyASelection_PropertiesAssets':'Accepted',
'PartyASelection_PropertiesDebts':'Agreed',
'PartyASelection_PropertiesMoney':'Agreed',
'PartyASelection_PropertiesSpecialGoods':'Decision taken'
]
List<String> selections= [
'PropertiesAssets',
'PropertiesDebts',
'PropertiesMoney',
'PropertiesSpecialGoods',
'PropertiesAssets',
'PropertiesDebts',
'PropertiesMoney',
'PropertiesSpecialGoods'
]
def selectedGroup = { s -> selections.findAll { it.contains s}}
List<String> okLabels = ['Agreed', 'Decision taken','Accepted']
def isAgreed = {a, b ->
(testVariables[a] in okLabels && testVariables[b] in okLabels)
}
List<Map<String, Integer>> result = selectedGroup("Properties").collect {String question ->
[(question) : isAgreed("PartyASelection_${question}", "PartyBSelection_${question}")? 1 : 0 ]
}
assert result == [
['PropertiesAssets':1],
['PropertiesDebts':1],
['PropertiesMoney':1],
['PropertiesSpecialGoods':1],
['PropertiesAssets':1],
['PropertiesDebts':1],
['PropertiesMoney':1],
['PropertiesSpecialGoods':1]
]
Other way
def r = [:]
def questionsCount = selectedGroup("Properties").size()
selectedGroup("Properties").eachWithIndex {String question, Integer i ->
println "question:${question}(${i+1}/${questionsCount})"
r.put(question,isAgreed("PartyASelection_${question}", "PartyBSelection_${question}")? 1 : 0 )
}
// This version includes all records in to the one map.
// Also, a record that is duplicated (as key) is overwritten.
r == [PropertiesAssets:1, PropertiesDebts:1, PropertiesMoney:1, PropertiesSpecialGoods:1]
then output:
question:PropertiesAssets(1/8)
question:PropertiesDebts(2/8)
question:PropertiesMoney(3/8)
question:PropertiesSpecialGoods(4/8)
question:PropertiesAssets(5/8)
question:PropertiesDebts(6/8)
question:PropertiesMoney(7/8)
question:PropertiesSpecialGoods(8/8)

evaluating value of an expression as expression in groovy

Here is the code i am trying to get working
def expr = ''
List params = []
params << 'filter-name'
params << 'servlet-name'
params << 'url-pattern'
params.each{expr = expr+ "it.'${it}'.text().trim()#"}
expr = expr.substring(0, expr.length()-1)
consNodes.each{
println "data is:$"{expr}"
println "actual : ${it.'filter-name'.text().trim()}#${it.'servlet-name'.text().trim()}#${it.'url-pattern'.text().trim()}"
}
in the above result comes like
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : presenceLogoutFilter##/adfAuthentication/*
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : remoteApplication##/rr/*
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : ServletADFContextFilter#GetHandler#
data is:it.'filter-name'.text().trim()#it.'servlet-name'.text().trim()#it.'url-pattern'.text().trim()
actual : ServletADFContextFilter##/PresenceServlet/*
So, as you can see that my constructed expression is not able to evaluate further. Any advise on how to make it work?
The problem is that you're creating a GString like this: "it.'${it}'.text().trim()#", but then you're converting it into a String when you concatenate it: expr + "it.'${it}'.text().trim()#". Once you turn a GString into a String it no longer evaluates expressions. But even if you address that it won't solve your problem because GStrings do not evaluate like you think they do. The best way to explain it is with an example:
import org.codehaus.groovy.runtime.GStringImpl
// What you're doing
def a = 'John'
def b = 'Hello, $a'
def c = "${a}"
assert b == 'Hello, $a'
// What the compiler is doing (ignoring the variable name changes)
def aa = 'John'
def bb = 'Hello, $a'
def cc = new GStringImpl([] as Object[], ['Hello, $a'] as String[])
assert cc == 'Hello, $a'
// What you want the compiler to do, but it will not.
def aaa = 'John'
def bbb = 'Hello, $a'
def ccc = new GStringImpl(['John'] as Object[], ['Hello, '] as String[])
assert ccc == 'Hello, John'
If you really want to, you can build the GStrings manually, but that will be very difficult. And you'd end up depending on a class which is not guaranteed to remain backward-compatible between Groovy releases.
Here's what you can do instead:
def params = []
params << 'filter-name'
params << 'servlet-name'
params << 'url-pattern'
def evaluators = params.collect {
{ attr, node -> node[attr]?.text()?.trim() ?: '' }.curry(it)
}
consNodes.each { node ->
println evaluators.collect { c -> c(node) }.join('#')
}
The output looks like this:
presenceLogoutFilter##/adfAuthentication/*
remoteApplication##/rr/*
ServletADFContextFilter#GetHandler#
ServletADFContextFilter##/PresenceServlet/*
Instead of a single large expression you and up with a list of closures, each responsible for evaluating a node attribute. Then, you can join the results with '#'s.

Difference of two maps in groovy using collectEntries

I am trying to find the difference between values in two maps
#Test
void testCollecEntries() {
def mapOne= ["A":900,"B":2000,"C":1500]
def maptwo = ["A":1000,"D":1500,"B":1500]
def balanceMap = maptwo.collectEntries { key, value-> [key:value-mapOne[key]] }
println balanceMap
}
I am trying to find the difference of values from maptwo with that of the values from mapOne. If the entry doesn't exist i need to ignore. This gives me a null pointer exception.
Appreciate any help.
It will throw NPE because you are looking for key "D" in mapOne which is not available.
You can avoid that by a null safe operation and default value to 0.
def one= [A:900, B:2000, C:1500]
def two = [A:1000, D:1500, B:1500]
def result = two.collectEntries{k,v -> [k, (v - (one[k]?:0))]}
println result
//Print
[A:100, D:1500, B:-500]
In case, you want to consider the common keys then use:
def result = two.collectEntries{k,v -> one[k] ? [k, (v - one[k])] : [:]}
//or
//def result = two.collectEntries{k,v -> (k in one.keySet()) ? [k, (v - one[k])] : [:]}
//Print
[A:100, B:-500]
You could look at this good example: http://groovyconsole.appspot.com/script/364002

Resources