Skip to main content
← Blog
Android

How to Do TDD in Android — Part 2: Unit Tests

3 min read
How to Do TDD in Android — Part 2: Unit Tests

Continuing the TDD in Android series — in this installment we write our first unit tests.

As we saw in Part 1, we have a project set up using the MVP pattern. The app will be a simple login screen with the following behavior:

  • Maximum 3 login attempts
  • Username/password validation

Creating the presentation layer

First, create a login package in the project and inside it a LoginPresenter class:

public class LoginPresenter {
}

With the cursor on the class name, press SHIFT + CTRL + T — Android Studio will ask you to create a new test called LoginPresenterTest.

Now we have our presenter and its test class. Time to write the tests.

Writing the first tests

The first thing to test: whether the maximum number of login attempts has been exceeded. In LoginPresenterTest:

@Test
public void checkIfLoginAttemptIsExceeded() {
    LoginPresenter loginPresenter = new LoginPresenter();
    Assert.assertEquals(1, loginPresenter.newLoginAttempt());
    Assert.assertEquals(2, loginPresenter.newLoginAttempt());
    Assert.assertEquals(3, loginPresenter.newLoginAttempt());
    Assert.assertTrue(loginPresenter.isLoginAttemptExceeded());
}

The methods newLoginAttempt and isLoginAttemptExceeded will be highlighted in red — they don’t exist yet. This is the first step in the TDD cycle (red → refactor → green).

Next, create those methods in LoginPresenter:

public class LoginPresenter {
    public int newLoginAttempt() {
        return 0;
    }

    public boolean isLoginAttemptExceeded() {
        return false;
    }
}

If you run the test now it fails — the methods exist but don’t do anything yet. Now implement them:

public class LoginPresenter {
    private int currentLoginAttempt = 0;
    private static final int MAX_LOGIN_ATTEMPT = 3;

    public int newLoginAttempt() {
        return ++currentLoginAttempt;
    }

    public boolean isLoginAttemptExceeded() {
        return currentLoginAttempt >= MAX_LOGIN_ATTEMPT;
    }
}

Run the test again — it passes and turns green.

Never lose sight of the green — @flipper83

Exercise: implement the inverse test yourself:

@Test
public void checkIfLoginAttemptIsNotExceeded() {
    // your implementation here
}

Checking username and password

Now let’s verify that the entered credentials are correct:

@Test
public void checkUserAndPasswordIsCorrect() {
    LoginPresenter loginPresenter = new LoginPresenter();
    Assert.assertTrue(loginPresenter.checkUserPassword("user", "password"));
}

The checkUserPassword method is red — implement it:

public boolean checkUserPassword(String user, String password) {
    boolean ret = true;
    if (isLoginAttemptExceeded()) {
        ret = false;
    } else if (user.equals(USER) && password.equals(PASSWORD)) {
        ret = true;
    } else {
        ret = false;
        newLoginAttempt();
    }
    return ret;
}

The complete LoginPresenter class:

public class LoginPresenter {
    private int currentLoginAttempt = 0;
    private static final int MAX_LOGIN_ATTEMPT = 3;
    private static final String USER = "user";
    private static final String PASSWORD = "password";

    public int newLoginAttempt() {
        return ++currentLoginAttempt;
    }

    public boolean isLoginAttemptExceeded() {
        return currentLoginAttempt >= MAX_LOGIN_ATTEMPT;
    }

    public boolean checkUserPassword(String user, String password) {
        boolean ret = true;
        if (isLoginAttemptExceeded()) {
            ret = false;
        } else if (user.equals(USER) && password.equals(PASSWORD)) {
            ret = true;
        } else {
            ret = false;
            newLoginAttempt();
        }
        return ret;
    }
}

Notice something: by using MVP, we’ve fully implemented and tested the logic of a login screen before writing a single line of UI code.

Download the current state of the project: https://github.com/jamontes79/TDD_Ejemplo/tree/f7549820c11db027fc70196c828ccb8bcb5e33ac

In the next installment we’ll build the UI and work with Mockito. What do you think of TDD so far?


More in Android