Automatically downloading Groovy console logs from Soap UI - groovy

I have Soap UI Pro. I am able to download all the system generated reports. I have a groovy script as one of the test steps and I am writing some transaction logs using log.info(). When I execute my test suite, I also want my console logs to be automatically downloaded to my machine. Can someone let me know if this is possible ?
or can I write my log.info() values to the system generated logs ?

There is my script to save the Script log to a file.
def loggerSize = 0
log.info "first log"
log.info "second log"
def logArea = null
logArea = com.eviware.soapui.SoapUI.logMonitor.getLogArea( "Script log" ); // Or HHTP log, Jetty log, Script log; each tab name in log part, can't capture 'Log Output' part ...
def model = null
def logger = ""
if( logArea != null ){
model = logArea.model
if( model.size > loggerSize ){
for(c in loggerSize..(model.size-1)){
logger += model.getElementAt(c).toString() + "##"
}
}
}
return logger

Related

Soap UI: Groovy Test Step : How to call a Specific Method in a groovy script from another Groovy Script

In my project, I want to keep all groovy utilities test step under one test case and to call them again and again where ever is needed. Like reading the test data file etc. I would be able to achieve that if the below problem is resolved. I tried a lot of ways but couldn't make it. Any help is welcome!!
For Example
script 1: test1Script
def sayHellow(){
log.info "Hello!!"
}
Script 2 : test2Script
import groovy.lang.Binding
import groovy.util.GroovyScriptEngine
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def projectPath = groovyUtils.projectPath
def scriptPath = projectPath + "\\GroovyScripts\\"
//GroovyShell shell = new GroovyShell()
//Util = shell.parse(new File(directoryName + "groovyUtilities.groovy"))
//groovyUtilities gu = new groovyUtilities(Util)
// Create Groovy Script Engine to run the script.
GroovyScriptEngine gse = new GroovyScriptEngine(scriptPath)
// Load the Groovy Script file
externalScript = gse.loadScriptByName("sayHello.groovy")
// Create a runtime instance of script
instance = externalScript.newInstance()
// Sanity check
assert instance!= null
// run the foo method in the external script
instance.sayhellowTest()
When I'm calling that method from another script, I'm getting below exception
groovy.lang.MissingPropertyException: No such log for class test1Script
The error shows that groovy runtime calls your method but it can't find the log property. I assume that this log variable is declared in the test1Script body, e.g. def log = ... In this case the variable becomes local to its declaration scope and it's not visible to the script functions. To make it visible, it can be annotated by #Field or it should be undeclared (doesn’t have type declaration, just log = ...). The latter, however, requires you to pass the variable value via so-called bindings when running the script as you run it. So given my assumptions above, you can annotate your log variable as a field and it should work:
//just for the sake of example it prints to stdout whatever it receives
#groovy.transform.Field
def log = [info: {
println it
}]
def sayHellow() {
log.info "Hello!!"
}
Now calling sayHellow from another script prints "Hello" to stdout:
...
instance.sayHellow()
It is very important to declare, context, testRunner, and Log variables in the called script.
script 1: sayHello.groovy
public class groovyUtilities {
def context
def testRunner
def log
def sayhellowTest() {
log.info "Hi i'm arpan"
}
}
script 2: RunAnotherGroovyScript.groovy
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def projectPath = groovyUtils.projectPath
def scriptPath = projectPath + "\\GroovyScripts\\"
// Create Groovy Script Engine to run the script and pass the location of the directory of your script.
GroovyScriptEngine gse = new GroovyScriptEngine(scriptPath)
// Load the Groovy Script file
externalScript = gse.loadScriptByName("sayHello.groovy")
// Create a runtime instance of script
instance = externalScript.newInstance(context: context, log: log, testRunner: testRunner)
// Sanity check if the instance is null or not
assert instance != null
// run the foo method in the external script
instance.sayhellowTest()
Standoutput:
Hi i'm arpan
"I want to keep all groovy utilities test step under one test case and
to call them again and again where ever is needed. Like reading the
test data file etc."
OK, so to me this simply sounds like you have a library of reusable functions and want to be able to call them from any test you might be running.
I suppose you could store them with another test and then call them from the test you're currently running, but SoapUI comes with the neat feature in that you can store your common functions/libraries 'outside' of the SoapUI project.
I have lots of such Groovy libraries and I store mine under the bin/scripts folder of SoapUI. I typically call common functions from a Script assertion test step in the test I'm running. For example, I have a getUserDetails type test step. I can do all the usual assertions against the step like valid response code, SLA etc. I can then use a Script assertion test step. This type of step allows you to run a chunk of Groovy script. This is OK for specific cases, but you wouldn't want to paste in something common as you need to update every Script assertion if something changes. But you can call an 'external' groovy script. Also, the Script Assertion step is just a method that has log, context and message exchange passed into it, so no need to instantiate your own. Just pass them into you external groovy script...
So, as an illustration...
ValidateUser.groovy (stored in bin/scripts/groovyScripts/yourOrg/common)
package groovyScripts.yourOrg.common; // Package aligns with folder it's stored in.
Class ValidateUser {
def log = null;
def context = null;
def messageExchange = null;
// Constructor for the class
ValidateUser(logFromTestStep, contextFromTestStep, messageExchangeFromTestStep) {
// Assign log, context and messageExchange to the groovy class.
this.log = logFromTestStep;
this.context = contextFromTestStep;
this.messageExhange = messageExchangeFromTestStep;
}
def runNameCheck() {
// Performs some validation. You have access to the API response via
// this.messageExchange
log.info("Running the Name Check");
}
}
In the test step of interest, go to the assertions and create a 'Script Assertion' From here you can instantiate your external class and call some method. E.g.
def validateUserObject = new groovyScripts.yourOrg.common.ValidateUser(log, context, messageExchange);
validateUserObject.runNameCheck();
What I like about these external type scripts is that I can use any text editor I like. Also, when I make a change and press Save, SoapUI is monitoring the scripts folder for changes and reloads the script so no need to restart SoapUI.

