Skip to content

Organisation and Policy Implementation

Estimated time to read: 3 minutes

Organisation

Organising tests can drastically improve readability of code.

Using the @Nested annotation, inner classes can be nested within another class. These nested classes can have their own @BeforeEach and @AfterEach annotations also.

@DisplayName can also be used to declare the display name of the test.

Note

Tests should follow BDD, see 103 - Writing Tests. This allows tests to be written in plain english.

// ...
public class AirportTest {

 @Test
 public void testEconomyFlightUsualPassenger() {
  Flight economyFlight = new EconomyFlight("1");
  Passenger mike = new Passenger("Mike", false);

  assertEquals("1", economyFlight.getId());
  assertEquals(true, economyFlight.addPassenger(mike));
  assertEquals(1, economyFlight.getPassengersList().size());
  assertEquals("Mike", economyFlight.getPassengersList().get(0).getName());

  assertEquals(true, economyFlight.removePassenger(mike));
  assertEquals(0, economyFlight.getPassengersList().size());
 }

 @Test
 public void testEconomyFlightVipPassenger() {
  Flight economyFlight = new EconomyFlight("1");
  Passenger john = new Passenger("John", true);

  assertEquals("1", economyFlight.getId());
  assertEquals(true, economyFlight.addPassenger(john));
  assertEquals(1, economyFlight.getPassengersList().size());
  assertEquals("John", economyFlight.getPassengersList().get(0).getName());

  assertEquals(false, economyFlight.removePassenger(john));
  assertEquals(1, economyFlight.getPassengersList().size());
 }

 @Test
 public void testBusinessFlightUsualPassenger() {
  Flight businessFlight = new BusinessFlight("2");

  Passenger mike = new Passenger("Mike", false);

  assertEquals(false, businessFlight.addPassenger(mike));
  assertEquals(0, businessFlight.getPassengersList().size());
  assertEquals(false, businessFlight.removePassenger(mike));
  assertEquals(0, businessFlight.getPassengersList().size());

 }

 @Test
 public void testBusinessFlightVipPassenger() {
  Flight businessFlight = new BusinessFlight("2");

  Passenger john = new Passenger("John", true);

  assertEquals(true, businessFlight.addPassenger(john));
  assertEquals(1, businessFlight.getPassengersList().size());
  assertEquals(false, businessFlight.removePassenger(john));
  assertEquals(1, businessFlight.getPassengersList().size());

 }
}
// ...
public class AirportTest {

 @DisplayName("Given there is an economy flight")
 @Nested
 class EconomyFlightTest {

  private Flight economyFlight;

  @BeforeEach
  void setUp() {
   economyFlight = new EconomyFlight("1");
  }

  @Test
  public void testEconomyFlightUsualPassenger() {
   Passenger mike = new Passenger("Mike", false);

   assertEquals("1", economyFlight.getId());
   assertEquals(true, economyFlight.addPassenger(mike));
   assertEquals(1, economyFlight.getPassengersList().size());
   assertEquals("Mike", economyFlight.getPassengersList().get(0).getName());

   assertEquals(true, economyFlight.removePassenger(mike));
   assertEquals(0, economyFlight.getPassengersList().size());
  }

  @Test
  public void testEconomyFlightVipPassenger() {
   Passenger john = new Passenger("John", true);

   assertEquals("1", economyFlight.getId());
   assertEquals(true, economyFlight.addPassenger(john));
   assertEquals(1, economyFlight.getPassengersList().size());
   assertEquals("John", economyFlight.getPassengersList().get(0).getName());

   assertEquals(false, economyFlight.removePassenger(john));
   assertEquals(1, economyFlight.getPassengersList().size());
  }

 }

 @DisplayName("Given there is a business flight")
 @Nested
 class BusinessFlightTest {
  private Flight businessFlight;

  @BeforeEach
  void setUp() {
   businessFlight = new BusinessFlight("2");
  }

  @Test
  public void testBusinessFlightUsualPassenger() {
   Passenger mike = new Passenger("Mike", false);

   assertEquals(false, businessFlight.addPassenger(mike));
   assertEquals(0, businessFlight.getPassengersList().size());
   assertEquals(false, businessFlight.removePassenger(mike));
   assertEquals(0, businessFlight.getPassengersList().size());

  }

  @Test
  public void testBusinessFlightVipPassenger() {
   Passenger john = new Passenger("John", true);

   assertEquals(true, businessFlight.addPassenger(john));
   assertEquals(1, businessFlight.getPassengersList().size());
   assertEquals(false, businessFlight.removePassenger(john));
   assertEquals(1, businessFlight.getPassengersList().size());

  }

 }

}

Business Policy Implementation

When adding new features to the codebase, it is imperative that the business policy flows are implemented as requested.

For example, the flowchart below states the requirement for new functionality to be included in the application.

graph TD
    ZZ(Input) --> A
 A[Calculate Bonus Points] -->|Passenger is VIP?| B{ }
    B --> |Yes|C[Bonus Points = Mileage / 10]
 B --> D[Bonus Points = Mileage / 20]
 C --> E{ }
 D --> E{ }
 E --> F(Output)
  1. Tests should be scaffolded first, written in plain english, to translate the flowchart to code.
  2. Tests should then be written, following the scaffold, that check against the policy 3 Tests should be run and expected to return failures as the the logic has not yet been implemented into the application.
  3. Code should be introduced into the application codebase that effectively implements the required policy
  4. Tests should be run again and, given a sound implementation, should pass.