Jenkins boolean parameter is always true in groovy - groovy

I have a Jenkins job that calls a groovy script and the groovy script uses Jenkins parameters to do it's work. I can retrieve all the parameters without a problem except for a boolean parameter. The boolean parameter is a checkbox in Jenkins
I read the jenkins parameter into Groovy as follows:
boolean libraryBranch = config.get('library_branch_feature');
Now when I print the 'libraryBranch' variable
out.println "-- Library branch feature?: " + libraryBranch.toString();
I get the following printed line:
-- Library branch feature ?: true
So it doesn't matter if the boolean Jenkins parameter is selected or not I always have a boolean value 'true' in Groovy. All other (string) parameters inside the same job are read without a problem.
Can someone help me with this issue?
EDIT
Ok I've decided to try and retrieve the code in a couple of other ways and tyring to find a good solution:
Boolean libraryBranch = build.buildVariableResolver.resolve("library_branch_feature");
String libraryBranchString = build.buildVariableResolver.resolve("library_branch_feature").toString();
Boolean libraryBranchStringAsBoolean = build.buildVariableResolver.resolve("library_branch_feature") as Boolean;
The above variables are then printed:
out.println "-- Library branch feature?: " + libraryBranch;
out.println "-- Library branch feature to String: " + libraryBranch.toString();
out.println "-- Library branch feature to String: " + libraryBranch.toString();
out.println "-- Library branch feature as String: " + libraryBranchString;
out.println "-- Library branch feature String as Boolean: " + libraryBranchStringAsBoolean;
The output of the above prints are posted below:
-- Library branch feature?: true
-- Library branch feature to String: true
-- Library branch feature to String: true
-- Library branch feature as String: false
-- Library branch feature String as Boolean: true
So the only way thus far to have the boolean value read correctly as a false is by not turning it into a boolean at all but just reading it as a string and use it as a string.
I would rather use it as a boolean though so any suggestions on the matter is still appreciated.

The answer is to read the Jenkins parameter as String and then convert it to a boolean using the method .toBoolean(); So my libraryBranch is now set as follows:
boolean libraryBranch = build.buildVariableResolver.resolve("library_branch_feature").toString().toBoolean();

Just out of curiosity, I tried the following:
Set the variable 'testmode' as a boolean in the pipeline setup.
Start the job, with testmode set false (unchecked).
In the pipeline script, run the following code immediately upon entry:
testmode=testmode.toBoolean()
if (testmode==false) { print "testmode tests true"}else{print "testmode tests false"}
you will see the result 'testmode tests false'.
To verify my claim that the 'boolean' variable testmode is ACTUALLY a string when it comes in, I tried:
testmode=testmode.toBoolean()
testmode=testmode.toBoolean()
and it blew up on the 2nd 'toBoolean'. I'll spare you the error message...
So, I claim that testmode comes in as the string "false" instead of as a boolean (whether because of promotion, demotion, forcing, whatever).
So, if its a boolean parameter, and you really wanted to treat it like a boolean and not have to say 'if (booleanvar=="true")', then convert it to a boolean as above and you're done.

The question and the answers are a bit dated. The modern method to
consume a boolean parameter is to use the params. global values. params
properly exposes Boolean parameters such that the following both work and
require no string/boolean conversions.
if (params.library_branch_feature) {
// truth logic here
}
// or
if (params.library_branch_feature != false) {
// truth logic here
}
From the Pipeline Syntax for params.:
Exposes all parameters defined in the build as a read-only map with variously typed values. Example:
if (params.BOOLEAN_PARAM_NAME) {doSomething()}
or to supply a nontrivial default value:
if (params.getOrDefault('BOOLEAN_PARAM_NAME', true)) {doSomething()}
NOTE:
It may not make sense that a boolean parameter can have NO value,
but '.getOrDefault()' is useful to set default values for string parameters.

I encountered the same problem with reading java Properties - retrieved boolean values are always true. So, say I have a settings file with property debugging=false. This test will fail:
class ConfigurationTest extends GroovyTestCase {
void testProcessConfiguration() {
Properties properties=new Properties()
FileReader fileReader=new FileReader('settings')
properties.load(fileReader)
boolean debug=properties.getOrDefault('debugging',false)
assert !debug
fileReader.close()
}
}
But if you make it properties.getOrDefault('debugging',false).toString().toBoolean() it will return correct value. Probably this is because of coercion?

