Using community soapui 5.2.1.
Can I use an XPATH assertion to test a number is between two values?
This question shows how to do one logical test.
But I'd like to store the value in a variable and test on an AND condition.
Something like (psuedo code):
declare namespace ns1='http://my.space/XML/output/6.1';
testme=//ns1:items-section[1]/ns1:results/#total_items;
testme > 100 && testme < 200;
If this can't be done, options i see are:
retrieving the attribute twice (guess that's not performant)
reverting to script assertion (more complex )
buy NG PRO ( more expensive)
IMO generally if you want to apply a pseudo code for assertion purpose I prefer to use script assertion since in SOAPUI Groovy script assertion gives you a lot of flexibility.
However your case seems short, and you're only worried about to avoid perform twice the same XPath; then you can use a option which is not in your list: XQuery Match assertion. The XQuery expression could be:
declare namespace ns1='http://my.space/XML/output/6.1';
declare variable $testme := //ns1:items-section[1]/ns1:results/#total_items;
($testme > 100 and $testme < 200)
Note the use of and instead of &&.
Also you can simplify your XPath expression using * for namespaces:
declare variable $testme := //*:items-section[1]/*:results/#total_items;
($testme > 100 and $testme < 200)
This will return in the expected result:
<xml-fragment>true</xml-fragment> or <xml-fragment>false</xml-fragment> depends on the $testme value.
Hope this helps,
Related
If I use a JSR223 Preprocessor with the following code:
log.info("" + ${rand});
where ${rand} is a random variable, how can I make this variable change every time I loop this thread?
Changing the number of threads will indeed have the variable change each run, with loop it just takes one value and keeps it for all the other loops.
Putting it in a JSR223 Sampler yields the same result. I basically want the code to behave as a User Parameter.
Don't inline JMeter Functions or Variables in JSR223 Test Elements because:
They may resolve into something which will cause compilation failure
The syntax conflicts with Groovy's GStrings feature
If you tick Cache compiled script if available box the first occurrence will be cached and used on subsequent iterations, if you don't - you will loose performance benefits of Groovy
When using this feature, ensure your script code does not use JMeter variables or JMeter function calls directly in script code as caching would only cache first replacement. Instead use script parameters.
So:
Either move your ${rand} variable to "Parameters" section and change your code to
log.info("" + Parameters);
or use vars shorthand to JMeterVariables class instance, in this case change your code like:
log.info("" + vars.get("rand"));
You need to use vars to avoid getting cached/same value
vars.get("rand")
See JSR223 Best practices
script does not use any variable using ${varName} as caching would take only first value of ${varName.. Instead use vars.get("varName")
I'm trying to evaluate a not equals in a if condition in bean shell but though the logic seems to be correct. I'm not getting the expected results.
This is for bean shell post processor in jmeter
r = ctx.getPreviousResult().getResponseCode();
if (!r.equals(200))
{
log.info("vin IS --> "+"${vin}");
p.println(r +","+ "${vin}" + ",");
}
I'm intending to print only non 200 response code but it prints 200 response codes too.
thanks in advance for your help
The code :
if (!r.equals(200))
Should be:
if (!r.equals("200"))
And by the way, you should not use Beanshell anymore, prefer JSR223 Test Elements + Groovy as per this :
https://www.ubik-ingenierie.com/blog/jmeter_performance_tuning_tips/
You're comparing a String with an Integer, you need to either cast it to the Integer first like:
r = Integer.parseInt(ctx.getPreviousResult().getResponseCode());
You're using Beanshell which is a some form of performance anti-pattern. It's recommended to use JSR223 Test Elements and Groovy language for any form of scripting as Groovy has much better performance comparing to Beanshell.
You're inlining JMeter Variables into scripts, it is not very safe as variables might resolve into something which cause compilation failure or unexpected behavior. Moreover in case of Groovy variables will either be resolved only once or clash with GString templates / compilation caching feature. So consider changing:
log.info("vin IS --> "+"${vin}");
to
log.info("vin IS --> "+vars.get("vin"));
I'm trying to run a FOR loop on robot framework depending of the status of another variable.
${STATUS1}= Run Keyword And Return Status Should Be Equal As Strings ${CELLVALUE} ${EXPECTEDVALUE}
\ ${COUNT}= Set Variable If '${STATUS1}' == 'True' ${COUNT}+1
\ ... '${STATUS1}' == 'False' ${COUNT}+0
But all I get is '''0'+0'+0'+1 or similar, even if I use Run keyword If and Evaluate instead of set var, I tried to convert to integer but nothing happens and I cannot convert it to integer or number. Any suggestions? thanks in advance!
It looks like you're simply wanting to increment ${COUNT} if ${CELLVALUE} equals ${EXPECTEDVALUE}. That can be done pretty easily with Set Variable if
If you know that ${CELLVALUE} and ${EXPECTEDVALUE} are of the same internal type (eg: strings or ints), and you're using robot framework 2.9 or greater, you can write it like this:
${COUNT}= Set variable if $CELLVALUE == $EXPECTEDVALUE
... ${COUNT+1} ${COUNT}
This assumes that ${COUNT} is initialized to an integer value, which you can do by assigning it the value ${0}
If you don't know the type, can't guarantee the type, or are using an older version of robot, you can use triple-quoted strings to coerce the values to strings:
${COUNT}= Set variable if '''${CELLVALUE}''' == '''${EXPECTEDVALUE}'''
... ${COUNT+1} ${COUNT}
Of course, you could use Run Keyword and Return Status like in your example, and then compare the status. That seems like an unnecessary extra step, but it might make sense in your actual test.
The point being, you can use Set variable if and extended variable syntax to solve this problem.
Note 1: With Set variable if, two values are provided. The first value is assigned if the expression is true, the second one is assigned if the value is false. The second value is the original variable, meaning it won't be changed. If you don't provide the second value, the variable will be set to None.
Note 2: Putting an expression inside curly braces (eg: ${COUNT+1} is documented in rule 4 of extended variable syntax.
Note 3: Starting with robot framework 2.9, variables are available in the evaluation namespace with the simplified syntax $varname. So, the robot variable ${CELLVALUE} can be used in python expressions as $CELLVALUE. This is documented in the section Evaluating Expressions in the BuiltIn library documentation.
I am new to using Halide and I am playing around with implementing algorithms first. I am trying to write a function which, depending on the value of the 8 pixels around it, either skips to the next pixel or does some processing and then moves on to the next pixel. When trying to write this I get the following compiler error:
84:5: error: value of type 'Halide::Expr' is not contextually convertible to 'bool'
if(input(x,y) > 0)
I have done all the tutorials and have seen that the select function is an option, but is there a way to either compare the values of a function or store them somewhere?
I also may be thinking about this problem wrong or might not be implementing it with the right "Halide mindset", so any suggestions would be great. Thank you in advance for everything!
The underlying issue here is that, although they are syntactically interleaved, and Halide code is constructed by running C++ code, Halide code is not C++ code and vice versa. Halide code is entirely defined by the Halide::* data structures you build up inside Funcs. if is a C control flow construct; you can use it to conditionally build different Halide programs, but you can't use it inside the logic of the Halide program (inside an Expr/Func). select is to Halide (an Expr which conditionally evaluates to one of two values) as if/else is to C (a statement which conditionally executes one of two sub-statements).
Rest assured, you're hardly alone in having this confusion early on. I want to write a tutorial specifically addressing how to think about staged programming inside Halide.
Until then, the short, "how do I do what I want" answer is as you suspected and as Khouri pointed out: use a select.
Since you've provided no code other than the one line, I'm assuming input is a Func and both x and y are Vars. If so, the result of input(x,y) is an Expr that you cannot evaluate with an if, as the error message indicates.
For the scenario that you describe, you might have something like this:
Var x, y;
Func input; input(x,y) = ...;
Func output; output(x,y) = select
// examine surrounding values
( input(x-1,y-1) > 0
&& input(x+0,y-1) > 0
&& ...
&& input(x+1,y+1) > 0
// true case
, ( input(x-1,y-1)
+ input(x+0,y-1)
+ ...
+ input(x+1,y+1)
) / 8
// false case
, input(x,y)
);
Working in Halide definitely requires a different mindset. You have to think in a more mathematical form. That is, a statement of a(x,y) = b(x,y) will be enforced for all cases of x and y.
Algorithm and scheduling should be separate, although the algorithm may need to be tweaked to allow for better scheduling.
I'm using soapUI 5 (non pro) and all i need is to validate(assert) a number is greater than zero in the expected result section. So this means
1) in XPath expression(Xpath match) I am declaring the below (I need to remove all text and only have numbers then check that number is greater than zero)
replace(//OUTBOUND_MESSAGE.MESSAGE_CONTENT, '[^0-9]','')
2) All i want to do in expected result is =!0 or number>0 so i attempted
${=!0} but doing that brings back a boolean T/F. I'm really lost :(
The expression ${=!0} is not working as you expect. In SOAPUI this kind of expressions ${=expression} are executed as groovy script so really SOAPUI is executing !0 which is result is true and this is the expected result. This is why SOAPUI throws replace..., expecting [true].
I think that it's better to change you XPath expression to evaluate directly if your expression is >0:
number(replace(//OUTBOUND_MESSAGE.MESSAGE_CONTENT, '[^0-9]',''))>0
And as expected result simply set true.