Why run soapui tests as junit tests?
There are probably many ways of running soapui tests and generating nice reports. The way I chose was to run them as junit tests because:
- can run tests from a jenkins job and use surefire to generate a report containing all the results
- can invoke the tests from an IDE - eclipse and netbeans are the only 2 I have run the project in
- can invoke the tests from the command line using maven
- dont need to have soapui installed on the system you are running the tests from since the jars are all included as part of the java project
Create base testcase class
The SoapUITestCase class is the helper base classs for our SoapUI junit classes. It provides the junit reporting, setting SoapUI properties and running the actual tests. It can be extended or modified to not require using a SoapUI properties file.
/**
* ****************************************************************************
*
* [ SoapUITestCase.java ]
*
******************************************************************************
*/
package com.qa.soapuiTestBase;
import java.util.HashMap;
import java.util.List;
import org.apache.log4j.Logger;
import com.eviware.soapui.model.testsuite.ProjectRunContext;
import com.eviware.soapui.model.testsuite.ProjectRunner;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.model.testsuite.TestSuite;
import com.eviware.soapui.model.testsuite.TestSuiteRunContext;
import com.eviware.soapui.model.testsuite.TestSuiteRunner;
import com.eviware.soapui.report.JUnitReport;
import com.eviware.soapui.report.JUnitReportCollector;
import com.eviware.soapui.report.JUnitSecurityReportCollector;
import com.eviware.soapui.tools.SoapUITestCaseRunner;
import com.qa.utils.Logtools;
import com.qa.utils.QAPropertiesSoapUI;
/**
* Base class for soapui junit test cases.
*
*/
public class SoapUITestCase {
static Logger qaLogger = Logger.getLogger(Logtools.class.getName());
/**
* The eviware SoapUITestCaseRunner class does not provide a public method for
* creating a JUnitSecurityReportCollector which is needed to get junit
* output. Copied the JunitSecurityReportCollector class from github:
* <ul>
* <li>https://github.com/SmartBear/soapui/blob/master/soapui/src/main/java/com/eviware/soapui/tools/SoapUITestCaseRunner.java</li>
* </ul>
* and Override it in private JunitSoapUITestCaserRunner classbelow.
*
*/
private static class JunitSoapUITestCaseRunner extends SoapUITestCaseRunner {
@Override
protected JUnitSecurityReportCollector createJUnitSecurityReportCollector() {
return new JUnitSecurityReportCollector() {
JUnitReportCollector self = new JUnitReportCollector();
@Override
public List<String> saveReports(final String path) throws Exception {
return self.saveReports(path);
}
@Override
public HashMap<String, JUnitReport> getReports() {
return self.getReports();
}
@Override
public void saveReport(final JUnitReport report, final String filename) throws Exception {
self.saveReport(report, filename);
}
@Override
public String getReport() {
return self.getReport();
}
@Override
public void afterRun(final TestCaseRunner testRunner, final TestCaseRunContext runContext) {
self.afterRun(testRunner, runContext);
}
@Override
public void afterStep(final TestCaseRunner testRunner, final TestCaseRunContext runContext, final TestStepResult result) {
self.afterStep(testRunner, runContext, result);
}
@Override
public void beforeRun(final TestCaseRunner testRunner, final TestCaseRunContext runContext) {
self.beforeRun(testRunner, runContext);
}
@Override
public void beforeStep(final TestCaseRunner testRunner, final TestCaseRunContext runContext) {
self.beforeStep(testRunner, runContext);
}
@Override
public void beforeStep(final TestCaseRunner testRunner, final TestCaseRunContext runContext,
final TestStep testStep) {
self.beforeStep(testRunner, runContext, testStep);
}
@Override
public void reset() {
self.reset();
}
@Override
public void afterRun(final TestSuiteRunner testRunner,
final TestSuiteRunContext runContext) {
self.afterRun(testRunner, runContext);
}
@Override
public void afterTestCase(final TestSuiteRunner testRunner,
final TestSuiteRunContext runContext,
final TestCaseRunner testCaseRunner) {
self.afterTestCase(testRunner, runContext, testCaseRunner);
}
@Override
public void beforeRun(final TestSuiteRunner testRunner,
final TestSuiteRunContext runContext) {
self.beforeRun(testRunner, runContext);
}
@Override
public void beforeTestCase(final TestSuiteRunner testRunner,
final TestSuiteRunContext runContext,
final TestCase testCase) {
self.beforeTestCase(testRunner, runContext, testCase);
}
@Override
public void afterRun(final ProjectRunner testScenarioRunner,
final ProjectRunContext runContext) {
self.afterRun(testScenarioRunner, runContext);
}
@Override
public void afterTestSuite(final ProjectRunner testScenarioRunner,
final ProjectRunContext runContext,
final TestSuiteRunner testRunner) {
self.afterTestSuite(testScenarioRunner, runContext, testRunner);
}
@Override
public void beforeRun(final ProjectRunner testScenarioRunner,
final ProjectRunContext runContext) {
self.beforeRun(testScenarioRunner, runContext);
}
@Override
public void beforeTestSuite(final ProjectRunner testScenarioRunner,
final ProjectRunContext runContext,
final TestSuite testSuite) {
self.beforeTestSuite(testScenarioRunner, runContext, testSuite);
}
};
}
}
/**
* Run a SoapUI project.
* <ul>
* <li>get properties from soapui- file</li>
* <li>set runner properties so junit test results are saved to output
* folder</li>
* <li>run the tests</li>
* </ul>
*
* @param soapuiProjectXML soapui project xml file
* results folder
* @param propFolder - relative folder path to props folder
* @throws Exception
*/
public final void runSoapUIProject(final String soapuiProjectXML,
final String propFolder) throws Exception {
qaLogger.info(Logtools.getCurrentlyExecutingMethodName());
SoapUITestCaseRunner runner = new JunitSoapUITestCaseRunner();
String[] globalProps;
String outputFolder = soapuiProjectXML.split("/")[3].split("-soapui-project.xml")[0];
System.out.println("SoapUI test: result output folder: " + outputFolder);
globalProps = QAPropertiesSoapUI.setProperties(propFolder); // read soapui- file
runner.setGlobalProperties(globalProps);
doRunSoapUIProject(soapuiProjectXML, runner, outputFolder);
}
/**
* Run a SoapUI project.
* <ul>
* <li>create string for project+endpoint specific folder results
* <li>get properties from soapui- file</li>
* <li>set test-endpoint global property to endpoint tests will run on
* <li>set runner properties so junit test results are saved to output folder specific to endpoint</li>
* <li>run the tests</li>
* </ul>
*
* @param soapuiProjectXML soapui project xml file results folder
* @param endpoint - String with endpoint tests are run on
* @param propFolder - relative folder path to props folder
* @return String - name of folder where test results are stored
* @throws Exception
*/
public final void runSoapUIProject(final String soapuiProjectXML,
final String endpoint,
final String propFolder) throws Exception {
qaLogger.info(Logtools.getCurrentlyExecutingMethodName());
SoapUITestCaseRunner runner = new JunitSoapUITestCaseRunner();
String[] globalProps;
String outputFolder = soapuiProjectXML.split("/")[3].split("-soapui-project.xml")[0] + "-" + endpoint;
System.out.println("SoapUI test: result output folder: " + outputFolder);
globalProps = QAPropertiesSoapUI.setProperties(propFolder); // read soapui- file
//set the endpoint to run tests on
for (int i = 0; i < globalProps.length; i++) {
if (globalProps[i].contains("test-endpoint")) //string must exactly match string in props file
{
globalProps[i] = "test-endpoint=" + endpoint;
break;
}
}
runner.setGlobalProperties(globalProps);
doRunSoapUIProject(soapuiProjectXML, runner, outputFolder);
}
/**
* Run the actual soapui project.
*
* @param soapuiProjectXML - soapui project xml file
* @param projectName - folder where test results get stored under main test
* results folder
* @param runner - soapui test runner instance
* @throws Exception
*/
private void doRunSoapUIProject(final String soapuiProjectXML,
final SoapUITestCaseRunner runner,
final String outputFolder) throws Exception {
qaLogger.info(Logtools.getCurrentlyExecutingMethodName()
+ " soapuiProjectXML: " + soapuiProjectXML);
String soapuiSettingsFile = System.getProperty("user.dir") + "/config/soapui-settings.xml";
String fullOutputFolder = "target/surefire-reports/" + outputFolder;
runner.setProjectFile(soapuiProjectXML);
runner.setExportAll(true);
runner.setPrintReport(true); // Outputs a small table to stdout of test results.
runner.setJUnitReport(true);
runner.setOutputFolder(fullOutputFolder);
runner.setSettingsFile(soapuiSettingsFile);
try {
runner.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Create junit class
The junit class is a very simple class that calls the runSoapUIProject method. You just need to pass it the relative location and file name of your soapui xml project file and the location of the global properties you want loaded on soapui startup. The junit test and SoapUITestCase classes can easily be modified to not require a global property file.
package com.qa.smoketestTest;
import org.junit.Test;
import com.qa.soapuiTestBase.SoapUITestCase;
/**
* Unit test for a soapui project. It calls the runSoapUIProject passing it:
* <ul>
* <li>soapui project file including path</li>
* <li>folder containing soapui property file</li>
* </ul>
*/
public class smoketestTest extends SoapUITestCase {
@Test
public void testquick() throws Exception {
runSoapUIProject(
"src/test/resources/smoketest-soapui-project.xml",
"/../props");
}
}
Run your junit test
I either run the junit tests from my favorite ide (right now that would be eclipse) or from the command line using maven.