In this series of articles, you can learn how to use automated software testing with Behavior-Driven Development. In part 1, I described the main assumptions of the process. Now it is time for BDD testing tools.
In this part, I will present select BDD frameworks that I use as testing user interfaces (User Interface testing).
Calabash tutorial for mobile app testing
This is a BDD framework for writing automated tests for Android, iOS, and hybrid platforms. Calabash uses the Cucumber framework to describe the behavior of an application in natural language. An interesting option is to install Calabash Sandbox on both Windows and MacOS platforms.
Calabash-Android installation
Installation instructions can be found here: GitHub – Calabash Android
Requirements:
- Installation of Ruby >= 2.0
- add permission to the application:
<uses-permission android:name="android.permission.INTERNET"/>
How to use Calabash?
To begin your adventure with Calabash, first, you have to generate a directory structure. To do so, you need to enter the command: calabash-android gen
.
The result should appear as below:
features
|_support
| |_app_installation_hooks.rb
| |_app_life_cycle_hooks.rb
| |_env.rb
| |_hooks.rb
|_step_definitions
| |_calabash_steps.rb
|_my_first.feature
In my_first.feature
you define features
and scenarios
, whereas in calabash_steps.rb
– we can define our steps (behaviors
).
Calabash provides many default steps (it is worth looking here: GitHub – Canned steps and here: GitHub – Steps, but you can also define your own steps for the application you are working on.
Calabash-Android example
I have designed an example application that calculates the volume for a circle, rectangle and cube. It looks more or less like this:
Writing a test
Feature: Circle feature
Scenario: As a user I can calculate area of circle
Then I press view with id "circle_button"
Then I enter text "55" into field with id "radius_edittext"
Then I go back
Given I press the "Calculate" button
Then I see the text "Area of circle is 9503.32"
Scenario: As a user I write bad radius
Then I press view with id "circle_button"
Then I enter text "-4" into field with id "radius_edittext"
Then I go back
Given I press the "Calculate" button
Then I see the text "Radius must be non-negative"
Then I clear "radius_edittext"
Then I go back
Given I press the "Calculate" button
Then I see the text "Incorrect data"
Feature: Square feature
Scenario: As a user I can calculate area of square
Then I press view with id "square_button"
Then I enter text "5" into field with id "value_x_edittext"
Then I enter text "8" into field with id "value_y_edittext"
Then I go back
Given I press the "Calculate" button
Then I see the text "Area of square is 40"
Running a test
In order to run the test, we need to build a server. We can do this by using the command:
calabash-android build <apk>
Once we have the server, nonetheless, if the keys which we signed the server and application are different, we have to use the following command:
calabash-android resign <apk>
The test start-up comes after issuing the following command:
calabash-android run <apk>
Done! Let’s check out next framework now!
Green Coffee
Green Coffee uses two frameworks: Gherkin and Espresso (GitHub – Espresso setup). It allows you to run Android instrumentation tests.
Green Coffee is a good alternative to Calabash – in that it doesn’t require the installation of Ruby. In addition to the tool not being cross platform (it can only be used within Android), we have to define the steps we want to use within the tests in our application ourselves in this framework.
Green Coffee installation
Installation instructions can be found here: GitHub – Green-coffee.
dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile 'com.mauriciotogneri:greencoffee:2.0.1'
}
defaultConfig
{
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
Directory Structure
We store features
in the assets
folder in androidTest
. While in java/<package>/test
, we put step definitions
and classes
that run the test.
Green Coffee Test Example
@RunWith(Parameterized.class)
public class SquareActivityTest extends GreenCoffeeTest {
@Rule
public ActivityTestRule activity = new ActivityTestRule<>(MainActivity.class);
public SquareActivityTest(ScenarioConfig scenario) {
super(scenario);
}
@Parameterized.Parameters
public static Iterable scenarios() throws IOException
{
return new GreenCoffeeConfig()
.withFeatureFromAssets("assets/square.feature")
.scenarios();
}
@Test
public void test()
{
start(new DefaultSteps(), new SquareActivityStep());
}
}
As you see, initially we start up the first activity that we want to test:
@Rule
public ActivityTestRule activity = new ActivityTestRule<>(MainActivity.class);
Next, we define the parameter which is injected into the test constructor. For example, a path for saving screenshots can be added to the parameter GreenCoffeeConfig
.
@Parameterized.Parameters
public static Iterable scenarios() throws IOException
{
return new GreenCoffeeConfig()
.withFeatureFromAssets("assets/square.feature")
.scenarios();
}
Finally, we define which step definitions the test will have access to:
@Test
public void test()
{
start(new DefaultSteps(), new SquareActivityStep());
}
Example test steps:
public class DefaultSteps extends BasicStep {
@Then("^I enter text \"([^\"]*)\" into field with id \"([^\"]*)\"$")
public void enterTextToEditTextWithId(String text, String id) throws NoSuchFieldException, IllegalAccessException {
onView(withId(resolve(id))).perform(clearText(), typeText(text), closeSoftKeyboard());
}
@Given("^I press the \"([^\"]*)\" button$")
public void pressButtonWithText(String text) {
onView(withText(text)).perform(click());
}
@Then("^I see the text \"([^\"]*)\"$")
public void seeText(String text) {
onView(withText(text)).check(matches(isDisplayed()));
}
}
A step can be defined with the help of the following properties:
- keyword:
@When, @Given, @Then
- a regular expression that describes a given step („<Regex corresponding to the appropriate behavior written in the feature file>”)
BasicStep class
To perform a specific action the object ID is necessary. BasicStep can be used to make searching for elements by ID easier
public class BasicStep extends GreenCoffeeSteps {
public int resolve(String id) throws NoSuchFieldException, IllegalAccessException {
Class<?> clazz = R.id.class;
Field field = clazz.getField(id);
return field.getInt(field);
}
}
Example usage of class:
Feature: Login screen to authenticate users
Scenario: As a user I can calculate area of circle
Then I enter text "55" into field with id "radius_edittext"
Given I press the "Calculate" button
Then I see the text "Area of circle is 9503.32"
Scenario: As a user I write bad radius
Then I enter text "-4" into field with id "radius_edittext"
Given I press the "Calculate" button
Then I see the text "Radius must be non-negative"
Then I clear "radius_edittext"
Given I press the "Calculate" button
Then I see the text "Incorrect data
Test Suite (grouping)
Another useful Green Coffee option is to group tests into one. This allows one test to run all the grouped tests.
@RunWith(Suite.class)
@Suite.SuiteClasses({
CircleActivityTest.class,
SquareActivityTest.class
})
public class AllTests {
}
We put all of the selected tests that we want to run simultaneously into Suite.SuiteClasses
.
User Interface Testing
In this part, I have talked about Calabash and Green Coffee – selected frameworks used for testing user interfaces (User Interface testing). In the next section, I will describe Spock – unit testing framework.
You can find the source code on my GitHub.
Popular posts
From Hype to Hard Hats: Practical Use Cases for AI chatbots in Construction and Proptech.
Remember the multimedia craze in the early 2000s? It was everywhere, but did it truly revolutionize our lives? Probably not. Today, it feels like every piece of software is labeled "AI-powered." It's easy to dismiss AI chatbots in construction as just another tech fad.
Read moreFears surrounding external support. How to address concerns about outsourcing software development?
Whether you’ve had bad experiences in the past or no experience at all, there will always be fears underlying your decision to outsource software development.
Read moreWhat do you actually seek from external support? Identify what’s preventing you from completing a project on time and within budget
Let’s make it clear: if the capabilities are there, a project is best delivered internally. Sometimes, however, we are missing certain capabilities that are required to deliver said project in a realistic timeline. These may be related to skills (e.g. technical expertise, domain experience), budget (hiring locally is too expensive) or just capacity (not enough manpower). What are good reasons for outsourcing software development?
Read more