[JAVA] Think of test code that is easy to understand through Comparator testing

When I was reading the test code I wrote four years ago, I realized that the intent of a certain Comparator test code was difficult to read. The content of the test is correct, but I couldn't imagine a specific use case by reading the test.

It's a good test code to some extent as it guarantees the correctness of the product code, but if possible, it would be happier if the maintainers of posterity could read the intention. So, I found a free time and tried to rewrite it.

In this article, we will introduce the old test code and the improved test code, and use it as a memorial service.

Product code

public class TodayReportComparator implements Comparator<Report> {
  @Override
  public int compare(Report lhs, Report rhs) {
    //Good luck
  }
}

TodayReportComparator is a Comparator that sorts today's reports in order to prioritize them.

Old test code

Let's start with the conventional test. This test verifies the result of running Comparator # compare.

public class TodayReportComparatorTest {

  private TodayReportComparator sut;

  @Before
  public void setUp() {
    sut = new TodayReportComparator();
  }

  @Test
public void Today's report comes to the top of yesterday's report() {
    final long now = System.currentTimeMillis();
    lhs = new Report(new Date(now));
    rhs = new Report(new Date(now - 24 * 60 * 60 * 1000));
    assertThat(sut.compare(lhs, rhs), lessThan(0)); //lhs is high
  }

  @Test
public void Today's report comes to the top of tomorrow's report() {
    final long now = System.currentTimeMillis();
    lhs = new Report(new Date(now));
    rhs = new Report(new Date(now + 24 * 60 * 60 * 1000));
    assertThat(sut.compare(lhs, rhs), lessThan(0)); //lhs is high
  }
}

Good point

bad place

In any case, it's a story that you should remember the behavior of Java SE, or you can imagine it if you think about it for a moment. But from the reviewer's point of view, I honestly don't want to use my brain there too much.

New test code

In the newly rewritten test, I focused on what I wanted the result of Collections.sort, which is the actual usage, to be.

public class TodayReportComparatorTest {

  private TodayReportComparator sut;

  @Before
  public void setUp() {
    sut = new TodayReportComparator();
  }

  @Test
public void Today's report comes to the top of yesterday's report() {
    // Given
    final long now = System.currentTimeMillis();
    Report todayReport = new Report(new Date(now));
    Report yesterdayReport = new Report(new Date(now - 24 * 60 * 60 * 1000));

    List<Report> actual = Arrays.asList(
        yesterdayReport,
        todayReport
    );

    List<Report> expected = Arrays.asList(
        todayReport, //The report dated today is at the top
        yesterdayReport
    );

    // When
    Collections.sort(actual, sut);

    // Then
    assertThat(actual, is(expected));
  }

  @Test
public void Today's report comes to the top of tomorrow's report() {
    // Given
    final long now = System.currentTimeMillis();
    Report todayReport = new Report(new Date(now));
    Report tomorrowReport = new Report(new Date(now + 24 * 60 * 60 * 1000));

    List<Report> actual = Arrays.asList(
        tomorrowReport,
        todayReport
    );

    List<Report> expected = Arrays.asList(
        todayReport, //The report dated today is at the top
        tomorrowReport
    );

    // When
    Collections.sort(actual, sut);

    // Then
    assertThat(actual, is(expected));
  }
}

I wrote it according to my current taste. I think that the intention of "giving priority to today's report and bringing it up" that I originally wanted to do can be expressed in the test.

Good point

bad place

in conclusion

Currently, I have a habit of writing TDD when writing Java, and if I can write a test, I write the test first.

Test code is useful not only for the correctness of the product code, but also for expressing and refining the usability. It would be nice to be able to write test code that will help improve the product code.

Recommended Posts

Think of test code that is easy to understand through Comparator testing
Write code that is difficult to test
Write code that is easy to maintain (Part 1)
Write code that is easy to maintain (Part 4)
Write code that is easy to maintain (Part 3)
Let's write a code that is easy to maintain (Part 2) Name
What is the model test code testing
"Let's write versatile code that is easy to use over time" (nth time)
[Java] Code that is hard to notice but terribly slow
The story of making a binding for libui, a GUI library for Ruby that is easy to install
I made a GitHub Action that makes it easy to understand the execution result of RSpec
Implementation of unit test code
How to identify the path that is easy to make a mistake