I am new to groovy script and soap UI. i added script assertion to a test step. how ever when i run the test case, script assertions are not running. i have to manually run it to verify my response is correct.
can anyone help me on this please?
My groovy script test assertion:
import groovy.json.JsonSlurper
//grab response
def response = messageExchange.response.responseContent
//Convert to JsonSluper to access data
def list = new JsonSlurper().parseText(response)
//check delegates are in one session per timeslot
for (i = 0; i < list.size(); i++) {
// find all items for this delegate in this timeslot
def itemsForThisDelegateInThisTimeslot = list.findAll {element -> element.delegateId == list[i].delegateId && element.agendaItemId== list[i].agendaItemId}
log.info(list[i].delegateId)
// there should not be more than 1
if(itemsForThisDelegateInThisTimeslot.size() > 1) {
log.info(list[i].delegateId + "Delegate already assigned to a workshop at same time");
//Assert fail in execution
throw new Error ('Fail')
}
}
Firstly, there are no assertions in this Script Assertion. Look up Groovy assert.
If you're 'asserting' that the script is Pass or Fail, you need something like...
assert (response.contains('Something from the response'));
or
assert (someBooleanVar == true);
If it passes, the step goes Green. If it fails, it goes Red.
IMHO, it looks you're throwing an exception when the step fails. I would not use an exception in this way. An exception is there to catch and report code issues. Not a test failure.
Regarding exceptions, look up Groovy Try and Catch.
As for this running (or not) when you run a test case. I suspect it is running, but as you're not asserting anything, you can't see the result.
Ever noticed the Script Log tab at the bottom of the screen? All of your log.info statements will be in here when the test step runs. I'd suggest clearing this log (right-click in the Script Log window...), and then running the test case again and have a look in the Script Log for some of your logging messages.
Related
I'm trying to get the Assertion results through an email.
There are several endpoints(requests) and associated assertions in my test plan.
Below is the Groovy code I'm using in JSR223 PreProcessor. In My SMTP Sampler, I've been using ${body} to get the results from the script.
But in email prints null when all the Assertions are passing and print exceptions when those are failing.
I need to get below through email.
Success message when there are all the assertions are passing
Fail message with the failure request name when they
import org.apache.jmeter.assertions.AssertionResult;
AssertionResult[] results = prev.getAssertionResults();
StringBuilder body = new StringBuilder();
for (AssertionResult result : results) {
body.append(result.getFailureMessage());
body.append(System.getProperty("line.separator"));
}
vars.put("body", body.toString());
JSR223 PreProcessor is being executed before each Sampler in its scope
prev stands for previous Sampler Result
Assuming above 2 points it is absolutely expected that when JSR223 PreProcessor is being executed before the first Sampler in your test the previous result doesn't exist yet, you just need to add another condition to check whether it is null or not.
import org.apache.jmeter.assertions.AssertionResult
if (prev != null) { // ensure that we have the previous sampler result
AssertionResult[] results = prev.getAssertionResults();
StringBuilder body = new StringBuilder();
for (AssertionResult result : results) {
body.append(result.getFailureMessage());
body.append(System.getProperty("line.separator"));
}
vars.put("body", body.toString());
}
If the soap request has a failure means Status != "HTTP/1.1 200 OK" , testCase should stop and no further steps should run
There is a way to do this in groovy, but i do not want an extra test step to be added in testcase
def headers = testRunner.testCase.getTestStepByName("RequestName").httpRequest.response.responseHeaders['#status#']
if (!headers.contains("HTTP/1.1 200 OK"))
{
testRunner.fail("" + headers + "Flow failed")
testRunner.fail("No futher testSteps will be run inside the current case")
}
Please note i cannot change below settings due to some other groovy code restriction
The reason for not changing above option i have a testcase where there are 10 steps. 1 is request and other 9 steps validate various things. So if i check the "Abort on error" option and step 3 fails. then none of the steps from 4 to 10 runs. So please provide a solution considering not using "abort" option
So could you please provide a solution for script assertion without ticking this option."Abort on error"
Since testRunner.fail is not available inside script assertion and also normal assertion (assert 0==1) does not stop testcase unless we tick the above setting. i am stuck with this limitations
You have access to testRunner through the context variable available in a script assertion, so why not something like:
def httpResponseHeader = messageExchange.responseHeaders
def headers = httpResponseHeader["#status#"]
log.info("Status: " + headers)
if (!headers.contains("HTTP/1.1 200 OK")) {
context.testRunner.fail("" + headers + "Flow failed")
context.testRunner.fail("No futher testSteps will be run inside the current case")
}
Thanks #craigcaulifield, your answer has helped me a lot.
Good to know that testRunner is available even in script assertion in a tricky way
Now using script assertion we can stop a testCase if request fails.
However when we run request alone not as part of testcase an error comes
cannot invoke method fail() on null object
This error comes because
context.testRunner.fail()
testRunner is only available during test Case execution and not individual testStep execution
So to overcome here is the code which can take care of both situation
def responseHeaders=messageExchange.responseHeaders
def status=responseHeaders["#status#"]
// Checking if status is successfully fetched i.e. Response is not empty
if(status!=null)
{
if(!status.contains("HTTP/1.1 200 OK"))
{
// context.testRunner is only available when the request is run as a part of testCase and not individually
if(context.testRunner!=null)
{
// marking the case fail so further steps are not run
context.testRunner.fail()
}
assert false, "Request did not returned successful status. Expected = [HTTP/1.1 200 OK] but Actual = " + status
}
}
else
{
if(context.testRunner!=null)
{
context.testRunner.fail()
}
assert false, "Request did not returned any response or empty response"
}
i have some projects in soapui.
i want to execute testsuites and testcases of these projects.
i tried with this groovy code:
//get test case from other project or from the same one
project = testRunner.getTestCase().getTestSuite().getProject().getWorkspace().getProjectByName("Project1")
testSuite = project.getTestSuiteByName("TestSuite 1 - Login");
testCase = testSuite.getTestCaseByName("TestCase 1-Login");
Thread.sleep(3000)
testSuite2 = project.getTestSuiteByName("TestSuite3 - Report");
testCase2 = testSuite.getTestCaseByName("TestCase1 - Report");
// run test case
runner = testCase.run(new com.eviware.soapui.support.types.StringToObjectMap(), false);
Thread.sleep(3000)
runner2 = testCase2.run(new com.eviware.soapui.support.types.StringToObjectMap(), false);
When i run this groovy code, i have the following error message:
java.lang.NullPointer.Exception
cannot invoke method run() on null object for the last line
runner2 = testCase2.run(new com.eviware.soapui.support.types.StringToObjectMap(), false);
If i remove the last line it's working well.
Any help please.
Thank you
I know this is super late to answer this question, but i will answer this so that it can help help seeking for help.
instead of Thread.sleep(3000), just use:
runner.waitUntilFinished()
Now it will wait until execution of step 1 get finished. Then it will start executing Step 2.
The only thing I can think of is that you're calling the wrong testcase on the step2, I tested the same with other test cases I have and it's happening the same If I put a wrong name for the test case I want to execute.
// TO RUN A TEST SUITEs ALL get APIs, getting testSuite handle from current //test_Case
// TO POST COMMENT I HAVE ADDED underscore char BELOW
// u need to import here
def my_TestSuite = testRunner.testCase.testSuite
log.info(my_TestSuite.name)
for (my_TestCase in my_TestSuite.get_TestCaseList())
{
for (testStep in myTestCase.get_TestStepList())
{
if( testStep instanceof WsdlTestRequestStep || testStep instanceof RestTestRequestStep ) {
def http_Verb = (testStep.getTestRequest().getMethod())
String apiType = http_Verb.toString()
if (apiType == "GET"){
log.info(myTestCase.name)
}
}
}
}
is there any way to read http log for specific test step?
In my http log there are several response-requests messages for current test step.
The following code gives me only first request/last response, but I need to take value from
second response.
log.info context.expand('${getHashValue#Request}')
log.info context.expand('${getHashValue#Response}')
Any ideas?
Thanks.
UPD:
Below code can get any kind of soap ui logs
def logArea = com.eviware.soapui.SoapUI.logMonitor.getLogArea( "http log" )
//error log can be replaced with jetty log, script log, SoapUI log, error log,memory log, wsrm log
if( logArea !=null )
{
def model = logArea.model
if( model.size > 0 )
for( c in 0..(model.size-1) )
{
def value= model.getElementAt(c).toString()
if(value.contains("ETag")) // here you can mention if you want to extract anything particular from the logs
{
log.info "value = " + value
}
}
}
this code can be even little modified to save soap ui logs in a file
credits :- https://webservice-testing.blogspot.in/2012/04/capture-soapui-logs-to-file.html
I am reading sample Hilo provided by MS, under ImageBrowserViewModel.cpp there is some code I am not understand:
// Observe the update after waiting the specified amount of time.
create_task([timeToWait]() {
assert(IsBackgroundThread());
::wait(timeToWait);
}).then([weakThis]() {
assert(IsMainThread());
auto vm = weakThis.Resolve<ImageBrowserViewModel>();
if (nullptr != vm)
{
vm->ObserveFileChange();
vm->m_hasFileUpdateTask = false;
}
}, task_continuation_context::use_current()).then(ObserveException<void>(m_exceptionPolicy));
The quest is app use IsBackgroundThread() & IsMainThread() to assert it should be correctly called under certain context. But for the ::wait(timeToWait) function call, there is no task_continuation_context defined to make sure it runs in background, I just wonder how does it make to work?? Thanks a lot!
The default for constructed tasks (as the first task is in your code snippet) is task_continuation_context::use_arbitrary(), so even though it is not specified this is what it will be. The task continuation lambda does assert this before calling ::wait (which would throw an exception if it attempted to run on the UI thread).