Chapters

Hide chapters

Android Test-Driven Development by Tutorials

Second Edition · Android 11 · Kotlin 1.5 · Android Studio 4.2.1

Section II: Testing on a New Project

Section 2: 8 chapters
Show chapters Hide chapters

Section III: TDD on Legacy Projects

Section 3: 8 chapters
Show chapters Hide chapters

A. Appendix A: Other Related Techniques
Written by Fernando Sproviero

TDD focuses on writing tests for classes and methods before writing code to support the app’s features. While this approach might be useful for the developers, some argue that it doesn’t consider the end user since they tend to focus on the expected behavior of the app or its use cases. Writing tests for functionality may even be easier to validate with the users.

After exploring TDD and reading this chapter, you’ll discover that other techniques and frameworks exist to enhance or complement TDD.

Acceptance test-driven development

In Acceptance test-driven development (ATDD) the entire team first defines what the acceptance criteria of a feature is before development on that feature starts.

Here’s how it works: The team collaborates with the end users. Based on that collaboration, the team writes one or more acceptance tests for each requirement. After that, the development team writes the code needed for the requirement to pass those acceptance tests.

ATDD focuses on the acceptance criteria agreed upon with the users. If these tests pass, you can assume the users will be happy with your app. This process gives you an idea of the feature development progress and also avoids gold-plating, which means to over-develop features or add functionality that end users don’t need or want.

With ATDD, you can take each requirement and write it in the user story format. Once you have that, you can write the acceptance tests for each one. That’s why, sometimes, this technique is also called Story Test-Driven Development (STDD).

Here’s an example template you might use to write a user story:

As a <role> I can <capability>, so that <receive benefit>.

Once you have that, you can turn it into this:

As a seller, I can publish an item so that I can sell it.
As a buyer, I can search for an item so that I can purchase it.

You can write user acceptance tests (UATs), also known as Story Tests, in a plain document or even a spreadsheet. Because these tests are not technical, any non-technical person can read and modify them. Once the team is satisfied, developers can use these tests as input to translate into test code. For example, in an app that has a login feature:

  1. Open the application.
  2. Log in with invalid <username> and <password>.
  3. Verify an error message is shown: “Invalid <username> and/or <password>!”

Or you may have a spreadsheet with inputs and expected output, for example, in a calculator app:

Number  Operator   Number  Expected
1       +          2       3
2       *          0       0

These story tests provide the following advantages:

  • You can use them to communicate between all of the roles of the team.
  • They’re easier to agree with the final user.
  • The examples are concrete.
  • Analysts, developers, testers and the end users have a more active role. They’re more involved and they all work together in creating possible scenarios. They understand the stories, the examples and the acceptance criteria.

Behavior driven development

Behavior Driven Development (BDD) is an extension of TDD. You might think of BDD as an enhanced version of TDD.

BDD explains that behaviors should drive the development of an app’s features. The behaviors are explained with examples in a simple language that’s understandable by all of the people involved in the app. That means that developers, testers and analysts can all collaborate in BDD. Usually, BDD is used as a tool that allows creating tests in plain English and allows collaboration between technical and non-technical members of the team.

The main focus of TDD is to write tests first and to think about designing the features. BDD not only does that, but also uses a natural language to describe the tests. To begin with, it pays attention to tests method naming. For example, the name of the methods could start with should, or use the given/when/then format instead of the traditional naming, which starts with test. This method naming was selected to focus and better describe a behavior. The idea is to break down a test scenario into three parts:

  • given: Describes the state of the world before you begin the behavior you’re specifying in this scenario. These are the pre-conditions to the test.

  • when: You specify the behavior.

  • then: Here you describe the expected changes due to the behavior.

Instead of writing a test class per class of a feature, BDD suggests writing a class per requirement. It also enforces writing code that uses the same business language, so there’s a ubiquitous language. This means that analysts and developers use the same language. For example, if you’re writing a game where the analyst states that cars are racing, you should have a class named Car and not a class called Automobile.

BDD doesn’t care about how the app is architected or implemented; its main focus is on the behavior.

In BDD, you can write the acceptance criteria as follows:

Given [a context]
When [an event happens]
Then [assert something]

Cucumber is a tool that supports BDD using this style for the acceptance criteria. It reads executable specifications that you provide written in plain English and it’ll validate that your app does what those specifications state. The specifications consists of multiple examples, or scenarios.

For example, suppose you’re writing a calculator application for Android. You could write the following feature file for Cucumber:

Feature: Calculate a result
  Perform an arithmetic operation on two numbers using a mathematical operator

  Scenario Outline: Enter a digit, an operator and another digit
    Given I have a CalculatorActivity
    When I press <num1>
    And I press <op>
    And I press <num2>
    And I press =
    Then I should see "<result>" on the display

  Examples:
    | num1 | num2 | op | result   |
    | 9    | 8    | +  | 17.0     |
    | 7    | 6    | –  | 1.0      |
    | 5    | 4    | x  | 20.0     |
    | 3    | 2    | /  | 1.5      |
    | 1    | 0    | /  | Infinity |

Here’s how this works:

You specify the name of the feature, give a description and write the scenario using the given/when/then format, in plain English.

You also have to translate those steps into Java or Kotlin. These steps are known as step definitions, For example:

@When("I press {operator}")
fun i_press_op(op: Char) {
  when (op) {
    '+' -> onView(withId(R.id.btn_op_add)).perform(click())
    '–' -> onView(withId(R.id.btn_op_subtract)).perform(click())
    'x' -> onView(withId(R.id.btn_op_multiply)).perform(click())
    '/' -> onView(withId(R.id.btn_op_divide)).perform(click())
    '=' -> onView(withId(R.id.btn_op_equals)).perform(click())
  }
}

The step I press {operator} is parameterized with an operator. Therefore, you create a function that handles this and translates each of the operators into an action within the UI. In this case, it’s pressing the corresponding button. This type of code is often called glue-code because it maps the English sentences into a lower-level language such as Kotlin.

By having enough step definitions mapped, you can let a non-technical person write various scenarios.

ATDD vs. BDD

You may find that some people consider both techniques the same thing since they focus on the end user requirements, understanding behaviors and generating similar outcomes.

Here’s a closer look at each technique you’ve seen so far:

  • TDD enforces good class design, ensuring that those classes work correctly in units and collaboration with others. ATDD and BDD enforce building the appropriate app for the user.

  • ATDD focuses on acceptance tests written in collaboration with the stakeholders. Sometimes these tests are written using spreadsheets and are understandable by non-technical people. However, at some point, the technical team needs to translate these tests to an automatizable test in code.

  • In BDD, you try to bring the business team and the technical team closer by using a common language that’s understandable by both parties. Using the given/when/then style, even non-technical people can write tests that can directly run in automated environments.

  • ATDD and BDD both have an objective of tackling down any misunderstood requirements inside of the team. All team members should interpret them the same way.

No matter which technique you choose or if you take parts of each one, they’re all great practices to explore on your team.

Key points

  • In TDD, you need to write tests before adding or modifying features.
  • You write tests in a technical language such as Java or Kotlin.
  • The people involved in TDD need to have a technical background. But in BDD or ATDD, both technical and non-technical people on the team can get involved.
  • TDD focuses on the implementation of the features. BDD focuses on the behavior. ATDD focuses on capturing the requirements and the acceptance criteria.
  • Each of the techniques outlined in this chapter enforces creating tests before adding or modifying features. This is in contrast to traditional development.

Where to go from here?

If you want to learn more about other TDD techniques, look at the following:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.