I am using the free (non-PRO) SoapUI 5.0 and I have a list of properties in a Test Suite.
I then have a number of Test Steps, each one having the same name as a Test Suite property.
I'm trying to write Groovy script in a Test Step property to retrieve the value of the Test Suite property with the same name.
For example:
Test Suite has a property colour_red with the value 12345.
Within the Test Suite is a Test Case, with a Test Step also called colour_red.
Within the colour_red Test Step is a property "info".
I'm trying to get the property value for "info" to be the Test Suite
property colour_red value of 12345.
What I have so far in the "info" property value:
${=new GroovyShell().evaluate(testRunner.testCase.testSuite.project.getPropertyValue(context.getCurrentStep().getLabel()))}
I'm not sure if I need the new GroovyShell().evaluate bit, but without that it still doesn't work. I cannot tell exactly what is being picked up but it is not the value of the Test Suite property with the same name.
From what I can see the script should retrieve the current Test Step name (colour_red) and then look for a property called that in the Test Suite.
My reason for doing this is that I have data in the Test Suite property values which needs to be shared between numerous Test Cases (all with many Test Steps).
Without the PRO version I am struggling but I think with Groovy there should be a way to do this.
Any help appreciated, thanks.
I think researching property expansion will help you.
http://www.soapui.org/Scripting-Properties/property-expansion.html
To get you going...
You can easily reference property values using these dynamic references:
Put a reference like ${#TestSuite#colour_red} as the property value of "info".
Now the info property value is dynamicaly set to whatever the TestSuite's colour_red property value is.
I think this does what you want:
def myStep = context.currentStep.name
def myValue = context.expand( '${#Project#' + myStep + '}' )
testRunner.testCase.setPropertyValue("info", myValue)
I made it a little more verbose than it needs to be. I do not think that -Pro will help you, unless I misunderstood what you need.
Related
I'd like to enable a test if a certain tag is "included", i.e. passed with option --include-tag of the ConsoleLauncher or useJUnitPlatform.includeTags property in Gradle. Is there any API to retrieve the value of this option in the context of test class or method?
I tried the script-based condition #EnabledIf like this:
#EnabledIf("'true' == systemProperty.get('itest.backendSystemPresent') || junitTags.contains('BackendSystemIT') == true")
But junitTags contains the #Tag annotations of the element in question, not the tags included at runtime.
Reading your question again, my answer is "No". You can't use junitTags to achieve your goals. And no, there's no such API at the moment. You would need something like:
#EnabledIf("'true' == evaluateTagExpression('BackendSystemIT') || ...)
Because you need to take care of tag expression here as well: https://junit.org/junit5/docs/current/user-guide/#running-tests-tag-expressions
But, tags are evaluated earlier in the process. Your condition will not get a chance to be executed when the test was already excluded by tag evaluation. So, I guess, you'll have to stick with the single system property switch to control the enabled state of the test method.
Btw. we are improving the tag expression language with any() and none() tokens, soon. https://github.com/junit-team/junit5/issues/1679
Possible solution:
Annotate your test with #Tag("BackendSystemIT")
Before running your tests, check for itest.backendSystemPresent system property and if it is set, pass a --include-tag "BackendSystemIT" to the test run.
Let Jupiter do the job of evaluating tag expressions
Is there any API to retrieve the value (of this option) of all tags that are attached directly or inherited in the context of test class or method?
Yes. Declare and use a org.junit.jupiter.api.TestInfo parameter in your test method.
#Test
#DisplayName("TEST 1")
#Tag("my-tag")
void test1(TestInfo testInfo) {
assertEquals("TEST 1", testInfo.getDisplayName());
assertTrue(testInfo.getTags().contains("my-tag"));
}
For details see https://junit.org/junit5/docs/current/user-guide/#writing-tests-dependency-injection
But junitTags contains the #Tag annotations of the element in question, not the tags included at runtime.
This is the expected behaviour -- the platform (here: console launcher) already applied the filter passed via --include-tag and other configuration parameters. In short: there's no need to manually check for tags in standard Jupiter tests. If there's problem with the built-in filtering, please create an issue here: https://github.com/junit-team/junit5/issues/new/choose
I need to automate two applications in which the navigation almost looks similar but the locators (xpath,id etc.,) are difderent.So,I have created a project with TestNg in eclipse and able to run one testcase for one application.But to maintain code reusability, I wanted to parameterize the locators( eg: in one application it is "//div[contains(text(),'abc')]" whereas in the other application it is "//div[contains(text(),'def')].Searched in google but nothing is helpful.
Please let me know your comments. Am okay to start a new framework where the locators can be parameterised.
Define all your locators in application like Excel,
The structure of Excel should be in a way that, the first row refers to key, the Second row refers to the locators for "application A", the third row refers to the locators for application B corresponding to the key. The structure of excel should be as below
Excel reader class should be row iterator, the first row serves as Key and corresponding row serves as values. first iteration row 1 and row 2 values are placed in key and value mapping in a hashmap and the execution will be on Application A.
I would suggest you to keep different packages for test and page(locators).
In the locator you can create java classes for different kind of pages that you have in your application, where you can keep our locators as per the pages(java class) and can create methods where you can parameterize them for reusability.
In the test class you'll have to just create objects of the pages(java class) so that you can use the methods
Hope this helps!
In your specific case you can try to write a utility function like this:
public static String setlocator(String param){
String test = "//div[contains(text(),'" +param+"')]";
return test;
}
and call that function in your any application to get the locator.
SoapUI provides a common syntax to dynamically insert properties in SOAP Request. In their documentation they explain how to access different properties depends on property scope:
#Project# - references a Project property
#TestSuite# - references a TestSuite property in the containing TestSuite
#TestCase# - references a TestCase property in the containing TestCase
#MockService# - references a MockService property in the containing MockService
#Global# - references a global property (optional)
#System# - references a system property
#Env# - references a environment variable
[TestStep name]# - references a TestStep property within the current TestCase
My problem is I want to access the name of the current testStep however documentation says that to access TestStep properties you need the name... There is another way to do so? like for example #TestCase#TestStep#Name. I know how to achieve this with groovy script but in my case I want to put the property directly on SOAP Request.
Thanks in advance
Finally I found the solution in the documentation, with '=' prefix it's possible to specify a groovy script and access to some context variables. In this context request variable is available and also its name property, so It's possible access to the current TestStep name with:
${=request.name}
Example below is grabbing the request from your TestCase and assigning a value to a specific element.
// get XMLHolder for request message def
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
// grabbing the specified request
def holder = groovyUtils.getXmlHolder("Specified#Request")
holder["//*:Password"] = 'password1';
For the example above you need to know the Xpath for your element.
Note, that this can be accomplished in several ways, but you specified doing in through groovy script. It can also be done through a #TestCase# property. Example:
<soapenv:Body>
<tns:AuthenticateUser>
<tns:Credentials>
<tns:IntegrationID>${IntegrationID}</tns:IntegrationID>
<tns:Username>${Username}</tns:Username>
<tns:Password>${Password}</tns:Password>
</tns:Credentials>
</tns:AuthenticateUser>
I have a SoapUI project which contains around 60 plus services. Each service requires some input which will be changed for every execution. So I have created certain Global Properties and assign some values to that properties.
I have to use these properties values in my SoapUI request ( i.e. JSON Format request ).
If it is groovy script means, I will use like this.
String HTiC_Username = com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils.globalProperties['HTiC_Username'].value;
But, how to get the value of the Global Property in the request?
Hope you understand my question. Please provide proper guidance.
Thanks
To dynamically "expand" (i.e. substitute) the value of a property into a test step, the following syntax is used: ${#scope#propertyName}
...where 'scope' refers to the level at which the property has been defined (e.g. Global, Project, TestSuite, TestCase).
So to expand a property named username defined as a Global property, for example, the following code can be used directly within a Request Test Step (e.g within a JSON body, or header value, etc):
${#Global#username}
To access the same property value within a Groovy Test Step, you can use the following syntax:
context.expand('${#scope#propertyName}')
...as in the following example:
context.expand('${#Global#username}')
What we did was the following:
created a test data file to store all the specific input data for the different services (testdata.properties)
Example content of testdata.properties:
Billing_customerID=1234567
OtherService_paymentid=12121212
....
create a SoupUi global parameter (File/Preferences/Global properties): testdata_filepath=C:\...
For specific services we added a Properties test step. You can specify the "Load from" field to our new global parameter: ${#Global#testdata_filepath} Now you can use the Load button to load parameters.
Finally you can reference the parameter in your xml in the following format: ${Properties#Billing_customerID}
Example content of a service with parameter:
...
<BillingCustomerIdentification>
<BillingCustomerID>${#Properties#Billing_customerID}</BillingCustomerID>
</BillingCustomerIdentification>
...
To set up your projects in this manner also helps to automate service tests eg. using Hudson (see my previous SO answer).
If it is too heavy and automation is not a target, you can simply use ${#Global#someinputvariable} format in your xml ;-)
I'm a Selenium n00b... it's clear how easy it is to run a test and verify a particular response, but how can I take a value from one response and use it in the next test?
an example might be a contact creation form...
type in name/email and click submit
response arrives with new ContactID
grab the ContactID that was returned and put it into "get" textbox and click "submit"
response arrives with contact details
verfy the name/email match the first set
how might I go about doing this in Selenium?
And now something completely different:
Now I understand when you say "test", you mean a single assertion within one test case. So you want to use a value returned from a request as input for another request in the same test case.
Assuming you use selenium ide: To do this, use one of the "store..." commands in selenium ide and store the value into a variable. The contactID can be found using a matching selector with the storeText command. For example:
command: storeText
target: selector for element containing contactId
value: contactId
Then, use variable substitution and the type command to insert that text somewhere else.
command: type
target: selector for target input box
value: ${contactId}
Hope this helps :)
(This answer is still correct I think if you interpret "test" as "test case". For another, totally different answer see below.)
You don't do this. Each test should be independent from all other tests. For your second test, just repeat the steps in the first test. This way, you can reproduce test success and failures in a reliable way.
If you have many tests which all start from a certain application state which requires many steps to reach, just write a private helper method to reach that state.
The alternative: All steps you describe can be put into a single test. There is no reason not to have several asserts in one test.