Exec nodejs and get output on error

I am trying to fire a command via exec in my go binary to get JSON output of the other script. The other script is a nodejs task checking for html problems.
If I fire the nodeJS task on cli everything works fine and I get JSON output, but if I fire the command inside of go I only get:
exit status 1
I am not total sure if the problem is a nodejs or a go problem, but even if nodejs founds HTML Problems I want to be able to analyze the JSON Response in my go script.
Here is my source code:
out, err := exec.Command("/usr/bin/testcafe", "'chromium:headless --no-sandbox'", "--reporter json", "/data/checks.js").Output()
status := http.StatusOK
message := ""
if err != nil {
status = http.StatusNotImplemented
message = err.Error() + string(string(out[:]))
fmt.Println(message)
}
As mentioned above if you ever need to access Stderr from an Command Exit in Golang use:
message += string(err.(*exec.ExitError).Stderr[:])
In my case the nodejs tool gave an exit code based on the amounts of problems. Solved this it runs perfectly now =).
I made a function that I use to do shell command execution:
https://gist.github.com/leninhasda/8f2b5cdc22677a8f2bdf2e896eb0b561
stdOut, stdErr, err := ShellExec("echo", "hello", "world")
if err != nil {
// error executing command
}
if stdErr != "" {
// shell command returned error message
}
if stdOut != "" {
// shell command returned output message
// hello world
}

SOAPUI Assertion script writing twice to file

I am writing a groovy script where I am extracting text from a response and writing it to an output file on my system. The problem I encounter is when I run the groovy script that calls the test. The script assertions runs and logs the text twice to the file.
It seems to write to the file just before it leaves the assertion.
I have tried the following:
...
...
if (context.alreadyWritten == null || !context.alreadyWritten) {
inputFile.append (testString+ "\n")
log.info testString
} else {
log.info ('Already written!')
}
I have set the flag (context.alreadyWritten) to false in groovy before I execute the test step.
SOAPUI version : 5.3.0
I see there was an issue previous with Smartbear when appending to file in an assertion script. However the workaround was advised to resolve this:
if (context.alreadyWritten == null || !context.alreadyWritten) {
}
Which does not resolve my issue
When I log the result using log.info I see only one instance of the message been logged.
Any ideas.
Thanks
If you are using Script Assertion, try below:
//Define the file name, change as needed
def fileName = '/path/to/file.xml'
//check if you got the response
if (context.response) {
log.info 'Response available and not empty'
def file = new File(fileName)
if (!context?.alreadySaved) {
file.write(context.response)
context.alreadySaved = true
log.info 'response written to file'
} else {
log.info 'Response already written'
}
} else {
log.info 'there is no response to save'
}

How Groovy can save console output to file?

i have a project in Soapui and a groovy code which run all tests of the project.
The result can be seen in the output console.
So what i want is to to save the content of the output ina file.
in Java we can do this:
//create a buffered reader that connects to the console, we use it so we can read lines
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//read a line from the console
String lineFromInput = in.readLine();
//create an print writer for writing to a file
PrintWriter out = new PrintWriter(new FileWriter("c:/temp7/output.txt"));
//output to the file a line
out.println(lineFromInput);
//close the file
out.close();
Is there an equivalent code in groovy ?
THank you
Of course you can read the console output.
But you ned to execute your tests from the GUI and not from command line with testrunner.
// Can be altered to 'soapUI log', 'http log', 'jetty log', 'error log' etc.
def logArea = com.eviware.soapui.SoapUI.logMonitor.getLogArea( "http log" );
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
if( logArea !=null )
{
def model = logArea.model
// only continue of logArea not empty
if( model.size > 0 )
for( c in 0..(model.size-1) )
// DO SOMETHING HERE... could write to file, could run assertions, etc.
writeToFile(model.getElementAt(c))
}

