Requirement 1 – placing pieces

We should start by defining the boundaries and what constitutes an invalid placement of a piece.


A piece can be placed on any empty space of a 3×3 board.

We can split this requirement into three tests:

  • When a piece is placed anywhere outside the x-axis, then RuntimeException is thrown
  • When a piece is placed anywhere outside the y-axis, then RuntimeException is thrown
  • When a piece is placed on an occupied space, then RuntimeException is thrown

As you can see, the tests related to this first requirement are all about validations of the input argument. There is nothing in the requirements that says what should be done with those pieces.

Before we proceed with the first test, a brief explanation of how to test exceptions with JUnit is in order.

Starting from Release 4.7, JUnit introduced a feature called Rule. It can be used to do many different things (more information can be found at https://github.com/junit-team/junit/wiki/Rules), but in our case we're interested in the ExpectedException rule:

public class FooTest {
  @Rule
  public ExpectedException exception = ExpectedException.none();
@Test public void whenDoFooThenThrowRuntimeException() { Foo foo = new Foo(); exception.expect(RuntimeException.class); foo.doFoo(); } }

In this example, we defined that the ExpectedException is a rule. Later on, in the doFooThrowsRuntimeException test, we're specifying that we are expecting the RuntimeException to be thrown after the Foo class is instantiated. If it is thrown before, the test will fail. If the exception is thrown after, the test is successful.

@Before can be used to annotate a method that should be run before each test. It is a very useful feature with which we can, for example, instantiate a class used in tests or perform some other types of actions that should be run before each test:

private Foo foo; 

@Before 
public final void before() { 
  foo = new Foo(); 
} 

In this example, the Foo class will be instantiated before each test. This way, we can avoid having repetitive code that would instantiate Foo inside each test method.

Each test should be annotated with @Test. This tells JunitRunner which methods constitute tests. Each of them will be run in a random order so make sure that each test is self-sufficient and does not depend on the state that might be created by other tests:

@Test 
public void whenSomethingThenResultIsSomethingElse() { 
  // This is a test method 
} 

With this knowledge, you should be able to write your first test and follow it with the implementation. Once done, compare it with the solution provided.

Use descriptive names for test methods. 

One of the benefits is that it helps to understand the objective of tests.

Using method names that describe tests is beneficial when trying to figure out why some tests failed or when the coverage should be increased with more tests. It should be clear what conditions are set before the test, what actions are performed, and what the expected outcome is.

There are many different ways to name test methods. My preferred method is to name them using the given/when/then syntax used in BDD scenarios. Given describes (pre)conditions, When describes actions, and Then describes the expected outcome. If a test does not have preconditions (usually set using the @Before and @BeforeClass annotations), Given can be skipped.

Do not rely only on comments to provide information about test objectives. Comments do not appear when tests are executed from your favorite IDE, nor do they appear in reports generated by the CI or build tools.

Besides writing tests, you'll need to run them as well. Since we are using Gradle, they can be run from the command prompt:

    $ gradle test

IntelliJ IDEA provides a very good Gradle tasks model that can be reached by clicking on View|Tool Windows|Gradle. It lists all the tasks that can be run with Gradle (test being one of them).

The choice is yours—you can run tests in any way you see fit, as long as you run all of them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.26.185