Related

Is it possible to get the name of variable in Groovy?

I would like to know if it is possible to retrieve the name of a variable.
For example if I have a method:
def printSomething(def something){
//instead of having the literal String something, I want to be able to use the name of the variable that was passed
println('something is: ' + something)
}
If I call this method as follows:
def ordinary = 58
printSomething(ordinary)
I want to get:
ordinary is 58
On the other hand if I call this method like this:
def extraOrdinary = 67
printSomething(extraOrdinary)
I want to get:
extraOrdinary is 67
Edit
I need the variable name because I have this snippet of code which runs before each TestSuite in Katalon Studio, basically it gives you the flexibility of passing GlobalVariables using a katalon.features file. The idea is from: kazurayam/KatalonPropertiesDemo
#BeforeTestSuite
def sampleBeforeTestSuite(TestSuiteContext testSuiteContext) {
KatalonProperties props = new KatalonProperties()
// get appropriate value for GlobalVariable.hostname loaded from katalon.properties files
WebUI.comment(">>> GlobalVariable.G_Url default value: \'${GlobalVariable.G_Url}\'");
//gets the internal value of GlobalVariable.G_Url, if it's empty then use the one from katalon.features file
String preferedHostname = props.getProperty('GlobalVariable.G_Url')
if (preferedHostname != null) {
GlobalVariable.G_Url = preferedHostname;
WebUI.comment(">>> GlobalVariable.G_Url new value: \'${preferedHostname}\'");
} else {
WebUI.comment(">>> GlobalVariable.G_Url stays unchanged");
}
//doing the same for other variables is a lot of duplicate code
}
Now this only handles 1 variable value, if I do this for say 20 variables, that is a lot of duplicate code, so I wanted to create a helper function:
def setProperty(KatalonProperties props, GlobalVariable var){
WebUI.comment(">>> " + var.getName()" + default value: \'${var}\'");
//gets the internal value of var, if it's null then use the one from katalon.features file
GlobalVariable preferedVar = props.getProperty(var.getName())
if (preferedVar != null) {
var = preferedVar;
WebUI.comment(">>> " + var.getName() + " new value: \'${preferedVar}\'");
} else {
WebUI.comment(">>> " + var.getName() + " stays unchanged");
}
}
Here I just put var.getName() to explain what I am looking for, that is just a method I assume.
Yes, this is possible with ASTTransformations or with Macros (Groovy 2.5+).
I currently don't have a proper dev environment, but here are some pointers:
Not that both options are not trivial, are not what I would recommend a Groovy novice and you'll have to do some research. If I remember correctly either option requires a separate build/project from your calling code to work reliable. Also either of them might give you obscure and hard to debug compile time errors, for example when your code expects a variable as parameter but a literal or a method call is passed. So: there be dragons. That being said: I have worked a lot with these things and they can be really fun ;)
Groovy Documentation for Macros
If you are on Groovy 2.5+ you can use Macros. For your use-case take a look at the #Macro methods section. Your Method will have two parameters: MacroContext macroContext, MethodCallExpression callExpression the latter being the interesting one. The MethodCallExpression has the getArguments()-Methods, which allows you to access the Abstract Syntax Tree Nodes that where passed to the method as parameter. In your case that should be a VariableExpression which has the getName() method to give you the name that you're looking for.
Developing AST transformations
This is the more complicated version. You'll still get to the same VariableExpression as with the Macro-Method, but it'll be tedious to get there as you'll have to identify the correct MethodCallExpression yourself. You start from a ClassNode and work your way to the VariableExpression yourself. I would recommend to use a local transformation and create an Annotation. But identifying the correct MethodCallExpression is not trivial.
no. it's not possible.
however think about using map as a parameter and passing name and value of the property:
def printSomething(Map m){
println m
}
printSomething(ordinary:58)
printSomething(extraOrdinary:67)
printSomething(ordinary:11,extraOrdinary:22)
this will output
[ordinary:58]
[extraOrdinary:67]
[ordinary:11, extraOrdinary:22]

Groovy check for key in map, is trying to access the map value correct?