Running SoapUI test cases using testRunner

I am working on a SoapUI project where I need to run my test suite using test runner. I am using external groovy scripting for environment variable. The problem I am facing here is whenever I am running test case from test runner its return Workspace as null, which is used in External groovy. So in external groovy I am getting workspace as null causing error [getProjectByname() cannot be invoked on null]. Below is the
constructor of global script where workspace is used
AvengerAPITestManager(String TestProject, String TestSuite, String TestCase,String TestStep)
{
TestName = "AvengerAPITests";
testProject = SoapUI.getWorkspace().getProjectByName(TestProject);
tSuite = testProject.getTestSuiteByName(TestSuite);
tCase = testProject.getTestSuiteByName(TestSuite).getTestCaseByName(TestCase);
tStepName = TestStep.toString();
tStep=testProject.getTestSuiteByName(TestSuite).getTestCaseByName(TestCase).getTestStepByName (TestStep);
}
Above we have user SoapUI.getWorkspace() which is working fine when trying to run from soapUI but whever I m trying to run from testrunner SoapUI.getWorkspace comes out to be null. I even tried passing workspace like I am passing testproject name still it didnt worked.
I tried something like this also
AvengerAPITestManager(Object workspace,String TestProject, String TestSuite, String TestCase, String TestStep)
{
TestName = "AvengerAPITests";
testProject = workspace.getProjectByName(TestProject);
tSuite = testProject.getTestSuiteByName(TestSuite);
tCase = testProject.getTestSuiteByName(TestSuite).getTestCaseByName(TestCase);
tStepName = TestStep.toString();
tStep = testProject.getTestSuiteByName(TestSuite).getTestCaseByName(TestCase).getTestStepByName(TestStep);
}
In the above code I tries passing Workspace object from the test case as I passed Testcase name and all but still I m getting null for workspace. Please tell me how do I deal with the problem.
Here is usefull working example https://github.com/stokito/soapui-junit
You should place your sample-soapui-project.xml to /src/test/resources folder that will expose it to classpath
If you want to use soap ui in external code, try to directly create new test runner with specific project file:
SoapUITestCaseRunner runner = new SoapUITestCaseRunner();
runner.setProjectFile( "src/dist/sample-soapui-project.xml" );
runner.run();
Or if you want to define test execution more precisely, you can use something like this:
WsdlProject project = new WsdlProject( "src/dist/sample-soapui-project.xml" );
TestSuite testSuite = project.getTestSuiteByName( "Test Suite" );
TestCase testCase = testSuite.getTestCaseByName( "Test Conversions" );
// create empty properties and run synchronously
TestRunner runner = testCase.run( new PropertiesMap(), false );
PS: don't forget to import soap ui classes, that you use in your code and put them to classpath.
PPS: If you need just run test cases outside the soap ui and/or automate this process, why not just use testrunner.sh/.bat for the same thing? (here is description of this way: http://www.soapui.org/Test-Automation/functional-tests.html)
I am not sure if this is going to help anyone out there but here is what I did to fix the problem I was having with workspace as null causing error[getProjectByname() cannot be invoked on null] When i run from cmd
try this:
import com.eviware.soapui.model.project.ProjectFactoryRegistry
import com.eviware.soapui.impl.wsdl.WsdlProjectFactory
import com.eviware.soapui.impl.wsdl.WsdlProject
//get the Util project
def project = null
def workspace = testRunner.testCase.testSuite.project.getWorkspace();
//if running Soapui
if (workspace != null) {
project = workspace.getProjectByName("Your Project")
}
//if running in Jenkins/Hudson
else{
project = new WsdlProject("C:\\...\\....\\....\\-soapui-project.xml");
}
if (project.open && project.name == "Your Project") {
def properties = new com.eviware.soapui.support.types.StringToObjectMap()
def testCase = project.getTestSuiteByName("TestSuite 1").getTestCaseByName("TestCase");
if(testCase == null)
{
throw new RuntimeException("Could not locate testcase 'TestCase'! ");
} else {
// This will run everything in the selected project
runner = testCase.run(new com.eviware.soapui.support.types.StringToObjectMap(), false)
}
}
else {
throw new RuntimeException("Could not find project ' Order Id....' !")
}
The above code will run everything in the selected project.

Resources