How can I assert a response consisting of an array of values to a user defined variable - xpath

I have a Soap request which response returns a set of values under the same tag
let's say
<PricelistDetails>
<ServicePricelistDetailInfo>
<cost>20</cost>
</ServicePricelistDetailInfo>
<ServicePricelistDetailInfo>
<cost>25</cost>
</ServicePricelistDetailInfo>
<ServicePricelistDetailInfo>
<cost>30</cost>
</ServicePricelistDetailInfo>
<PricelistDetails>
I'v created an Xpath assertion to assert the cost tag to a user defined variable:
/Envelope/Body/GetServicePricelistResponse/GetServicePricelistResult/ServicePricelistInfoList/ServicePricelistInfo/PricelistDetails/ServicePricelistDetailInfoList/ServicePricelistDetailInfo/cost ='${COST1}'
whilst COST1 is defined as below :
name : COST1
Value :[20,25,30]
but when running the test plan it is showing an assertion error
Note:
I 've created an Xpath extractor to test the assertion query and it returned all
of the cost values from the response correctly

I would suggest putting your XPath query into XPath Extractor, adding Debug Sampler afterwards and checking the generated variables via View Results Tree listener, my expectation is that you will get something like:
cost=20
cost_1=20
cost_2=25
cost_3=30
cost_matchNr=3
So you will be able to use "normal" Response Assertion against these ${cost_1}, ${cost_2} and ${cost3} variables.
If for some reason you need to go the "XPath way" - use the following XPath Expression in the assertion:
concat("[", //PricelistDetails/ServicePricelistDetailInfo[1]/cost, ",", //PricelistDetails/ServicePricelistDetailInfo[2]/cost, ",", //PricelistDetails/ServicePricelistDetailInfo[3]/cost, "]")="${COST1}"
Demo:
References:
XSLT, XPath, and XQuery Functions
XPath Language Specification
How to Use JMeter Assertions in Three Easy Steps

Your expression will just compare each of values from returned array (20, 25, 30) with [20,25,30] like:
20 = [20,25,30] # false
25 = [20,25,30] # false
30 = [20,25,30] # false
and return false as all comparissons failed, while you need to compare all of them at once:
[20,25,30] = [20,25,30] # true
I'm not sure that it's the best solution, but as last resort you can try
concat('[', string-join(//PricelistDetails/ServicePricelistDetailInfo/cost, ','), ']') = '${COST1}'

Related

Extracting corresponding values in JSR223 post processor in JMeter Randomly

Hi All / Dimitri T Could you please post your valuable thoughts on extracting corresponding Values (For example ItemID1 and ItemSlot1) in one block of code randomly. I was able to write below Jsr223 postprocessor code and it is working fine. But when there are Blank spaces in ItemSlot id, then they are not fetching. From below code , i am passing ${rannum} under "Match No" in required regular expression.
Note: There will be more than 100 corresponding values. In some cases, we won't have ItemSlot1.i.e Blank/null values are appearing from server response. Hence, my script is not picking corresponding values.
Application Server Response:
"viewSaleListingLink": "https://Example.com/cars/item/search/-/listing/ItemID1/100011142",
"saleCountry": "",
"saleNote": "",
"bidLiveUrl": "https://Example.com/cars//registration?p_p_id=RegistrationPortlet_WAR_PWRWeb&p_p_lifecycle=1&p_p_state=normal&ItemSlot1=103009468",
JSR223PostProcessor Code
import java.math.MathContext;
import java.math.RoundingMode;
// Read occurance values from pervious response
def Max = Integer.parseInt( vars.get("ItemID1_matchNr"));
int min=1;
int rannum = min + (int) (Math.random() * ((Max - min) + 1));
log.info("Values id ="+rannum);
vars.put("rannum",rannum.toString());
enter image description here
If you need to extract a random match/pair of matches from the response using Regular Expression Extractor - it's sufficient just to provide 0 as the "Match No" and it will automatically fetch the random match group so you won't have to write any code:
Also be aware that Post-Processors are executed in the order they appear (upside down) so:
If your JSR223 PostProcessor is above the Regular Expression Extractor - ItemID1_matchNr will be undefined
If your JSR223 PostProcessor is below the Regular Expression Extractor - your rannum variable won't have any value
Also your response seems to be JSON so it makes sense switching to JSON JMESPath Extractor which is more powerful and convenient

Jmeter values mapping

How to achieve a kind of mapping between string and numeric values that can be used for comparison in assertion? Example:
MAP "DELIVERED"=0
"PENDING"=1
"WAITING"=2
sampler1 - extracted numeric_value=0
sampler2 - assert string value="DELIVERED" is equal to its numeric value
Please check the below test plan:-
I have used variable name from regular expression of 1st sampler in the switch controller like ${regVar}..Then used the second request 3 times i.e. 0,1,2 and used response assertion with the desired value like "DELIVERED"=0 for first sampler under switch i.e "0" then in second "PENDING"=1 i.e "1"..so on.
With this, based on the regEx value from 1st http sample, only one http request will be send for 2nd sampler and that request have it own assertion. I have tried with both positive and negative cases. Please change the assertion value based on your requirements.
Please check if it helps.
Be aware of JSR223 Assertion which allows you to use arbitrary Groovy code to define pass/fail criteria.
You can access the numeric_value using vars shorthand for JMeterVariables class like:
def numericValue = vars.get('numeric_value')
Example code:
def myMap = ['0':'DELIVERED', '1':'PENDING', '2':'WAITING']
def numericValue = vars.get('numeric_value')
log.info('Numeric value is: ' + numericValue)
log.info('Status is: ' + myMap.get(numericValue))
Demo:
More information: Scripting JMeter Assertions in Groovy - A Tutorial
Thanks Dmitri, implemented solution based on your suggestion and it suites fine.

Taurus / performance tests: verify data inside a JsonArray

I extract a JsonArray containing a list of string, and I want to validate by a regex each string inside this object.
Problem, I don't seem to find any answers on the Taurus' website.
Do you know how I can do it ?
Example below:
# Verification of value inside the JsonArray
extract-jsonpath:
names: $.names
- foreach: name in names
do:
- jsonpath: ${name} # if this JSONPATH is not found, assert will fail
validate: true # validate against an expected value
expected-value: "\\w" # value we're expecting to validate. [default: false]
regexp: true # if the value is regular expression, default: true
expect-null: false # expected value is null
invert: false # invert condition
I don't think it is possible with Taurus YAML syntax as:
foreach keyword generates a normal JMeter ForEach Controller
These jsonpath, validate, etc. are applied to a Sampler by default, they will not work if you add them just as children of the ForEach Controller
Assuming above points I would suggest adding a JSR223 PostProcesssor to perform all the checks. In Taurus it is being done via JSR223 Blocks like:
- url: https://api.example.com/v1/media/search
extract-jsonpath:
names: $.names
jsr223:'1.upto(vars.get("names_matchNr") as int,{if (vars.get("names_$it").matches("\\w+")) {prev.setSuccessful(false)}})'
See The Groovy Templates Cheat Sheet for JMeter article to get more ideas with regards to what can be done using Groovy scripts.

Regular expression is fetching 9 values how can we add all 9 value to next request in Jmeter

Regular expression is fetching 9 values
Need to add all these ticked values with comma separation in next request.How can we do this in J meter
How can we pass multiple values extracted via regular expression to next request in JMeter
Can you please share some snippet of the HTML response, I'd like to help you with the answer. Also, at times, using an XPath expression in an XPath Extractor can be easier to work with.
If the reference name for is set to VALUE, then you can access each of the 9 matched values as VALUE_1, VALUE_2, ...... VALUE_9
Given you configure your Regular Expression Extractor as follows:
Reference Name: arg_name
Regular Expression: `arg_names" value="(.+?)"
Template: $1$
Match No.: -1
You will get JMeter Variables like:
arg_name_1=foo
arg_name_2=bar
arg_name_3=baz
arg_name_matchNr=3
Now you should be able to concatenate the values using the following __groovy() function:
${__groovy(def builder = new StringBuilder(); 1.upto(Integer.parseInt(vars.get("arg_name_matchNr"))) { builder.append(vars.get("arg_name_" + it)).append("\,") }; builder.toString(),)}
Demo:
More information:
vars is a shorthand to JMeterVariables class instance
Groovy For Loop Examples
Apache Groovy - Why and How You Should Use It

Use Datasource Properties in XPath Expression of SoapUI

I need to know whether it is possible to use a datasource property in XPath Expression panel of XPath Match Configuration. For instance, if we have the following XML document:
<ns1:Ions>
<ns1:Ion>UI</ns1:Ion>
<ns1:IonType>X</ns1:IonType>
<ns1:StartDate>2010-05-10</ns1:StartDate>
</ns1:Ions>
<ns1:Ions>
<ns1:Ion>HH</ns1:Ion>
<ns1:IonType>RI</ns1:IonType>
<ns1:StartDate>1998-11-23</ns1:StartDate>
</ns1:Ions>
<ns1:Ions>
<ns1:Ion>CF</ns1:Ion>
<ns1:IonType>A</ns1:IonType>
<ns1:StartDate>2000-06-10</ns1:StartDate>
</ns1:Ions>
I need to evaluate to see whether a content of IonType is 'A' only if its sibling node, Ion, has a value of 'CF'. I was hoping to accomplish this by setting XPath Match Configuration as following:
XPath Expression (DataSourceInput#ION is 'CF')
declare namespace ns1='http://my.namespace.com';
//ns1:Ions[ns1:Ion[text()=${DataSourceInput#ION}]]/ns1:IonType/text()
Expected Results (DataSourceInput#ION_TYPE is 'A')
${DataSourceInput#ION_TYPE}
Running the test would result in SoapUI [Pro] to error the following, Missing content for xpath declare. If I replace ${DataSourceInput#ION} with an actual value, i.e. 'CF', the test works accordingly (I even tried place single quotes around ${DataSourceInput#ION}, but it didn't work).
Is there another way of accomplish this in SoapUI?
I try what you do and it works for me if I put single quotes around the property:
declare namespace ns1='http://my.namespace.com';
//ns1:Ions[ns1:Ion[text()='${DataSourceInput#ION}']]/ns1:IonType/text()
Did you check that testStep name is exactly DataSourceInput? If there are spaces in the TestStep name (i.e your testStep name is Data Source Input you have to put ${Data Source Input#ION}).
Anyway I give you another way to do so, you can add a testStep of type groovy script after the testStep where you are getting the <Ions>response, and check the assert here like follows:
// get xml holder
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def ionsHolder = groovyUtils.getXmlHolder("IonsTestStepName#response");
// generate xpath expression
def xpathExpression = "//*:Ions[*:Ion[text()='" + context.expand('${DataSourceInput#ION}') + "']]/*:IonType/text()";
log.info xpathExpression;
// get the node value
def nodeValue = ionsHolder.getNodeValue(xpathExpression);
// check expected value
assert nodeValue == context.expand('${DataSourceInput#ION_TYPE}'),'ERROR IONS VALUE';
Hope this helps,

Resources