Removing the property values from all test cases of a test suite in SoapUI? - groovy

I have 108 test cases in a test suite.
In each test cases, it has certain properties starts with r_ (means it is a return variable from other test case). I want to remove all the property values which starts with r_.
I can do this by TearDown Script in each test case. But, it takes lot of time.
Is it possible from doing the same from Suite level TearDown Script ?

Yes, it is possible.
Below is the suite level TearDown Script.
//Define the pattern of property names which you want to clear the values
def pattern = 'r_'
//Loop thru each case of the suite and find those matching properties and clear them
testSuite.testCaseList.each { kase ->
def props = kase.propertyNames.findAll { it.startsWith(pattern) }
def msg = props ?: 'None'
log.info "Matching properties for ${kase.name} test are : ${msg}"
props?.each { prop -> kase.setPropertyValue(prop, '')}
}

Related

Access test case property from test suite tear down script

I am trying to access the test case property from test suite tear down script.
i am not able to use test runner properties.
def testSuiteProperty = testRunner.testCase.testSuite.getPropertyValue( "MyProp" )
Need to access the test case property using test case name.
It will be very helpful if some one can answer it.
To access the test Suite property, it is simply a case of this in your tear down script....
def someProp = context.expand( '${#TestSuite#someProp}' )
Now, I use the Pro version and I don't know what you're using, so I'm not sure if the next part of my answer will help.
In Setup Script, Tear Down script, Script assertions, you can 'right-click' in the code window where you type your script and there is a 'Get Data' menu item int he context menu. This allows you to select a piece of data of interest. In fact, the line of code above was generate by using the 'Get Data' context menu option.
To access a custom property for a given test case within your suite tear-down script, you need to do this...
def testCase = testSuite.testCaseList.find { p -> p.name == 'TestCase 2' }
def testProp = testCase.getProperty('testCaseProp');
log.info(testProp.value);
The syntax you are using is not correct
Try using this
def testCs = testRunner.testCase.testSuite.project.testSuites["name of testsuite"].getTestCaseByName(name)
def tcprop = testCs.getPropertyValue("NameOftestCaseProp")
We are first getting refernce of the test case and then accessing its property
or below should also work
def testcaseProp= testRunner.testCase.testSuite.project.testSuites["name of testsuite"].getTestCaseByName(name).getPropertyValue("name of property)
try whichever looks simple to you, though both are same

SoapUI & Groovy - How to get properties from different TestCases using Run testCase

Sorry in advance. I am sure this is not a new question but I swear I've been looking for days and have tried several solutions but no one fits exactly what I need. I hope you guys can help me...
My problem:
I have a main script which sends bash commands to our server:
TestSuite: Tools;
TestCase: sendBashCommands;
TestStep: groovycript;
This test script is called by several test cases using "Run testCase". Each test case have a different bash command:
TestSuite: ServerInfo
TestCase: getServerVersion
Property: BashCommand="cat smt | grep Version"
TestStep: Run sendBashCommands
TestCase: getServerMessage
Property: BashCommand="cat smt | grep Message"
TestStep: Run sendBashCommands
...
On my sendBashCommands.groovyScript I have already tried the following:
//def bashCmd= context.expand( '${#BashCommand}' );
//it returns empty;
//def bashCmd= testRunner.testCase.getPropertyValue( "BashCommand" );
//it returns null;
//def bashCmd= context.getTestCase().getPropertyValue( "BashCommand" );
//it returns null;
def bashCmd = context.expand('${#TestCase#BashCommand}');
//it also returns empty;
Currently I use a solution which works with project properties but what I actually need is working with these properties on the level of the test case which is calling the sendBashCommand script. Is that possible? How could I do it?
I think you are doing it for maintenance purpose...
As per your approach, the result has to come as null or empty. Because your groovyscript cannot get the properties of other testcases directly. If you call a getProperty() Method directly, then it will refer to the current testStep's property. So the following approach could help you.
put the following code in your individual test cases, "getServerVersion" etc.
def currentProject = testRunner.testCase.testSuite.project
// the following is to store the names of the test suite and the test cases from which you want to call your main script
currentProject.setPropertyValue("TestSuiteName",testRunner.testCase.getTestSuite().getLabel().toString())
currentProject.setPropertyValue("TestCaseName", testRunner.getTestCase().getLabel().toString())
// call sendBashCommands here -> run sendBashCommands
put this code in your main groovy script (sendBashCommands.groovyscript)
def currentProject = testRunner.testCase.testSuite.project
def callingTestCase = currentProject.testSuites[currentProject.getPropertyValue("TestSuiteName")].testCases[currentProject.getPropertyValue("TestCaseName")]
def bashCmd = callingTestCase.getPropertyValue( "BashCommand" )
// to verify
log.info bashCmd
The project is common to all the test suites, so you have to use project property in any case, i.e., for your requirement :)
Enjoy :)

