At the moment we are developing an application and deploying it in my local machine. And now I'm doing a load test using jmeter and it runs without a issue. The problem I'm getting is when I try to run the same test on a different machine with a different server it doesn't work.
And I observed that html element id's are different on different servers with JSF.(Issue is form submissions are not working). Is there a way to overcome this issue with jmeter since I want to run the same test scripts on different servers.
The process of extracting dynamic values from previous response and adding them to next request is called correlation. JMeter provides variety of Pre Processors and Post Processors to allow modification of requests on-the-fly.
Example use case:
Send a GET request a JSP page which contains a number of inputs
Extract all the inputs names and populate values where required
Populate dynamic fields of next request with values extracted in point 2
Send a POST request
Point 1: No changes to your script required
Point 2:
Add XPath Extractor as a child of GET Request and populate it as follows:
Reference Name: INPUT
XPath Query: //input/#name | //input[#type='hidden']
This extractor will fetch all <input> HTML elements and store it to JMeter Variables as
INPUT_1=javax.faces.ViewState
INPUT_2=loginForm_SUBMIT
INPUT3=...
...
Add a Beanshell Pre Processor as a child of next request with the following code
import java.util.Iterator;
import java.util.Map;
Iterator iter = vars.getIterator();
while (iter.hasNext())
{
Map.Entry e = (Map.Entry)iter.next();
if (e.getValue() != null)
{
if (e.getKey().toString().startsWith("INPUT_") && e.getValue().toString().length() >0)
{
sampler.addArgument(e.getValue().toString(),"VALUE OF YOUR INPUT");
}
}
}
The code above will fetch all variables prefixed with INPUT_ and add it as parameters to your next request.
See How to use BeanShell: JMeter's favorite built-in component guide for more information on Beanshell scripting in Apache JMeter to see what else can be done using Beanshell scripting and using of JMeter objects exposed to Beanshell test elements.
Related
I have a Test plan with several thread groups that write summary report results in the same csv file hosted in a server, this works fine using a networkdrive (z:) and changing jmeter.properties -> resultcollector.action_if_file_exists=APPEND.
Finally I have a tearDown Thread Group that insert the csv data into a sql server (the previous used networkdrive is hosted in this server in c:\jmeter\results.csv) and then it deletes the csv.
The case is when I run the test plan full I always have this error: "Cannot bulk load because the file "c:\jmeter\results.csv" could not be opened. Operating system error code 32"
The strange thing is that if I start the tearDown Thread Group alone it works fine, it makes the bulk insert in sql server and then it deletes de csv.
I started 2 days ago with Jmeter, so I'm sure I am misunderstanding something :S
Summary Report Config
JDBC Request
BeanShell PostProcessor that deletes csv
Test plan Structure
It happens because Summary Report (as well as other listeners) keep the file(s) open until test ends so you need to trigger this "close" event somehow.
Since JMeter 3.1 you're supposed to be using JSR223 Test Elements and Groovy language for scripting therefore replace this Beanshell PostProcessor with the JSR223 PostProcessor and use the following code:
import org.apache.jmeter.reporters.ResultCollector
import org.apache.jorphan.collections.SearchByClass
def engine = engine = ctx.getEngine()
def test = engine.getClass().getDeclaredField('test')
test.setAccessible(true)
def testPlanTree = test.get(engine)
SearchByClass<ResultCollector> listenerSearch = new SearchByClass<>(ResultCollector.class)
testPlanTree.traverse(listenerSearch)
Collection<ResultCollector> listeners = listenerSearch.getSearchResults()
listeners.each { listener ->
def files = listener.files
files.each { file ->
file.value.pw.close()
}
}
new File('z:/result.csv').delete()
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It
I am trying to do setproperty across multiple threads in the same threadgroup, the postprocessor set new variable using setproperty, so that It can be accessed across multiple threads.
In Beanshell preprocessor, I'm having below line of code.
${__setProperty("url", "youtube")};
Under thread Group I'm having Beanshell post processor, having below one line in postprocessor.
${__setProperty("url", "google")};
under thread group, I have Http Sampler, in hostname field I have given ${__property(url)}.com
The Aim is, when it executes first time, the URL will be google.com and when first threads complete than
the URL becomes youtube.com
But the setProperty only set google, and the second one in postprocessor was not working.
Refer the below Image for details, it shows how I created the element in Jmeter.
enter image description here
Note: This was just a sample use case, but I have complex example, but answering to this question will help me to add the logic in complex script.
Thanks
So is the goal that the very first thread to complete will change the URL for all subsequently created threads?
My understanding of the documentation is that you can't change the value of a property inside the thread-group:
Properties can be referenced in test plans - see Functions - read a property - but cannot be used for thread-specific values.
(see http://jmeter.apache.org/usermanual/test_plan.html#properties)
My assumption is that each thread in a thread-group gets a copy of the properties. If you change the value of the property inside the thread group, then you are actually changing the copy for that particular thread. Since you are changing it in the post-processor, the thread is very likely just about to be disposed, resulting in your change being lost. After disposal a new thread is created but with the original value of the property.
So what you need to do is figure out how to change the value outside of the thread-group.
I have done something similar in my own tests whereby I am changing the value of a property in the middle of the test, and the value is picked up immediately by all of the active thread-groups, resulting in each new thread created from that point forward getting the new value. I am doing this by using the Beanshell Server: https://jmeter.apache.org/usermanual/best-practices.html#beanshell_server
In my specific case I use jenkins job that calls a shell-script which connects to the beanshell-service running on the local-host:
java -jar ${jmeter_home}/apache-jmeter-5.0/lib/bshclient.jar localhost 9000 ${test_plan_home}/update_Prop.bsh "${property}" "${value}"
where my update_prop.bash file is simply:
import org.apache.jmeter.util.JMeterUtils;
JMeterUtils.getJMeterProperties().setProperty(args[0],args[1]);
You would not need to use Jenkins or anything like that, though - if you setup your JMeter Process to include the Beanshell-server (see the link above) then you can simply replace the code in your post-processor:
${__setProperty("url", "google")};
with the code to connect to the beanshell server and execute that command there instead:
exec("./updateprop.bash url google");
JMeter properties are global therefore once you set the property it is available for all threads
Each JMeter thread (virtual user) executes Samplers. Pre and Post processors are obeying JMeter Scoping Rules Looking into your test plan the execution order is following:
Beanshell PreProcessor
HTTP Request Sampler
Beanshell PostProcessor
therefore HTTP Request sampler will never hit youtube (unless you run into a race condition due to concurrency) because PreProcessor will set the URL back to google
It is recommended to use JSR223 Test Elements and Groovy language for scripting since JMeter 3.1
It is NOT recommended to inline JMeter Functions and/or variables into scripts, you need to either use "Parameters" section or go for code-based equivalents instead so you need to replace this line:
${__setProperty("url", "youtube")};
with this one:
props.put("url", "youtube");
I'm configuring some requests programmatically in my test cases, I can set headers, custom properties, teardown scripts, etc. however I can't find how to set a standard json body for my put requests.
Is there any possibility from the restMethod class ?
So far I end up getting the method used :
restService = testRunner.testCase.testSuite.project.getInterfaceAt(0)
resource = restService.getOperationByName(resource_name)
request = resource.getRequestAt(0)
httpMethod = request.getMethod()
if (httpMethod.toString().equals("PUT"))
but then I'm stuck trying to find how to set a standard body for my PUT requests.
I try with the getRequestParts() method but it didn't give me what I expected ...
can anyone help, please
thank you
Alexandre
I’ve managed this. I had a tests of tests where I wanted to squirt the content of interest into the “bare bones” request. Idea being that I can wrap this in a data driven test. Then, for each row in my data spreadsheet I pull in the request body for my test. At first I simply pulled the request from a data source value in my spreadsheet, but this became unmanageable in my spreadsheet.
So, another tactic. In my test data sheet (data source) I stored the file name that contains the payload I want to squirt in.
In the test itself, I put in a groovy step immediately before the the step I want to push the payload into.
The groovy script uses the data source to firstly get the file name containing the payload, I then read the contents of the file.
In the step I want to push the data into, I just use a get from data, e.g. {groovyStep#result}.
If this doesn’t completely make sense, let me know and I’ll update with screenshot when I have access to SoapUi.
My use case is that I want to do a bulk update of request bodies in multiple SoapUI projects.
Example of request body.
{
"name": "${#TestSuite#NameProperty}"
"id": "${#TestSuite#IdProperty}"
}
I want to expand the property ${#TestSuite#NameProperty} through Groovy, and get the value stored at TestSuite level then modify it as necessary.
Suppose I have 50 test steps in my test case and I want to expand the request for each one from Groovy script. To expand a specific test steps, I would pass the test Steps's name. For example:
expandedProperty = context.expand('${testStep1#Request}')
But, how can I achieve the same, if I wanted to iterate over all 50 test steps? I tried to used a nested parameter inside the context.expand expression, but it did not work. For Example:
currentTestStepName = "TestStep1"
expandedProperty = context.expand('${${currentTestStepName}#Request}')
This only returned me the expanded request from the test step right above it (where I am running the groovy script from) rather than the "TestStep1" step. ( Which is madness!)
Also, context.expand only seems to work while executing via Groovy script from the SoapUI workspace project. Is there and other way, or method similar to context.expand which can expand the properties like "${#TestSuite#NameProperty}" during headless execution? Eg: A groovy compiled jar file imported in SoapUI.
Thanks for any help in advance!
You can use context.expand('${${currentTestStepName}#Request}') way to get it.
There are other approaches as well, which does not use context.expand.
In order to get single test step request of any given test step:
Here user passes step name to the variable stepName.
log.info context.testCase.testSteps[stepName].getPropertyValue('Request')
If you want to get all the requests of the test case, here is the simple way using the below script.
/**
* This script loops thru the tests steps of SOAP Request steps,
* Adds the step name, and request to a map.
* So, that one can query the map to get the request using step name any time later.
*/
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
def requestsMap = [:]
context.testCase.testStepList.each { step ->
log.info "Looking into soap request step: ${step.name}"
if (step instanceof WsdlTestRequestStep) {
log.info "Found a request step of required type "
requestsMap[step.name] = context.expand(step.getPropertyValue('Request'))
}
}
log.info requestsMap['TestStep1']
Update :
If the step that you are interested is REST step, use below condition instead of WsdlTestRequestStep in the above.
if (step instanceof com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep) { //do the stuff }
I am trying to do the following in SOAPUI:
Read a response and extract a node from it
Insert the node into another request
Generate some xml in a Groovy script and store in a TestCase property
Insert the generated xml from the property as a child node to the node inserted in Step 2.
For 1 and 2: The structure of the response is something like
<A><B>bb</B><C>cc</C><D>dd</D></A>
I extract it via a Property Transfer step using //A to identify the beginning of the node, and passing the node with its children to the request in the next test step. Until this, the node in the request has no content. This works.
For 3 I generate something like
<E>ee</E>
The goal after step 4 is a request structure looking like this:
<A><E>ee</E><B>bb</B><C>cc</C><D>dd</D></A>
A solution using
${#TestCase#new_xml}
to insert the node does not work because there is no way to place the property where the E node should be (as far as I know).
I tried inserting the E node via another Property Transfer test step - the value of the property gets inserted in the request as child to the A node (same way the A node was copied from the response to the next request in Step 2). The result is this:
<A><![CDATA[<E>ee</E>]]<<B>bb</B><C>cc</C><D>dd</D></A>
I would like to know:
How to insert the E node as a child node to the A node while avoiding CDATA (or removing the CDATA subsequently).
Why the xml is passed without CDATA in Step 2 which also uses the SOAPUI Property Transfer Step, but not in Step 4.
Any tips appreciated!
For 1 & 2, you can use just a simple property expansion.
Let say your Response looks like:
<AAA>
<BBB/>
<CCC/>
<BBB/>
<BBB/>
<DDD>
<BBB/>
</DDD>
<CCC/>
</AAA>
And let say you want to transfer the entire node DDD, including the children. In your next request you would use ${<TestStep_name>#Response//*:DDD}. Note the *: means "any namespace", since in a real SOAP Response you will probably have some kind of namespace.
For 3:
// Generate some xml in a Groovy script
def xml = '<AAA><BBB/><CCC/><BBB/><BBB/><DDD><BBB/></DDD><CCC/></AAA>'
// store in a TestCase property
testRunner.testCase.setPropertyValue('my_property', xml)
If you want to get more fancy, you could use one of the many Java XML libraries, some of which are packaged with SoapUI. Here is one possibility.
For 4, you would again use property expansion: ${#TestCase#my_property}