Share it now!

What is TDD? Where do we start? How do we do a test?

TDD is a methodology to validate classes/methods/attributes that will be created. By example, if it were asked to create a method that searches the data from a house. With TDD, it is possible to validate all situations that the developer might imagine, like: house without number, null as a method return, owner has died and etc.

Where do we start? We need to configure do JUnit so it will make our vision about TDD clearer. I’m sorry if you already know how to do this, it will be fast (we got to help the rookie!).
I will be using the Eclipse as IDE, but TDD should (and must) be applied to all kind of IDEs. Just in case you don’t use JUnit as you test framework, the concept that you will see in here it is applicable to TDD in every framework.

PS.: The little details such to create packages/classes or to open an Eclipse’s view you may find here: Creating a WebServer.

I’ve created a Project named TDD. Then, using “Package Explorer” view, add JUnit library:
Config 01
Config 02
Config 03

We are going to write a test to this user case: Your project will have a class named User that will store all information about each person logon/logoff in your software. As requirement, this class will have a method that will block the user access to the software. Let’s create a package name “test.com” and a class named TestUser inside this package.

package test.com;

public class TestUser {
}

The TDD ideology is that we should start a test by its end. (WHAT?!) In the software companies today is common to start writing a code from where it should start, but with TDD we start it from its ending. Why? By coding using TDD, we got an idea that will lead us to where we supose to be going, we avoid the creation of unnecessary parameters, the created methods are more cohesive and then it goes…
When we write tests cases we must have this sequence in mind: “Red, Green and Refactor”. What does this mean? When we write tests cases using JUnit we have a red bar (that we will see very soon) showing red status when our tests fail and green when all tests are executed with success.

To get the expected result we might use methods that will guarantee that result for us. We will be using assertEquals(desired value, returned value). In our user case, what do we want? Always that the User got a denied access our method should return true. Let’s do some code?

package test.com;
import static org.junit.Assert.*;
import org.junit.Test;

public class TestUser {
    @Test
    public void isUserWithDeniedAccess(){
        assertEquals(true, user.accessDenied);
    }
}

Let’s talk about this code. Observe that we got the annotation “@Test” and when we run the JUnit framework, it will locate all methods with that annotation and will invoke the test validation. We can see the assertEquals that we imported from the JUnit doing an “import static”. Notice that I’m already “trying to access” an object that does not exists in the method or not in the project either. Do you remember when I said that we should start from its ending? Our ending (goal, target) is that the User gets really no access to the software. Even if the class/attribute/methods it is not in the software code yet, as first steps, we will use it regularly. Writing the code by its ending enable us to start to think on the classes name, attributes and etc.

Even if the code does not compile, we are on the way… Small steps… Always small steps.

And to finish our test, the code will be like:

@Test
public void isUserWithDeniedAccess(){
        User user = new User();
        assertEquals(true, user.accessDenied);
}

Observe that the User class was “instantiated” even when it does not exist in our TDD test software. Now we have a test case that we can’t compile.

Are you remembering TDD steps: “Red, Green and Refactor”? To archive the red bar we need first to remove all compile errors. Let’s create our class User inside a package named “com” and create the needed attribute.

package com;
public class User {
    public boolean accessDenied;
}

To finish, create the import statement in our test class (TestUser):

import com.User;

We are ready to get the read bar. To run the test using the JUnit just right click on the test class and go to “Run as > JUnit Test”.
Running JUnit

The red bar gives us the message that we are ready to work in our method, so the method will return the desired value. We start with an error to be sure that, when we get the green bar, our method is really working as we wished. In our situation, we are doing a simple test, but if we were doing a complex method, would give us the assurance that that we got our goal complete. Using a test unit, allow us to not need to build the application every time to test our recently created method. We just need to execute the tests and check the result of our coding.

Our next step will be to get the green bar. Usually at this part of the process we write the code to our method. This simple use case that we are doing does not need a method to be tested yet; we just need to change the attribute value. Our test is the one that does the change at the classes attributes, stimulating it to get the test value that we want. That’s why we are not changing our User class, but we are using our test method to stimulate it by changing its value so the User class might behave as we want. TDD works with small steps if you already have a good knowledge you might create the necessaries methods instead taking this small steps. But, it is a good idea to access directly the attributes, by small steps, because we are already testing them. And late, we will do some refactoring to encapsulate those attributes.

@Test
public void isUserWithDeniedAccess(){
        User user = new User();
        user.accessDenied = true;
        assertEquals(true, user.accessDenied);
}

Run JUnit again and you will get a green bar.

And what do we have? The uglier working code ever and there is nothing if we start to looking for OO/Design patterns. What should we do? The methods/attributes refactoring should stay to the end. Let’s add these refactoring at our “TO-DO” list, doing this list will help us to do not forget about something.

Using this approach we got a better code view from where we could change it and “upgrade it”. It’s just get better, we are sure that our new code it is working as we desired. But we need to change our code to have OO patterns before we give the task as completed. We will create a method that will check if the user got his access denied, we need to protect our attribute.

// TestUser.java
package test.com;

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.User;

public class TestUser {
    @Test
    public void isUserReallyBlocked(){
        User user = new User();
        user.accessDenied = true;
        assertEquals(true, user.hasAccesDenied());
    }
}

//User.java
package com;

public class User {
    public boolean accessDenied;

    public boolean hasAccesDenied() {
        return accessDenied;
    }
}

We did not change the attribute access level yet because we still have one more step. Let’s create a “way” that our class change its attribute and protect it from direct access. We will use the concept Tell, don’t ask. Write the code using this “pattern” we will have a clean and bulletproof code and our task will be complete. Our final code would be:

package test.com;

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.User;

public class TestUser {
    @Test
    public void isUserReallyBlocked(){
        User user = new User();
        user.denyAcces();
        assertEquals(true, user.hasAccesDenied());
    }
}

package com;

public class User {
    private boolean accessDenied;

    public boolean hasAccesDenied() {
        return accessDenied;
    }

    public void denyAcces() {
        accessDenied = true;
    }
}

Observe our code and notice that our User class has a clear code, straight and without unnecessary methods. Starting the code by the test allow us to focus more on the behavior. Just run the test again to see the final green bar.

I hope this post might help you on your first steps. Soon, I will post here some good TDD practices so we can get our test case even better. Today post was more to tell about the tool, at next post we will be seeing about TDD concepts.

Good night.