how to use testrunner.fail in groovy class for soapui

I am trying to fail the test case if string values are not same.I have created a class and a method to compare the string values.
public class test1 {
public String onetwo(str1,str2)
{
def first = str1
def second=str2
if (first==second)
{
return "Strings are same"
}
else
{
testrunner.fail("String Values are not same")
}
}
public String fail(reason)
{
return "implementation of method1"+reason
}
}
def objone =new test1()
def result = objone.onetwo('Soapui','Soapui')
def result1 = objone.onetwo('Soapui','SoapuiPro')
while executing it i am getting below message for last line of above code
ERROR:groovy.lang.MissingPropertyException: No such property: testrunner for class: test1
Please suggest how to use testrunner.fail or any other way to fail the test case if strings are not same.
Thank You
It can't find SoapUI's testrunner because you're accessing it inside your own class. (Note that the error message is trying to find test1.testrunner, which of course does not exist.) If you accessed testrunner from the top level of the script (where you define your variables) it should work.
If you still want to have a reusable class/method, an easy fix would be to have it return a boolean or an error message, and then you call testrunner.fail if your method returns false/error. Something like this (although a boolean return might make for cleaner code):
public class test1 {
public String onetwo(str1,str2)
{
def first = str1
def second=str2
if (first==second)
{
return "Strings are same"
}
else
{
return "String Values are not same"
}
}
...
}
def objone =new test1()
def result = objone.onetwo('Soapui','Soapui')
def result1 = objone.onetwo('Soapui','SoapuiPro')
if (result != "Strings are same")
{
testrunner.fail(result)
}
...
This thread from another site also describes a much more complex solution of making reusable Groovy libraries for SoapUI.
If two strings are to be compared in groovy script test step, then it is not required to write a class, instead can be achieved with below statement.
Matching Samples - note that nothing happens on successful assertion
String compare and fail if not equal
assert 'Soapui' == 'Soapui', "Actual and expected does not match"
Another example - with boolen
def result = true;assert result, "Result is false"
Non-Matching example - test fails on failure
Strings not matching, and shows error message
assert 'Soapui' == 'SoapuiPro', "Actual and expected does not match"
Another example with non zero test
def number=0;assert number, "Number is zero"
If you need only example of the class and like to access testRunner object, then we need pass it either to the class or to the method where testRunner is needed. Otherwise, other class do not know about the objects that are available to groovy script.
Here is some more information on the objects availability at various level of test case hierarchy.
When soapUI is started, it initializes certain variables and are available at Project, Suite, Test case, Setup Script, Teardown script etc., If you open the script editor you would see the objects available there.
For instance, groovy script test step has log, context, testRunner, testCase objects. However, if some one creates a class with in Groovy Script test step, those objects are not available with in that user defined class.

Test Groovy class that uses System.console()

