Friday, 18 July 2014

Integrate SoapUI with Selenium and Cucumber




 1   Introduction


1.1    Background

Web Service is a way to publish your application over internet and enable other applications to access functions provided by it.
With web service, one could reuse the existing applications, instead of developing the same application over and over again. For example, there are some typical web services such as currency conversion, weather reports, or even language translation.
Web services can also help to solve the interoperability problem by giving different applications a way to link their data. With Web services you can exchange data between different applications and different platforms.

SOAP is a simple XML-based protocol to let applications exchange information over HTTP by exposing an interface defined in Web Services Description Language (WSDL). Other applications can interact with Web service using its WSDL interface. Web Service Functional Testing ensures that your web service is functionally correct.

SoapUI is a popular web service testing tool to create set of request automatically and comparing the result with the expected output.

Selenium is a portable software testing framework for web applications.

Cucumber is a tool for running automated acceptance tests written in a behaviour-driven development (BDD) style.


1.2    Purpose

In this article we will see how SoapUI can be used to test the web service and how to use Cucumber to write web service test scenario in a readable fashion and seamless integrate with Selenium to fully test web service.

1.3    Prerequisites

Before start, you need to install JDK, Eclipse, Maven and SoapUI Pro. Selenium and Cucumber could be installed by maven automatically with a pom.xml, which will be covered in part 3.
Version:

2    Create a SoapUI Function Test Case


 
There are a lot of public web services if search on the internet with "public web service". In this article, a weather web service will be used to test.

 
The WSDL used in this article is: http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL. By open this link, you will find there is a list of operations defined in the WSDL, such as "GetWeatherInformation", "GetCityForecaseByZIP" and "GetCityWeatherByZIP" as below.

 
In the article, we will test one of the operation named as "GetCityWeatherByZIP" by creating a test case and setting properties by groovy script.

 




2.1    Create a SOAP project

Click on the "File->New SOAP Project" menu to launch the create project dialog.



 

Then input the WSDL into the "Initial WSDL" text field.





 

After clicking "OK" button, the sample requests for all operations defined in the above WSDL will be generated in the project as below.



 

2.2    Run the generated request

Click on the request under the getCityWeatherbByZip operation, input any zip code in USA, for example: 98004 (Bellevue) in the left request panel. Then clickto send request to the server. The weather information of Bellevue will be returned as below.




2.3    Create test steps

Now, you could add the request into a test case as a test step. If there is no test case or test suite, by adding the request into a test case, the test suite and test case will be generated automatically.

The test case will look like this:




2.3.1    Create project properties

Now, we will start to customize the test case. Instead of hard coding the zip code, we could parameterize it as a property. Click on project node, then switch to the "Custom Properties" tab to add three properties, named as "usePropertyFileFlag","zipCode" and "city" like following.

2.3.2    Add properties into the test steps

Double click on the test step " GetCityWeatherByZIP - Request 1", on the request panel, click on the "Form" tab, and click add data button, and choose the property "zipCode".


2.3.3    Add assertion into the test steps

On the response panel, click on the outline tab, and right-click on the city node to add an assertion for content using the property "city".
Note: If the response panel is empty, you could click the run button to send the request firstly, then the response xml will be shown like following.




You could click the "Add Assertion"button to add more assertions into the test step like following.



 

Then click the run button to verify the test case works well. Every assertion should pass with green.

2.4    Use groovy scripts to set properties

Now we will try to use various zip codes to verify the "GetCityWeatherByZIP" request. There are several approaches to accomplish task. For example, using the DataSource and DataSource Loop feature. You could refer to SoapUI tutorial about this implementation.
Here, instead of using DataSource, we will try to store the zip code in a separated property file and pass the values into the test case while running. A groovy script will be used to accomplish it. SoapUI supports using groovy scripts to create customized test steps or setting up, tearing down steps for the whole test case or test suite.

2.4.1    Create a groovy script in the test suite setup

Click on the setup tab in a test suite, and add your setup script in the panel like following. The script will create a "zipcode.txt" property file if it does not exist.



 


 


 