I'm new to groovy and both of the below seem to be valid, but I wanted to know in what scenario, if any, the first option would return groovy false and give me a key lookup error. Or, is this always OK in groovy? Googling didn't return any detail...
mapFoo = ['keyOne': 'valueOne', 'keyTwo': 'valueTwo']
keyExists = false
// what is the downside of using this
if (mapFoo['keyThree']){
keyExists = true
}
// vs contains()
if (mapFoo.containsKey('keyThree')){
keyExists = true
}
The downside of the first one is that the value might be zero, false, the empty string, or indeed null (thanks Szymon 😀)
All of these will also be considered false
The second one is more trustworthy in these potential situations, and also better expresses your intent to future readers of your code
However, if the scope of the map is small and you know the possible values, it's much quicker to type
boolean keyExists = mapFoo.keyThree

JMeter Assertion : Error when comparing variables

I am trying to assert my API response data with a value I obtained from my Database.
My code fails to compare my variables unless I add toString() to both my variable. Is there any way around it or is toString() mandatory?
The code in question is :
Boolean comparision = false;
for (int i; i < vars.getObject("dbData").size(); i++) {
if (vars.getObject("dbData").get(i).get("DbData").toString().equals(${codeid_API}.toString()))
{
comparision = true;
}
}
${codeid_API} is the variable where I stored my API response data.
(vars.getObject("dbData").get(i).get("DbData") gets the value from my DB.
You can use Objects.equals instead
Objects.equals(vars.getObject("dbData").get(i).get("DbData"), ${codeid_API});
Returns true if the arguments are equal to each other and false otherwise.
For integer you can compare using == and use as int for casting
if (vars.getObject("dbData").get(i).get("DbData") as int == vars.get("codeid_API") as int );
Don't inline JMeter variables in form of ${codeid_API} into Groovy scripts, in case of enabled compiled scripts caching it will be resolved only once and it might break your script logic.
Consider replacing it with vars.get('codeid_API) instead where vars is the shorthand for JMeterVariables class instance
Quote from JSR223 Sampler documentation:
JMeter processes function and variable references before passing the script field to the interpreter, so the references will only be resolved once. Variable and function references in script files will be passed verbatim to the interpreter, which is likely to cause a syntax error. In order to use runtime variables, please use the appropriate props methods, e.g.
props.get("START.HMS");
props.put("PROP1","1234");
More information: Debugging JDBC Sampler Results in JMeter

Parameterizing Objects in spock

I have a problem with parameterizations of list of object by using spock where block. It seems the ListInput value is not taking from the where clause and always coming null value. I have verified the same feature for string and other primitive types and it is working fine.
Does Spock support parameterizations objects ? If yes what is the issue here .
def "check Param Of List of Objects"()
{
expect:
def a= hasflag(ListInput);
a== flag
where:
ListInput | flag
BOList1 | true
BOList2 | false
}
Here the type of BOList1 is an java ArrayList contains the object
You haven't really provided enough information for a definitive answer but I'll try to help.
The where block isn't exactly just a block of code, it's more like a number of parameters passed to a method. It can do a lot, but sometimes you need to pass your code a little differently.
Of note:
- Void methods aren't allowed (but you can get around this using .with{} )
- An iterative parameter cannot also be a derived parameter (constructed from other parameters)
- If you're referencing class level variables (defined within the class but outside this test) they need to be given the #Shared annotation for your tests to have access.
Given more information about where your lists are coming from will help me give better advice.
Final tip; explicitly typecast your parameters to see if that gives you anymore information
def "check Param Of List of Objects"(ArrayList listInput, boolean flag) {
expect:
flag == hasflag(ListInput);
where:
listInput | flag
BOList1 | true
BOList2 | false
}

Strange abstraction behaviour - boolean() returns false while

I'm trying to perform some basic logic on my application which checks the entities position to call an enter/exit method however I'm getting some strange results:
Contains false - Compare true
Where the following method prints the results
#Override
public void checkLocation(Player player) {
System.out.println("Contains " + contains(player) + " - Compare ${inLocation(player.position)}");
}
The contains boolean:
#Override
public boolean contains(Player player) {
return inLocation(player.position);
}
I don't understand how contains(player) returns false, while the inLocation(player.position) returns true? Really stomping on my understanding of how things work.
The code is in groovy. ${var} is just groovy's way of concatenating.
Depending on the context of your code it is possible that groovy's contains method is being called on the class/controller/service that this code exists in, instead of calling your defined contains method. Maybe it is implicitly calling
this.contains(player)
Try changing your method name to "hasPlayer()" or add a println inside your contains method to ensure that code is being called.

Resources