I have a groovy script that asks some questions from the user via a java.io.console object using the readline method. In addition, I use it to ask for a password (for setting up HTTPS). How might I use Spock to Unit Test this code? Currently it complains that the object is a Java final object and can not be tested. Obviously, I'm not the first one trying this, so thought I would ask.
A sketch of the code would look something like:
class MyClass {
def cons
MyClass() {
cons = System.console()
}
def getInput = { prompt, defValue ->
def input = (cons.readLine(prompt).trim()?:defValue)?.toString()
def inputTest = input?.toLowerCase()
input
}
}
I would like Unit Tests to test that some mock response can be returned and that the default value can be returned. Note: this is simplified so I can figure out how to do the Unit Tests, there is more code in the getInput method that needs to be tested too, but once I clear this hurdle that should be no problem.
EDITED PER ANSWER BY akhikhl
Following the suggestion, I made a simple interface:
interface TestConsole {
String readLine(String fmt, Object ... args)
String readLine()
char[] readPassword(String fmt, Object ... args)
char[] readPassword()
}
Then I tried a test like this:
def "Verify get input method mocking works"() {
def consoleMock = GroovyMock(TestConsole)
1 * consoleMock.readLine(_) >> 'validResponse'
inputMethods = new MyClass()
inputMethods.cons = consoleMock
when:
def testResult = inputMethods.getInput('testPrompt', 'testDefaultValue')
then:
testResult == 'validResponse'
}
I opted to not alter the constructor as I don't like having to alter my actual code just to test it. Fortunately, Groovy let me define the console with just a 'def' so what I did worked fine.
The problem is that the above does not work!!! I can't resist - this is NOT LOGICAL! Spock gets 'Lost' in GroovyMockMetaClass somewhere. If I change one line in the code and one line in the test it works.
Code change:
From:
def input = (cons.readLine(prompt).trim()?:defValue)?.toString()
To: (add the null param)
def input = (cons.readLine(prompt, null).trim()?:defValue)?.toString()
Test change:
From:
1 * consoleMock.readLine(_) >> 'validResponse'
To: (again, add a null param)
1 * consoleMock.readLine(_, null) >> 'validResponse'
Then the test finally works. Is this a bug in Spock or am I just out in left field? I don't mind needing to do whatever might be required in the test harness, but having to modify the code to make this work is really, really bad.
You are right: since Console class is final, it could not be extended. So, the solution should go in another direction:
Create new class MockConsole, not inherited from Console, but having the same methods.
Change the constructor of MyClass this way:
MyClass(cons = null) {
this.cons = cons ?: System.console()
}
Instantiate MockConsole in spock test and pass it to MyClass constructor.
update-201312272156
I played with spock a little bit. The problem with mocking "readLine(String fmt, Object ... args)" seems to be specific to varargs (or to last arg being a list, which is the same to groovy). I managed to reduce a problem to the following scenario:
Define an interface:
interface IConsole {
String readLine(String fmt, Object ... args)
}
Define test:
class TestInputMethods extends Specification {
def 'test console input'() {
setup:
def consoleMock = GroovyMock(IConsole)
1 * consoleMock.readLine(_) >> 'validResponse'
when:
// here we get exception "wrong number of arguments":
def testResult = consoleMock.readLine('testPrompt')
then:
testResult == 'validResponse'
}
}
this variant of test fails with exception "wrong number of arguments". Particularly, spock thinks that readLine accepts 2 arguments and ignores the fact that second argument is vararg. Proof: if we remove "Object ... args" from IConsole.readLine, the test completes successfully.
Here is Workaround for this (hopefully temporary) problem: change the call to readLine to:
def testResult = consoleMock.readLine('testPrompt', [] as Object[])
then test completes successfully.
I also tried the same code against spock 1.0-groovy-2.0-SNAPSHOT - the problem is the same.
update-201312280030
The problem with varargs is solved! Many thanks to #charlesg, who answered my related question at: Spock: mock a method with varargs
The solution is the following: replace GroovyMock with Mock, then varargs are properly interpreted.

Clone TestStep from a Test Case to another Test Case using groovy

I use groovy script in my test suite to fill gaps in Automation. Here I need to clone a Property from one Test case to another Test Case. For Example.. Clone the Property test step from TestCase1 to TestCase2, In order to get values from that property.
I tried to get values in the property from one TC to another, But SOAPUI will not allow to do that action. we can't transfer a property value from one TC to another TC. So I go for cloning the Test step using groovy.
Your help is much appreciated.. Awaiting response from anyone..
Thanks,
Madhan
You can run TestCase2 from TestCase1 using test step "Run TestCase". Create properties that you need directly in TestCase2 so you can set them by "Property transfer" test step in TestCase1. More information about run test case here and about property transfer here.
Another way is to set properties and run TestCase programmatically. Something like this:
// get properties from testCase, testSuite or project if you need
def testCaseProperty = testRunner.testCase.getPropertyValue( "MyProp" )
def testSuiteProperty = testRunner.testCase.testSuite.getPropertyValue( "MyProp" )
def projectProperty = testRunner.testCase.testSuite.project.getPropertyValue( "MyProp" )
def globalProperty = com.eviware.soapui.SoapUI.globalProperties.getPropertyValue( "MyProp" )
//get test case from other project or from the same one
project = testRunner.getTestCase().getTestSuite().getProject().getWorkspace().getProjectByName(project_name)
testSuite = project.getTestSuiteByName(suite_name);
testCase = testSuite.getTestCaseByName(testcase_name);
//set properties if you need
testRunner.testCase.setPropertyValue(property_name, property_value);
testRunner.testCase.setPropertyValue(another_property_name, another_property_value);
// run test case
runner = testCase.run(new com.eviware.soapui.support.types.StringToObjectMap(), false);
The following example copies all of the properties from a test suite to the project that the test suite belongs in.
A similar mechanism could be used for test case properties, etc.
testSuite.getProperties().each {
testSuite.getProject().setPropertyValue(it.getKey(), testSuite.getPropertyValue(it.getKey()))
}
To copy from one test case to another (I will leave defining the test cases)
def sourceTestCase = youdefinethis
def destTestCase = youdefinethis
sourceTestCase.getProperties().each {
destTestCase.setPropertyValue(it.getKey(), sourceTestCase.getPropertyValue(it.getKey())
}

Resources