Source code:
def usePropertyFileFlag = context.expand( '${#Project#usePropertyFileFlag}' )
log.info("--------------------------"+usePropertyFileFlag)
if (usePropertyFileFlag.equalsIgnoreCase("true")){
    Properties properties = new Properties();
    File f= new File("c:\\sning\\zipCode.txt");
    if (!f.exists()) {
        f.createNewFile();
        properties.setProperty("zipCode", "35594");
        properties.setProperty("city", "Winfield");
        properties.store(new FileOutputStream(f), "writing the properties");
    }
}

 

Clickto run this step, and you will find the file "zipcode.txt" has been created successfully.


2.4.2    Create a groovy test step in the test case

Then open the test case, click the "create a new groovy script test step" button to create a groovy test step named as "SetProperties". This groovy script will read the property file "zipcode.txt" and pass the property into the test case.




Source code:
def usePropertyFileFlag = context.expand( '${#Project#usePropertyFileFlag}' )
if (usePropertyFileFlag.equalsIgnoreCase("true")){
    props = new java.util.Properties()
    fis = new FileInputStream ("C:/sning/zipcode.txt")
    props.load (fis)
    testRunner.testCase.testSuite.project.setPropertyValue( "zipCode", props.getProperty ("zipCode") )
    testRunner.testCase.testSuite.project.setPropertyValue( "city", props.getProperty("city") )
}

 

2.4.3    Run the test suite

Now, click the run button on the test suite, the test case will run successfully.

Switch to the "TestSuite Log" tab, double click on the Step 2, you could see the request and response message like following. Both of them are using soap envelope.






2.4.4    Generate a test report by SoapUI

Click the "Creates a Report for this item" button to generate a predefined SoapUI test report.










Now, a SoapUI function testcase has been created successfully. Before we move on to other parts, please save the project as WeatherSoapTest-soapui-project.xml. All of the test steps and test case definitions and groovy scripts will be stored in this project xml file, which will be used in the following steps.

 

3    Integrate with Selenium and Cucumber


 

Now, instead of only using a static property file to test a specific zip code, we need to test the request with various zip codes dynamically. In this article, we will use Selenium to fetch and parse the zip codes and cities from following website, and pass them into SoapUI test case to verify: http://www.phaster.com/zip_code.html.



 

3.1    Create a project with Maven

If it is the first time you use eclipse and maven together, you must add the maven repository path to eclipse by running the command below, and restart eclipse if it is open.

 


mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo

 



3.1.1    Create a default maven java project

Run following commands in maven to create a java project named as "WeatherService".
mvn archetype:generate -DgroupId=au.net.planit -DartifactId=WeatherService -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

3.1.2    Update the pom.xml

Change the directory to the WeatherService folder just created by above command, and update the dependencies relevant with SoapUI, Selenium and Cucumber. Following is the whole content of the pom.xml.
Note that the highlighted ones are for SoapUI.



3.1.3    Install the dependencies

Then run the following comands to install all the dependencies.
cd WeatherService
mvn clean install
mvn eclipse:eclipse

3.1.4    Import the project into eclipse

Now, you could import the "WeatherService" project into your eclipse workspace by click "File->Import" menu from Eclipse. Then choose "General->Existing Projects into Workspace".



After clicking finish, you will see the project like this.




3.2    Import the SoapUI project file into the java project.

Create a resource source folder like src/test/resources, and copy paste WeatherSoapTest-soapui-project.xml into the resources folder. You could refer to the Appendix I for the details content of the WeatherSoapTest-soapui-project.xml.









3.3    Create a Cucumber Feature File

Now, we will use Cucumber to create a feature file in the resources folder. The scenario will look like following.


Feature:

        As weather web service user

        I will be able to get the weather information by the predefined operations in the WSDL

        

@getWeatherByZipcode

    Scenario: Get the city weather information by zipcode

             Given I have a list of zipcode

             When I use the weather service to get the weather information

             Then the information should be found successfully


3.4    Create a Cucumber JUnit Test Case

Create a Cucumber JUnit test runner like following and run it. You will get a list of missing methods displayed in the console.


package au.net.planit;

import org.junit.runner.RunWith;

import Cucumber.api.CucumberOptions;

import Cucumber.api.junit.Cucumber;



@RunWith(Cucumber.class)

@CucumberOptions(features = "src/test/resources/", tags={"@getWeatherByZipcode"},format = {"pretty", "html:build/Cucumber -report", "json:build/Cucumber -json-report.json"})

public
class RunCukesTest {

}




Create a JUnit test case and copy paste the missing methods into it like following.

package au.net.planit;



import
static org.junit.Assert.*;

import Cucumber.api.PendingException;

import Cucumber.api.java.en.Given;

import Cucumber.api.java.en.Then;

import Cucumber.api.java.en.When;



public
class WeatherTestByZipCode {





@Given("^I have a list of zipcode$")

public
void i_have_a_list_of_zipcode() throws Throwable {


// Write code here that turns the phrase above into concrete actions


throw
new PendingException();

}



@When("^I use the weather service to get the weather information$")

public
void i_use_the_weather_service_to_get_the_weather_information() throws Throwable {


// Write code here that turns the phrase above into concrete actions


throw
new PendingException();

}



@Then("^the information should be found successfully$")

public
void the_information_should_be_found_successfully() throws Throwable {


// Write code here that turns the phrase above into concrete actions


throw
new PendingException();

}



}


3.5    Implement the Test Steps Based on Selenium

3.5.1    Fetch a list of zip codes from a website by Selenium

Then start to implement these missing steps with Selenium. The following code will find the city and zip codes on http://www.phaster.com/zip_code.html and store the parsed valued in a hashtable.


3.5.2    Call the SoapUITestCaseRunner in JUnit

Following code will use to call the SoapUI test case and set the properties.
Note: "usePropertyFileFlag=false", which means instead of using a static property file to store the "zipCode" and "city", we will pass the zipCode and city into the test step at runtime dynamically by setProjectProperties() method.



Source code for the whole test case:
package au.net.planit;
import org.junit.Assert.assertArrayEquals;
import java.util.Hashtable;

import java.util.Iterator;

import java.util.List;

import java.util.Map.Entry;

import java.util.Set;

import java.util.concurrent.TimeUnit;

import org.openqa.Selenium.By;

import org.openqa.Selenium.WebDriver;

import org.openqa.Selenium.WebElement;

import org.openqa.Selenium.firefox.FirefoxDriver;

import com.eviware.SoapUI.tools.SoapUITestCaseRunner;

import Cucumber.api.java.en.Given;

import Cucumber.api.java.en.Then;

import Cucumber.api.java.en.When;

public
class GetWeatherByZipTest {

    private Hashtable<String, String> zipAndCities;

    private
int
failureCount =0, totalCount= 0;

    private StringBuffer zipCodes = new StringBuffer();

    public WebDriver driver;

    

    @Given("^I have a list of zipcode$")

    public
void i_have_a_list_of_zipcode(){


        driver = new FirefoxDriver();

        driver.manage().window().maximize();

        driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);

        driver.get("http://www.phaster.com/zip_code.html");

        

        List<WebElement> rows = driver.findElements(By.cssSelector("blockquote tr"));

        zipAndCities = new Hashtable<>();

        for (int i = 1; i < 5; i++) {

            List<WebElement> columns = rows.get(i).findElements(By.cssSelector("td"));

            String city = columns.get(1).getText().split("\n")[0].split("\\(")[0];

            String zipCode = columns.get(2).getText().split(" ")[0].split("-")[0].split("\n")[0];

            zipAndCities.put(zipCode, city);

        }

    }

    

    @When("^I use the weather service to get the weather information$")

    public
void i_use_the_weather_service_to_get_the_weather_information() {

        Set<Entry<String, String>> set = zipAndCities.entrySet();

        Iterator<Entry<String, String>> iterator = set.iterator();

        while (iterator.hasNext()) {

            Entry<String, String> entry = iterator.next();

            String zipCode = entry.getKey();

            String city = entry.getValue();

            String[] prop ={"usePropertyFileFlag=true","zipCode="+zipCode, "city="+city};

            

            try {

                SoapUITestCaseRunner SoapUITestCaseRunner= new SoapUITestCaseRunner();

             SoapUITestCaseRunner.setProjectFile("src/test/resources/WeatherSoapTest-SoapUI-project.xml");

                SoapUITestCaseRunner.setProjectProperties(prop);

                SoapUITestCaseRunner.setTestSuite("TestSuite 1");

                SoapUITestCaseRunner.setTestCase("TestCase 1");

                SoapUITestCaseRunner.run();

            } catch (Exception e) {

                System.err.println("checking " + zipCode + " failed!");

                failureCount++;

                zipCodes.append(zipCode + " [" + city +"] ");

                e.printStackTrace();

            }finally{

                totalCount++;

            }

        }

    

    }

    

    @Then("^the information should be found successfully$")

    public
void the_information_should_be_found_successfully() {

        assertArrayEquals("There are " + failureCount +" in " + totalCount+" cities are not found, " + zipCodes.toString(), new
int[]{0}, new
int[]{failureCount});

        driver.quit();

    }



}


3.5.3    Run the test case

Now, run the "RunCukesTest" again. In the console view, you will find a list of zip codes and cities fetched and passed into the SoapUI TestCase 1 to be verified one by one.


3.5.4    View SoapUI Log File

In addition, there is a soapui.log generated under the project root folder like following. You could open it to see the logs if you need. If it is not there, try to refresh the project.
























You could run the test from maven command line as well.
Now we have integrated the SoapUI with Selenium and Cucumber successfully. Hope you enjoy on this journey with the three giants of open source testing world!


Resources


Your First SoapUI Project: One will learn how to create your first SOAP project in SoapUI, add a WSDL-file, and get acquainted with SoapUI's interface.

Groovy Selenium WebDriver and SoapUI: Using Selenium in SoapUI with groovy.
Testing a Web Service with SoapUI, JUnit, Maven and Cucumber: How to use SoapUI in continuous build.
Web Service, SOAP, WSDL, REST Introduction: Some introduction material about web service relevant terms in W3School website.


13 comments:

  1. Many thanks for this article. Not only help me to solve almost of my task but give me a very basic summary to my love at that time also: Cucumber, Selenium and SoapUI. Great!

    ReplyDelete
  2. Very nice article!! Just what I was looking for..Thanks :)

    ReplyDelete
  3. Good article. It would be possible to extend SoapUi with new components integrated with Selenium WebDriver. This way you'll be able to use new teststeps more easily. Please, see the following vídeo:https://youtu.be/9eqSuma6pfQ

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. thank u for sharing this good article..we are offering soup ui online training

    ReplyDelete
  6. WeatherSoapTest-soapui-project.xml is referred to Appendex I, but is not available (link not present)

    ReplyDelete
  7. hi,we provide online training & video tutorial for soapui
    for free videos refer
    http://soapui-tutorial.com/soapui-tutorial/introduction-to-webservices/

    ReplyDelete
  8. Thank for sharing this useful information;
    It is very useful to me and who are wanted to learn or update their knowledge on SOAP UI through SOAP UI online training or offline training.

    ReplyDelete
  9. Fantastic information. CAUTION: you don't want those try{}catch (Exception) in your steps as you're hiding failures from your test runner. Otherwise, you're tolerating errors to generate a comprehensive report. Do you rally want to tolerate those errors? Why not just fail fast (let the exception rollback to the test runner) and move onto the next scenario.

    Also, I'd move that xxx.run() from the When into the Then since that's where you do evaluation anyhow.

    Great work on showing Cucumber driving a test authored in SoapUI.

    ReplyDelete
  10. I am getting some issue as mentioned here can you help me

    https://community.smartbear.com/t5/TestComplete-Plugin-Development/Not-able-to-execute-the-SoapUI-test-cases-from-MAVEN/m-p/144429#M183

    ReplyDelete