I have 50+ tests in my current SoapUI workspace. I need to add a new project level parameter on all of these tests. Is there a way I can do this using the groovy console within SoapUI?
For example :
testRunner.testCase.testSuite.project.setPropertyValue( "SuperMan",("SuperMan"));
I can run this to create a property within the current working project.
Is there a way I can create this under all projects on my current workspace?
Thanks in advance.
Yes, We can do this but it's little tricky.
Way to do this:
Create a empty generic project in soapui, Add empty testsuite, add Empty testcase
In test case Add a groovy script step
Now paste this groovy code
for(project in com.eviware.soapui.SoapUI.workspace.projectList) {
if(project.open && project.name != testRunner.testCase.testSuite.project.name){
project.setPropertyValue( "TestProperty","TestValue");
}
}
Run the groovy step, you will get property added at Project level.
Please mark this as correct response if this solve your problem.
Using your testRunner access you simply need one level more workspace. From here you can access projects map and iterate over each project adding the property:
testRunner.testCase.testSuite.project.workspace.projects.each{ key, proj ->
proj.setPropertyValue('superman','superman')
}
This code doesn't add the property on closed projects in workspace but not fails accessing it.
Alternatively as #Rao suggest on his comment it's possible to use default it object iterator and access the value instead of defining key, proj -> on each:
testRunner.testCase.testSuite.project.workspace.projects.each{
it.value.setPropertyValue('superman','superman')
}
I prefer the first approach for clarity.
Hope it helps,
Related
I am new in SoapUI and groovy scripting
I would like to create a repository of groovy scripts that can be reused at various test steps
I am using SoapUI Free version and following is the structure of my SoapUI Project
Project
|-TestSuite
| |-TestCase
| |-TestSteps
| |-LocalScript (Groovy TestStep to reuse library scripts)
| |-OtherTestStep (Run TestCase TestStep)
|-ScriptLibrary
|-TestCase
|-TestSteps
|-GroovyScriptStep1 (Contain a class for commonly used functions)
|-GroovyScriptStep2 (Contain another class for other functions)
Here is what I was able to do:
I was able to create a library using the sample mentioned in this post. Similar to example in the post, my code in test step (GroovyScriptStep1 as per above structure) of library was just reading some value from external file and is used in test step of other TestSuite (LocalScript step in above structure).
Here is the problem:
Now I want to create a new class and add a function to it which will need info from running class and simply print it. The difference here is that some values are generated in the test run and should be passed to library script inorder to process/print etc.
To make my question more clear following is the code snippet
I will be using a simple scenario here
Sample objective: Want to be able to print all the assertions and status (since this will be used in all the test cases I want to create a library)
Code for same when not using library will be as under(this can go as groovy script step)
def obj = context.testCase.getTestStepByName("Request 1");
def assertions = obj.getAssertionList()
//Loop on assertions
assertions.each{
log.info(it.name + ' --> ' + it.status)
Code something similar in Library TestSuite's Test case step
context.setProperty("Assertions", new Assertions());
class Assertions{
def printAssertion(def someArgumentToGetAssertionlistforTestStepinAnotherTestSuite){
def obj = ????
def assertions = obj.getAssertionList()
//Loop on assertions
assertions.each{
log.info(it.name + ' --> ' + it.status)
}
}
}
Code from where I want to call this method (LocalScript as per above project structure)
scripts = testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"];
scripts.testCases["Scripts"].testSteps["Assertions"].run(testRunner, context);
context.Assertions.printAssertion(ArgumentRequired);
This is just one example, I want to create libraries of some more common scripts that use context variable when used locally
Kindly help me with this and please let me know if some more information/clarification is required
What I get from your questions is that you want to create a code library in SoapUI that can be reused.
I think the best way is by creating jar files and deploying it in ext folder of SoapUI
Create a new groovy script file with a class (follows java standards in file naming i.e. class name and file name should be same)
Compile the groovy code file
Create the jar file
Deploy the jar file at SoapUI_Home/bin/ext folder
Restart the SoapUI if was already open
Create the object of class and use the methods anywhere in the SoapUI projects
Note: If you are migrating your project to some other machine, make sure to migrate these libraries as well if you are using them in projects
Details with example:
Step 1: Create a new groovy script file with a class structure
i. Considering the class ScriptLibrary that contain a method named printTestDetails as in following code in it:
class ScriptLibrary {
def context
def testRunner
def log
def printTestDetails(def PrintThisToo) {
log.info 'Name of the test case is :'+testRunner.testCase.name
log.info 'Name of the test suite is : '+testRunner.testCase.testSuite.name
log.info PrintThisToo
}
}
ii. Save the file with class name, ScriptLibrary.groovy in this case
Step 2: Compile the code
i. Open command prompt and fire following command (from the folder where where your .groovy file is kept)
Compile the code:
groovyc -d classes ScriptLibrary.groovy
Step 3: Create the jar file
i. After compiling the code we can create the jar
Create jar file:
jar cvf ScriptLibrary.jar -C classes .
Step 4: Deploy the jar file at SoapUI_Home/bin/ext folder
Step 5: Restart the SoapUI if was already open
Step 6: Create the object of class and use the methods anywhere in the SoapUI projects
i. Creating object
def scripts = new ScriptLibrary(context:context, log:log, testRunner:testRunner)
ii. Calling methods
scripts.printTestDetails(“This is my argument”)
I hope this solves your problem over all, this approach will allow you to freely use the code any where in the SoapUI and most importantly will solve your problem for getting context, log and testrunner in external code
You can also use any IDE of your choice to create code library and work on same to compile and create jar as well.
Let me know if you have any doubts or need more clarification
While I like Samarth's Answer for large projects, there is something about not having to leave SoapUI that makes TestHat's Answer very interesting.
This is what I used in my latest project:
A Testsuite ScriptLibrary with Testcases according to areas and Groovy script steps for every function.
I run these functions with testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"].testCases["Demo"].testSteps["SomeFunction"].run(testRunner, context);, which then mutates the context to include the needed functions.
In order to use the correct log and testRunner instances, I pass those via parameters. e.g. context.someFunction(log, testRunner);
Because normal functions can't be assigned to the context, I either use closures or classes.
For classes I use something like
class SomeClass {
def logger;
def runner;
SomeClass(logger, runner) {
this.runner = runner;
this.logger = logger;
}
public static SomeClass with(logger, runner) {
return new SomeClass(logger, runner);
}
public void someFunction(String a) {
// This prints to the log of the caller function and not this one
logger.info a;
}
}
context.SomeClass = SomeClass;
and then call it with
testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"].testCases["Demo"].testSteps["SomeClass"].run(testRunner, context);
context.SomeClass.with(log, testRunner).someFunction(
"Hello World"
);
This is mainly done because you can't easily create a new instance from the context.SomeClass variable.
While the context is persisted inside a Testcase, it gets cleared when using a "Run Testcase" teststep, which freqently use.
Maybe this was some help to somebody in the future.
This should do it
context.setProperty("Assertions", new Assertions());
class Assertions{
def printAssertion( tStep){
def assertions = tStep.getAssertionList()
//Loop on assertions
assertions.each{
log.info(it.name + ' --> ' + it.status)
}
}
}
and call it like this
TestStep=testRunner.testCase.testSuite.getTestCaseByName("yourTestCase").getTestStepByName("stepName")
context.Assertions.printAssertion(TestStep)
On the project level, you can write "Load Script" and you can save your utility class instance in the project level context:
context.setProperty("ScriptLibrary", new ScriptLibrary())
and in your test suit (eg. in "Setup Script") you can get it:
testSuite.project.context.getProperty('ScriptLibrary')
or in your test case:
testCase.testSuite.project.context.getProperty('ScriptLibrary')
or in your Groovy test step:
testRunner.testCase.testSuite.project.context.getProperty('ScriptLibrary')
For Assertion :
Put this script in Repository
context.setProperty("Assertions", new Assertions());
class Assertions{
def printAssertion(tStep){
def assertions = tStep.getAssertionList()
//Loop on assertions
}
}
Use this Script in SoapUI:
TestStep=testRunner.testCase.testSuite.getTestCaseByName("addTestCase").getTestStepByName("add")
//context.Assertions.printAssertion(TestStep)
scripts = testRunner.testCase.testSuite.project.testSuites["ScriptLibrary"];
scripts.testCases["Demo"].testSteps["TestAssertion"].run(testRunner, context);
context.Assertions.printAssertion(TestStep).each{
log.info(it.name + ' --> ' + it.status)
}
return null
I have a question about jenkins build flow plugin.
There is a default value called params in build flow dsl which looks like a map.
What I want to do is pass this map to the jobs I want to build later, however, build flow dont accept a map as a parameters.
For example:
build("test_job", params)
The most stupid way I know is just paste all of them one by one, like, build("test_job", "Key1":params[1], "key2":"params[2]")
Any better idea for this case?
Br,
Tim
The order is the key here!
You can do this (at least it works for me), use the map of parameters as the first argument :
job_params = [:]
job_params['BRANCH'] = 'The Branch Name'
build( job_params, 'pipelinetester' )
And it works!
Try this method
build("jobname", parameter_name:"your parameter value")
Example :
In your case if you are using name as parameter and your value "abc"
then use
build ("job-name", name:"abc")
You can do this by archiving your map from project 1 and copy it using this plugin:
https://wiki.jenkins-ci.org/display/JENKINS/Copy+Artifact+Plugin
Or you can use shared folder using the plugin:
https://wiki.jenkins-ci.org/display/JENKINS/CopyArchiver+Plugin
I have a question about name lookup in Groovy. Consider the following build script:
apply([plugin: 'java'])
def dependenciesClosure = {
delegate.ext.name = "DelegateName"
println name
println delegate.toString()
project(':api')
}
dependenciesClosure();
dependencies(dependenciesClosure)
The gradle check command produces the output
webapp
project ':webapp'
DelegateName
org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler_Decorated#397ef2
Taking that into account, nonlocal variable name lookup is performed on a delegate object first an, if the name's not found, performed on the global project object. Is that correct?
Correct, Gradle uses a delegate first resolve strategy within configuration closures. In this case, the delegate is an instance of DependencyHandler. You can see what any given block delegates to by looking at the Gradle DSL documentation.
Edit: To confirm your last point, yes, the build script itself delegates to an instance of Project.
Consider the following method invokation containing in the gradle build script:
gradle.taskGraph.whenReady{taskGraph ->
println gradle.toString()
println "Ready"
}
It prints
build 'task_graph'
Ready
I thought we work in the scope of Project object, since gradle should be a property of that Project object. But there is neither property nor even method with such name. Why can we use it in the build script?
I may be wrong but I think your confusion is that there exists a getGradle() method on the Project interface but no such public field named gradle. This is a Groovy feature. In Groovy, getter and setter methods can by referenced as properties. For example:
println project.description // same as project.getDescription()
project.description = 'My java project' // same as project.setDescription('My java project')
I'd highly suggest familiarizing yourself with Groovy by checking out their documentation. You'll see a lot of differing syntax in Gradle examples simply because there are many different ways to accomplish the same thing in Groovy.
I am wondering how we can pass variables between two step definitions files.
I found this How to share variables across multiple cucumber step definition files with groovy but their structure is different from mine, because I am not using classes in step definition.
The following is my two step definition files.
Feature File 1
Scenario: Consumer registration
When I try to register with my details with "memberNo" mem no.
Then I should be able to get success response
stepDef1
When(~'^I try to register with my details with "([^"]*)" mem no.$') { String memdNo ->
sMemdNo = memNo + getRanNo()
// more code here
}
Feature File 2
Scenario: Event Generation
When I activate my account
Then I can see the file having "logName" event
stepDef2
Then(~'^I can see the file having "([^"]*)" event$') { String logName ->
eventFile = GetLogtData(logName , sMemdNo )
// more code here
}
So, as per the above I want to get the value of sMemdNo from stepDef1 and use it in stepDef2.
I will recommend that you use the World, to store global variables needed across step definitions.
You can see an example here: cucumber-jvm-groovy-example.
You can combine the World with a Factory and/or dependency injection pattern.
To use variables between steps you can add the variable at the top of the steps file (groovy or java), and the variable used in one step will have the value available for other variable.
Example
Result