I have isolated all the request alone in One Test Suite. I need to collect each api call time Taken..
Every Functional Test Case will call Request Test Suite using Run Test Case option.
I have following code in the script assertion of each request.
def endpoint = messageExchange.getEndpoint()
uri = endpoint.replace("baseurl","")
log.info("Current URI: "+uri)
uri = "t_"+uri
def headers = messageExchange.getResponseHeaders()
bytes= headers["Content-Length"].get(0)
log.info("Number of Bytes: "+ bytes)
timeTaken = messageExchange.getTimeTaken().toString()
values = timeTaken + ";"+ bytes
context.testCase.setPropertyValue(uri, values)
I expected that the uri would be created as the key and timeTaken and bytes are values.
When run the request (from Request Test Suite) it creates the property.
But Functional Test Case calls this request from other Test suite it does not create such property.. How to resolve this? I see the work around run the each request and get the property created so that on next run it would be updated.. But the problem is when starting test suite I am deleting all the properties and values. So again it is a mess up.. Can someone let me know how to resolve this issue?
you can add a result to a csv file directly after execution like this:
new File('out.csv').append( "$uri; $timeTaken; $bytes\n" )
Related
I have two HTTP GET requests in Jmeter. The first one calls to a server and gets a CSV that holds some user data. Using a JSR223 Post processor, I am , mapping that data onto a JSON and assigning the values to three variables to be passed onto the second request. The script for doing that is below.
import org.apache.commons.io.IOUtils
import java.nio.charset.StandardCharsets
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def response = prev.getResponseDataAsString()
def lines = response.split('\n')
def userData = []
for (int i = 1; i < lines.length; i++) {
def line = lines[i]
def tokens = line.split(',')
userData << [login_type: tokens[0], username: tokens[1], password: tokens[2]]
}
def jsonString = JsonOutput.toJson(userData)
def jsonSlurper = new JsonSlurper()
def jsonMap = jsonSlurper.parseText(jsonString)
for (int i = 1; i <= Math.min(jsonMap.size(), Integer.parseInt("${__P(threads)}")); i++) {
if(i < jsonMap.size()){
vars.put("login_type" , jsonMap[Integer.parseInt("${__threadNum}")-1].login_type)
vars.put("username" , jsonMap[Integer.parseInt("${__threadNum}")-1].username)
vars.put("password" , jsonMap[Integer.parseInt("${__threadNum}")-1].password)
}
}
I pass these three variables in the next request body as {"login_type":"${login_type}","username":"${username}","password":"${password}"}
When running the script i'm getting the response as 400 for second request even though i can see the data is getting passed.
POST data:
{"login_type":"data","username":"data","password":"data"}
I tried the second request by manually giving the login data instead of the variables and it works.
{"login_type":"EMAIL","username":"username","password":"pass"}
The only difference i see on both attempts is in the request header where the Content-Length: 83 is shown for when manually sending data and Content-Length: 84 is shown for when passing the data from the groovy script. Though i don't think that's what causing the issue. Can anyone explain as to why this is happening and how to fix this.
I looked into the requests and the POST request body coming from the groovy script has a line break at the end.
{"login_type":"login_type","username":"username","password":"password
"}
Hence causing the request to throw a 400. How can i send the body data in one line?
Maybe there is some invisible character like whitespace or line break which is expected by your system under test and which you're not sending when you're populating variables in Groovy.
Use a sniffer tool like Wireshark or Fiddler to compare both requests byte by byte and amend your JMeter configuration or Groovy code to 100% match the "manual" request.
Also regarding your usage of JMeter Functions in the script, according to JSR223 Sampler documentation:
The JSR223 test elements have a feature (compilation) that can significantly increase performance. To benefit from this feature:
Use Script files instead of inlining them. This will make JMeter compile them if this feature is available on ScriptEngine and cache them.
Or Use Script Text and check Cache compiled script if available property.
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 replace:
${__P(threads)} with props.get('threads')
${__threadNum} with ctx.getThreadNum()
See Top 8 JMeter Java Classes You Should Be Using with Groovy for more information on what do these props and ctx guys mean.
I am able to use below code to replace blank value with null in http post request body
def body = sampler.getArguments().getArgument(0).getValue().replaceAll('""','null')
sampler.getArguments().removeAllArguments()
sampler.addNonEncodedArgument('', body,'')
sampler.setPostBodyRaw(true)
But, I get an error for multiple iterations.
javax.script.ScriptException: javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method getValue() on null object
I suspect the removeAllArguments call is affecting subsequent calls to the first line. If it works the first time and fails all subsequent calls then it's probably that. Try commenting that line out and see if it continues to happen:
def body = sampler.getArguments().getArgument(0).getValue().replaceAll('""','null')
sampler.getArguments().removeAllArguments() // I bet this line affects all invocations of the script.
sampler.addNonEncodedArgument('', body,'')
sampler.setPostBodyRaw(true)
Wouldn't that be easier to go for __strReplace() function instead (can be installed as a part of Custom JMeter Functions bundle using JMeter Plugins Manager)?
Whatever, if you like Groovy and copy-pasting the code from Internet without understanding what it's doing I think you need to amend "your" code to look like:
def data = new org.apache.jmeter.config.Arguments()
def body = new org.apache.jmeter.protocol.http.util.HTTPArgument('',sampler.getArguments().getArgument(0).getValue().replaceAll('""','null'),'',false)
data.addArgument(body)
sampler.setArguments(data)
Is there any way in which I can run a Property Transfer step from a groovy script? Both are in the same test case.
Test case contains the following test steps:
groovy script
soapUI request (GetAccountNumber)
property transfer step (transfers a response property from above to a request property in the below step)
soapUI request (DownloadURL)
I need to make sure that the flow is as follows:
Groovy runs and reads numbers from a file and passes them to GetAccountNumber.
GetAccountNumber runs with the passed values and generates a response.
This response is passed by the property transfer step to DownloadURL.
DownloadURL runs with this passed value and generates an output.
All I need to do is run the Property Transfer from the groovy because the other steps can be run from groovy.
It isn't running with the following code
def testStep_1 = testRunner.testCase.getTestStepByName("PropertyTransfer")
def tCase_1 = testRunner.testCase.testSuite.testCases["SubmitGenerateReport"]
def tStep_1 = tCase.testSteps["PropertyTransfer"]
tStep_1.run(testRunner, context)
Without more context I think that your problem is a simple typo, you get your testCase and assing to tCase_1:
def tCase_1 = testRunner.testCase.testSuite.testCases["SubmitGenerateReport"];
However then to get the tStep_1 you use tCase instead of tCase_1:
def tStep_1 = tCase.testSteps["PropertyTransfer"]; tStep_1.run(testRunner, context);
Additionally if the testStep you want to run from groovy are in the same testCase you're executing; you can run it simply using:
testRunner.runTestStepByName('some teststep name')
Which I think it's more convenient than get the testStep from the testCase and then run it.
Hope it helps,
Using Windows 7 with Soap 5.2.0 freeware.
I also asked about this in the Smart Bear community and was only given recommended posts to read. The posts didn’t relate to this problem.
I have a REST project that has one test suite with one test case containing two test steps. The first step is a groovy step with a groovy script that calls the second test step. The second test step is a REST GET request that sends a string to our API server and receives a response back in JSON format. The second test step has a script assertion that does "log.info Test Is Run", so I can see when the second test is run.
When the groovy script calls the second test step it reads the second test step’s JSON response in the groovy script like this:
def response = context.expand('${PingTest#Response}').toString() // read results
I can also use this for getting JSON response:
def response = testRunner.testCase.getTestStepByName(testStepForPing).getPropertyValue("response")
The project runs as expected when run through the Soap UI but when I run the project with test runner, the response from the groovy script call to get the JSON response is empty, using either of the methods shown above. When run from testrunner, I know the second test step is being called because I see the log.info result in the script log.
This is part of the DOS log that shows the second test step is running and it seems there are no errors for the second test step run.
SoapUI 5.2.0 TestCase Runner
12:09:01,612 INFO [WsdlProject] Loaded project from [file:/C:/LichPublic/_Soap/_EdPeterWorks/DemoPing.xml]
12:09:01,617 INFO [SoapUITestCaseRunner] Running SoapUI tests in project [demo-procurement-api]
12:09:01,619 INFO [SoapUITestCaseRunner] Running Project [demo-procurement-api], runType = SEQUENTIAL
12:09:01,628 INFO [SoapUITestCaseRunner] Running SoapUI testcase [PingTestCase]
12:09:01,633 INFO [SoapUITestCaseRunner] running step [GroovyScriptForPingtest]
12:09:01,932 INFO [WsdlProject] Loaded project from [file:/C:/LichPublic/_Soap/_EdPeterWorks/DemoPing.xml]
12:09:02,110 DEBUG [HttpClientSupport$SoapUIHttpClient] Attempt 1 to execute request
12:09:02,111 DEBUG [SoapUIMultiThreadedHttpConnectionManager$SoapUIDefaultClientConnection] Sending request: GET /SomeLocation/ABC/ping?echoText=PingOne HTTP/1.1
12:09:02,977 DEBUG [SoapUIMultiThreadedHttpConnectionManager$SoapUIDefaultClientConnection] Receiving response: HTTP/1.1 200
12:09:02,982 DEBUG [HttpClientSupport$SoapUIHttpClient] Connection can be kept alive indefinitely
12:09:03,061 INFO [log] **Test Is Run**
This is the testrunner call I use in DOS command line:
“C:\Program Files\SmartBear\SoapUI-5.2.0\bin\testrunner.bat" DemoPing.xml
When the groovy script is run through test runner I get the project using ProjectFactoryRegistry and WsdlProjectFactory. Any advice on why I can’t read JSON response when using testrunner would be appreciated.
I can provide more info/code if needed.
Thanks.
Please try the below script:
import groovy.json.JsonSlurper
//provide the correct rest test step name
def stepName='testStepForPing'
def step = context.testCase.getTestStepByName(stepName)
def response = new String(step.testRequest.messageExchange.response.responseContent)
log.info response
def json = new JsonSlurper().parseText(response)
Thank you Rao! Your suggestion worked when I used it as shown below. The DOS window showed the response text:
// setup stepName as variable for name of test step to run.
def stepName = "PingTest"
// use stepName to get the test step for calling the test step (testCase is a
string variable of the test case name).
def step = context.testCase.getTestStepByName(stepName)
// call the test step.
step.run(testRunner, context)
// show the results.
def response = new String(step.testRequest.messageExchange.response.responseContent)
log.info response // this response shows correctly in the DOS window
The json slurper also works. At your convenience, if you have any suggested links or books describing the technique(s) you used here please let me know of them.
Thanks.
I am calling a REST based service from SoapUI. I have created a load test for the service and the test works. I wrote the following code in my setup script for the load test.
log.info("This is from the setup script")
def request = context.expand('${#Request}')
log.info(request)
def response = context.expand('${#Response}')
log.info(response);
The only item I am getting in my log is the "This is from the setup script".
I also added the following lines of code in my Teardown script.
log.info("Teardown script")
def response = context.expand('${#Response}')
log.info(response);
I am not seeing the "Teardown script" text in the log. At this point I am a bit puzzled as to the behavior.
Load Test:
Test Suite
Test case options.
I have unchecked the Discard OK results test box.
What changes do I need to do to my scripts in order to log the requests and the responses?
When you create a setup and/or teardown script, remember those are run only once per run, not per test! What you intended is not going to work.
In your setup, since no tests have run yet, the context is going to be empty ... as you can see from your log message.
In your teardown, I suspect there is a bug in SoapUI and the log is not getting sent to the log tab. If you intentionally create an error (I used logg.info "Hello world!" - note the intentional double g), I still got a an error in the error log tab.