Forum Discussion
Looks like I was trying to solve the issue in a wrong manner. To solve the issue, instead of setting the 'token' property at Test Suite level, I set it at Test Case level in my groovy script.
Also after setting the property and running the test case once, I could see the 'token0' variable in the "run test case" properties dialog box (in the "values to return" section).
I simply checked this variable (so that it is returned to caller) and used "token0" variable in my source test case's request. Every thread in my source test case got different value for 'token0' and the load test was able to run successfully with multiple threads.
Unfortunately my above reply solved only half the issue. I am able to return a distinct value from the called test case to the caller in each thread.
However, my called test case is still considering context.ThreadIndex value as 0 and I am unable to use context.ThreadIndex to pickup a distinct variable for each thread in the called test case itself.
So the below request in the called test case is always using username0 and password0 variables from Project level instead of each thread using username1/password1, username2/password2 and so on from the Project level.
<myrequest><user>${=context.testCase.testSuite.project.getPropertyValue("username"+context.ThreadIndex)}</user><password>${=context.testCase.testSuite.project.getPropertyValue("password"+context.ThreadIndex)}</password></myrequest>
I also tried checking the "copy LoadTest related properties in the target context" option in the run test case step options dialog.
Any tips? Is it possible to pass arguments to called test case so that each caller thread instance can pass distinct value?
- amitst7 years agoOccasional Contributor
The above issue is solved after I called the test case through Groovy script and passing a new context to it while running. Similarly returning the context from the run test case and using properties set in the run test case back in the parent test case.
The groovy step looks like below (that calls Login test case).
import com.eviware.soapui.support.types.StringToObjectMap
// get test suite
def myTestSuite = testRunner.testCase.testSuite.project.getTestSuiteByName("TestSuite 1")
// get your test case
def myTestCase = myTestSuite.getTestCaseByName("Login")
// set the user and password properties in the context
context.setProperty("username", context.testCase.testSuite.project.getPropertyValue("username" + context.ThreadIndex))
context.setProperty("password", context.testCase.testSuite.project.getPropertyValue("password" + context.ThreadIndex))
// run the testCase passing the context
def contextMap = new StringToObjectMap( context )
def calledTestRun = myTestCase.run(contextMap,false);def myContext = calledTestRun.getRunContext()
token = myContext.testCase.getPropertyValue("token")
context.setProperty("token", token)
The login test case (called test case) used ${#username} and ${#password} variables in its request to use distinct login credential values for each thread.
Similarly the groovy script inside the login test case set a 'token' property inside context.testCase.setPropertyValue(). This will be extracted by caller by getting the context.
During the load test I have observed that in 1 in 15 times, I saw 2 threads overwriting each other's token (around 3-4 invalid token errors after say 50 successful logins).
Can you please let me know if getRunContext() call is not thread-safe after running the test case?
- JHunt7 years agoCommunity Hero
Where you have:
myContext.testCase.setPropertyValue(...)
This means:
myContext.getTestCase().setPropertyValue(...)
and getTestCase() returns the actual test case itself, i.e. the object that you are setting the property on is NOT unique to your run context.
(edited: I had some incorrect advice below here)
- JHunt7 years agoCommunity Hero
Also I'm not sure what this is supposed to do:
def contextMap = new StringToObjectMap( context ) def calledTestRun = myTestCase.run(contextMap,false); def myContext = calledTestRun.getRunContext()
I would have thought that this is just creating two references to the same object:
assert contextMap.is(myContext)
Isn't it?