Automated Acceptance Testing iOS Mobile Apps with Appium, Cucumber-JVM, Jenkins, and Sauce Labs – Part 2

This series was originally posted on Sauce Labs Blog. This is a reblog with revisions.

Welcome to the second part of Automated Acceptance Testing iOS Mobile Apps with Appium, Cucumber-JVM, Jenkins, and Sauce Labs. In this post we will define steps for the feature we identified in Part 1. We will run this feature with Maven and look at Cucumber results.

Running features with Maven

Before we move forward, we need to configure a support/helper class which tells Cucumber options for running  features that we have added to the project. Add a new Java class RunCukesTest to scr/test/java/bmicalculator.test and copy following code


package bmicalculator.test;

import cucumber.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@Cucumber.Options(format = {"pretty", "html:target/cucumber-html-report", "json-pretty:target/cucumber-report.json"})
public class RunCukesTest {

}

Now let’s run this feature file, in terminal navigate to the project folder and run following command


mvn test

After executing above command, Cucumber will suggest some step definitions for missing steps as below:


@Given("^I enter \"([^\"]*)\" as height$")
public void I_enter_as_height(String arg1) throws Throwable {
 // Express the Regexp above with the code you wish you had
 throw new PendingException();
}

@Given("^I enter \"([^\"]*)\" as weight$")
public void I_enter_as_weight(String arg1) throws Throwable {
 // Express the Regexp above with the code you wish you had
 throw new PendingException();
}

@Given("^I press the Calculate button$")
public void I_press_the_Calculate_button() throws Throwable {
 // Express the Regexp above with the code you wish you had
 throw new PendingException();
}

@Then("^I should see \"([^\"]*)\" as bmi and \"([^\"]*)\" as category$")
public void I_should_see_as_bmi_and_as_category(String arg1, String arg2) throws Throwable {
 // Express the Regexp above with the code you wish you had
 throw new PendingException();
}

Undefined step: Given I enter "170" as height
Undefined step: And I enter "50" as weight
Undefined step: And I press the Calculate button
Undefined step: Then I should see "17.30" as bmi and "Underweight" as category

Undefined step: Given I enter "181" as height
Undefined step: And I enter "80" as weight
Undefined step: And I press the Calculate button
Undefined step: Then I should see "24.42" as bmi and "Normal" as category

Undefined step: Given I enter "180" as height
Undefined step: And I enter "90" as weight
Undefined step: And I press the Calculate button
Undefined step: Then I should see "27.78" as bmi and "Overweight" as category
Undefined step: Given I enter "175" as height

Undefined step: And I enter "100" as weight
Undefined step: And I press the Calculate button
Undefined step: Then I should see "32.65" as bmi and "Obese" as category

1 scenario (0 passed)
16 steps (0 passed)

Implementing Step Definitions

Cucumber drives features & scenarios with automated steps using step definitions. Step definitions are glue between the steps described in a Scenario to the actual automation code which drive the App either through API or User Interface. The App user interface many not be ready at this time.

While development team is busy in developing the App we can create place holders for the steps from the sample scenario as suggested by Cucumber.

Add new Java class Bmi_Calculator_Step_Defs to src/test/java/bmicalculator.test package and implement steps for our example feature. We will mark them as pending with Cucumber PendingExeception() as below:

package bmicalculator.test;

import cucumber.annotation.en.*;
import cucumber.runtime.PendingException;

public class Bmi_Calculator_Step_Defs {

@Given("^I enter \"([^\"]*)\" as height$")
public void I_enter_as_height(String arg1) throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}

@Given("^I enter \"([^\"]*)\" as weight$")
public void I_enter_as_weight(String arg1) throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}

@Given("^I press the Calculate button$")
public void I_press_the_Calculate_button() throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}

@Then("^I should see \"([^\"]*)\" as bmi and \"([^\"]*)\" as category$")
public void I_should_see_as_bmi_and_as_category(String arg1, String arg2) throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
}

When this feature is executed by Cucumber, it will show these steps as pending.

Once developers are done with the initial version of the App and it’s ready for testing we will refactor these steps and add code to drive the user interface of the App using Appium and Selenium WebDriver API to check the expected behavior of the App.

We need to declare an instance of WebDriver class from Selenium WebDriver API. We will add a setup method setupLocal() which will initialize the driver instance and connect to Appium running on a local machine

@Before
public void setUpLocal()  throws Throwable {
	//Setup for running Appium test in local environment
	DesiredCapabilities capabilities = new DesiredCapabilities();
	capabilities.setCapability(CapabilityType.BROWSER_NAME, "iOS");
	capabilities.setCapability(CapabilityType.VERSION, "6.1");
	capabilities.setCapability(CapabilityType.PLATFORM, "Mac");
	capabilities.setCapability("app", "/Users/upgundecha/Desktop/AppExamples/BmiCalculator/build/Release-iphonesimulator/BmiCalculator.app");

	//Create an instance of RemoteWebDriver and connect to the Appium server.
	//Appium will launch the BmiCalc App in iPhone Simulator using the configurations specified in Desired Capabilities
	driver = new RemoteWebDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
}

Also implement the steps with Selenium WebDriver API to interact with the App elements in following way

public void I_enter_as_height(String height) throws Throwable {
	WebElement heightTextField = driver.findElement(By.name("Height"));
	heightTextField.sendKeys(height);

}

@Then("^I enter \"([^\"]*)\" as weight$")
public void I_enter_as_weight(String weight) throws Throwable {
	WebElement weightTextField = driver.findElement(By.name("Weight"));
	weightTextField.sendKeys(weight);
}

@Then("^I press the Calculate button$")
public void I_press_the_Calculate_button() throws Throwable {
	WebElement calculateButton =  driver.findElement(By.name("Calculate"));
	calculateButton.click();
}

@Then("^I should see \"([^\"]*)\" as bmi and \"([^\"]*)\" as category$")
public void I_should_see_as_bmi_and_Normal_as_category(String bmi, String category) throws Throwable {

	WebElement bmilabel = driver.findElement(By.name("bmi"));
	WebElement bmiCategorylabel = driver.findElement(By.name("category"));

	//Check the calculated Bmi and Category displayed
	assertEquals(bmi,bmilabel.getText());
	assertEquals(category,bmiCategorylabel.getText());
}

At the end add a tearDown() method to close the App

public void tearDown() {
	driver.quit();
}

This makes the step definitions complete. When this feature is run, Cucumber will call the Selenium WebDriver API which in turn calls the Appium and steps are performed on the App’s user interface in iOS Simulator. At the end of execution Cucumber will display results as below


1 scenario (1 passed)
16 steps (16 passed)

In the next post we will explore how to run Cucumber features with Sauce Labs cloud and Jenkins.


2 Comments on “Automated Acceptance Testing iOS Mobile Apps with Appium, Cucumber-JVM, Jenkins, and Sauce Labs – Part 2”

  1. […] Automated Acceptance Testing iOS Mobile Apps with Appium, Cucumber-JVM, Jenkins, and Sauce Labs – … → […]

  2. […] Automated Acceptance Testing iOS Mobile Apps with Appium, Cucumber-JVM, Jenkins, and Sauce Labs – … […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s