简体   繁体   中英

Unit testing with generated inputs and expected outputs

I'm writing some simple unit tests for a method which acts like a database query: it returns a list of results that can be customised using a limit (max of n results) and a page (the p'th set of n results). I'd like to test a few cases, such as:

  • Return all the results
  • Return the first page of a limited result set
  • Return an aribtrary page of a limited result set
  • Return the last page of a limited result set which overruns the total number of results
  • Return a page beyond the total number of results

I need to mock the results (effectively names) that are returned, so I'm just generating them with a counter to make a list of "Name #1", "Name #2", etc. for as many as I need. Each test looks (roughly) like:

public void testGetMockCandidatesLimited() throws Exception {
    int numResults = 4;
    setupMock(numResults);
    results = queryFunction(...);

    // Check that the expected number of results was returned
    assertEquals(numResults, results.size());
    // Check that the results are correct and in order
    for (int i = 0; i < numResults; i++) {
        assertEquals(result.get(i).getName(), "Name #" + (i + 1));
    }
}

My question is: is it okay to 'generate' the expected answers in this way? This is a trivial example, but the next step was to write a test to write a test to get the second page of two results each, and I had:

    final int TEST_LIMIT = 2, TEST_PAGE = 1;
    // Check that the expected number of results was returned
    assertEquals(numResults, results.size());
    // Check that the results are correct and in order
    for (int i = TEST_LIMIT * TEST_PAGE; i < TEST_LIMIT * TEST_PAGE + TEST_LIMIT; i++) {
        assertEquals(result.get(i).getName(), "Name #" + (i + 1));
    }

Now it just so happens that this test is 'correct' in the sense that i will take on the values that I expect it to and ensure that the results are "Name #3" and "Name #4". However it also happens that my queryFunction calculates which results to return in the same way ( limit * page + limit kind of thing).

This is concerning because if the test generates the expected answers in the same way that the unit under test does, it won't detect if there's a bug in that approach. However naming the input values with constants makes the tests much more readable than just have magic integers between 1 and 4 plugged in everywhere.

What is the best way to deal with this situation, for both readability and maintainability (eg changing values in the future, should you need to)?

In asking this question I think I've convinced myself that the solution is to define the expected values as constants up front as well, such as:

final int LIMIT = 2, PAGE = 1, MIN_RESULT = 3, MAX_RESULT = 4;

... and then use those values in the assertions. This retains all the readability of named key values, and discourages the temptation to generate the expected outputs. In this case I would still be using a loop to generate each expected name between Name #MIN and Name #MAX , but the bounds themselves would be explicitly static.

Is this as good as it gets, or are there better ways to deal with this repetitiveness?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM