"Knowing is not enough; we must apply. Willing is not enough; we must do." | ||
--Bruce Lee |
The red-green-refactor technique is the basis of TDD. It is a game of ping pong in which we are switching between tests and implementation code at great speed. We'll fail, then we'll succeed and, finally, we'll improve.
We'll develop a Tic-Tac-Toe game by going through each requirement one at a time. We'll write a test and see if it fails. Then, we'll write a code that implements that test, run all the tests, and see them succeed. Finally, we'll refactor the code and try to make it better. This process will be repeated many times until all the requirements are successfully implemented.
We'll start by setting up the environment with Gradle and JUnit. Then, we'll go a bit deeper into the red-green-refactor process. Once we're ready with the setup and theory, we'll go through the high-level requirements of the application.
With everything set, we'll dive right into the code—one requirement at a time. Once everything is done, we'll take a look at the code coverage and decide whether it is acceptable or more tests need to be added.
The following topics will be covered in this chapter:
You are probably familiar with the setup of Java projects. However, you might not have worked with IntelliJ IDEA before or you might have used Maven instead of Gradle. In order to make sure that you can follow the exercise, we'll quickly go through the setup.
The main purpose of this book is to teach TDD, so we will not go into detail about Gradle and IntelliJ IDEA. Both are used as an example. All exercises in this book can be done with different choices for IDE and build tools. You can, for example, use Maven and Eclipse instead. For most, it might be easier to follow the same guidelines as those presented throughout the book, but the choice is yours.
The following steps will create a new Gradle
project in IntelliJ IDEA:
In the New Project dialog, we can observe that IDEA has already created the build.gradle
file. Open it and you'll see that it already contains the JUnit dependency. Since this is our framework of choice in this chapter, there is no additional configuration that we should do. By default, build.gradle
is set to use Java 1.5 as a source compatibility setting. You can change it to any version you prefer. The examples in this chapter will not use any of the Java features that came after version 5, but that doesn't mean that you cannot solve the exercise using, for example, JDK 8.
Our build.gradle
file should look like the following:
apply plugin: 'java' version = '1.0' repositories { mavenCentral()` } dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' }
Now, all that's left is to create packages that we'll use for tests and the implementation. From the Project dialog, right click to bring the context menu and select New | Directory. Type src/test/java/com/packtpublishing/tddjava/ch03tictactoe
and click on the OK button to create the tests
package. Repeat the same steps with the src/main/java/com/packtpublishing/tddjava/ch03tictactoe
directory to create the implementation package.
Finally, we need to the make test and implementation classes. Create the TicTacToeSpec
class inside the com.packtpublishing.tddjava.ch03tictactoe
package in the src/test/java
directory. This class will contain all our tests. Repeat the same for the TicTacToe
class in the src/main/java
directory.
Your Project structure should be similar to the one presented in the screenshot below:
The source code can be found in the 00-setup branch of the tdd-java-ch03-tic-tac-toe
Git repository at https://bitbucket.org/vfarcic/tdd-java-ch03-tic-tac-toe/branch/00-setup.
Always separate tests from the implementation code.
The benefits are as follows: this avoids accidentally packaging tests together with production binaries; many build tools expect tests to be in a certain source directory.
A common practice is to have at least two source directories. The implementation code should be located in src/main/java
and the test code in src/test/java
. In bigger projects, the number of source directories can increase, but the separation between implementation and tests should remain.
Build tools such as Maven and Gradle expect source directories' separation, as well as naming conventions.
That's it. We're set to start working on our Tic-Tac-Toe application using JUnit as the testing framework of choice and Gradle for compilation, dependencies, testing, and other tasks. In Chapter 1, Why Should I Care for Test-driven Development?, you first encountered the red-green-refactor procedure. Since it is the cornerstone of TDD and is the main objective of the exercise in this chapter, it might be a good idea to go into a bit more detail before we start the development.