Guest Post: Automated iOS Acceptance Testing with Appium, Cucumber-JVM, Jenkins, and Sauce Labs Part 2

Welcome back to our 3 part series of guest posts written by Unmesh Gundecha, testing guru and author of Selenium Testing Tools Cookbook . Read on to hear about how to use Appium, Cucumber-JVM, Jenkins, and Sauce Labs to do iOS acceptance testing. ___________________________________

Running features with Maven

Before we move forward, we need a configure class which tells Cucumber options for running these features. 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 the above command, Cucumber will suggest some step definitions for missing steps as below You can implement missing steps with the snippets 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 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, let’s create place holders for the steps from sample scenario Add new Java class Bmi_Calculator_Step_Defs to src/test/java/bmicalculator.test package and implement steps for the example feature that we are testing. 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. Developers are done with the initial version of the App and it’s ready for testing. In the next step we will implement the steps by driving the user interface of the App using Appium and Selenium API to check the expected behavior of the application. In this step we need to declare an instance of WebDriver class from Selenium. We will add a setup method setupLocal() which will initialize the driver instance and connect to Appium running on a local machine
private WebDriver driver;

@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 API to interact with the application 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 the feature is run, Cucumber will call the Selenium API which in turn calls the Appium and steps are performed on the App’s user interface in iOS Simulator. At the end of the execution Cucumber will display results as below 1 scenario (1 passed) 16 steps (16 passed) Come back next week to see the final post on running features in the Sauce cloud! Read Part 1

Written by

Bill McGee

Topics

CI/CDAppium