Skip to content

Test definition

Mauricio Togneri edited this page Apr 13, 2018 · 29 revisions

A test definition is a class that extends from GreenCoffeeTest and its goal is to declare:

  • The Activity that will be instantiated to run the tests
  • The feature that will be parsed to extract the scenarios to execute
  • The step definitions that will be used during the test

Example

@RunWith(Parameterized.class)
public class LoginFeatureTest extends GreenCoffeeTest
{
    @Rule
    public ActivityTestRule<LoginActivity> activity = new ActivityTestRule<>(LoginActivity.class);

    public LoginFeatureTest(ScenarioConfig scenarioConfig)
    {
        super(scenarioConfig);
    }

    @Parameters(name = "{0}")
    public static Iterable<ScenarioConfig> scenarios() throws IOException
    {
        return new GreenCoffeeConfig(true) // automatically take a screenshot if a test fails
                        .withFeatureFromAssets("assets/login.feature")
                        .scenarios(
                            new Locale("en", "GB"),
                            new Locale("es", "ES")
                        );
    }

    @Test
    public void test()
    {
        start(new LoginSteps());
    }
}

Be aware that all test definitions have to use the annotation @RunWith(Parameterized.class), extend from GreenCoffeeTest and have the following constructor:

public TestDefinitionClass(ScenarioConfig scenarioConfig)
{
    super(scenarioConfig);
}

Activity declaration

In the previous example we can see that the tests will be executed using an instance of the activity LoginActivity:

@Rule
public ActivityTestRule<LoginActivity> activity = new ActivityTestRule<>(LoginActivity.class);

The declared activity will be used just as an entry point for the tests and of course we can start new activities during the tests.

Feature declaration

To declare the feature that will be used we have to declare a static method with the annotation @Parameters that returns the list of scenario configurations that will be used during the tests. In our case:

@Parameters(name = "{0}")
public static Iterable<ScenarioConfig> scenarios() throws IOException
{
    return new GreenCoffeeConfig(true) // automatically take a screenshot if a test fails
                        .withFeatureFromAssets("assets/login.feature")
                        .scenarios(
                            new Locale("en", "GB"),
                            new Locale("es", "ES")
                        ); // the locales used to run the scenarios (optional)
}

To return the list of scenarios we use the class GreenCoffeeConfig.

The class accepts an optional parameter to indicate if it should automatically take a screenshot in case that a scenario fails. Screenshots will be stored in the folder Android/data/your_package/files/screenshots. This helps to find the bug by seeing what was on the screen at the moment of failure. If the parameter is set to false or omitted, no screenshots will be taken in case of error.

This class also allows you to load a feature from a string, from a file, from a URL or from an input stream. You can filter the scenarios based on their tags, for example:

@Parameters(name = "{0}")
public static Iterable<ScenarioConfig> scenarios() throws IOException
{
    return new GreenCoffeeConfig()
                    .withFeatureFromAssets("assets/login.feature")
                    .withTags("@tag1", "@tag2")
                    .scenarios();
}

In the previous example we load the features from a file in the assets folders and we return only the scenarios that have either the tag @tag1 or @tag2 (or both). If a scenario in the feature doesn't have any of those tags it will not be executed during the test.

Finally, the method scenarios accepts a list of locales that will be used to run the scenarios. For example:

@Parameters(name = "{0}")
public static Iterable<ScenarioConfig> scenarios() throws IOException
{
    return new GreenCoffeeConfig()
                        .withFeatureFromAssets("assets/login.feature")
                        .scenarios(
                            new Locale("en", "GB"),
                            new Locale("es", "ES")
                        );
}

In the previous example, the scenarios will be executed twice: one with the locale in English and the other with the locale in Spanish. If no locales are defined, the default one will be used.

Step definitions declaration

Each test definition should declared only one method with the annotation @Test. In our case:

@Test
public void test()
{
    start(new LoginSteps());
}

You can use any name for the method as long as it is the only one using the annotation and it must call the method start from the parent class. This method accepts a list of classes that contain the step definitions that will be used to match the steps in the scenarios.

Before the scenario starts

The test definition class can override the method beforeScenarioStarts which will be called, as its name indicates, before each scenario starts.

@Override
protected void beforeScenarioStarts(Scenario scenario, Locale locale)
{
    // do something
}

This is an ideal place to, for example, clear all the application's data in order to perform the test as if it's the first execution.

After the scenario ends

The test definition class can override the method afterScenarioEnds which will be called, as its name indicates, after each scenario ends.

@Override
protected void afterScenarioEnds(Scenario scenario, Locale locale)
{
    // do something
}

Next chapter: Step definitions