使用生成的输入和预期输出进行单元测试

时间:2013-03-07 01:54:24

标签: unit-testing testing

我正在为一个类似数据库查询的方法编写一些简单的单元测试:它返回一个结果列表,可以使用限制(最多n个结果)和一个页面(第p组)自定义结果)。我想测试几个案例,例如:

  • 返回所有结果
  • 返回有限结果集的第一页
  • 返回有限结果集的aribtrary页面
  • 返回超出结果总数的有限结果集的最后一页
  • 返回超出结果总数的页面

我需要模拟返回的结果(实际名称),所以我只是使用计数器生成它们以列出“名称#1”,“名称#2”等等。我需要。每个测试看起来(大致)如:

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));
    }
}

我的问题是:以这种方式“生成”预期的答案是否可以?这是一个简单的例子,但下一步是编写一个测试来编写测试以获得每个结果的第二页,我有:

    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));
    }

现在碰巧这个测试是“正确的”,因为我会接受我期望的值,并确保结果是“Name#3”和“Name#4”。然而,我的queryFunction也会以相同的方式计算返回哪些结果(limit * page + limit类似的东西)。

这是令人担忧的,因为如果测试以与被测单元相同的方式生成预期答案,则不会检测该方法中是否存在错误。但是,使用常量命名输入值会使测试更具可读性,而不仅仅是插入1到4之间的魔术整数。

处理这种情况的最佳方法是,可读性和可维护性(例如,如果需要,将来会改变价值观)?

1 个答案:

答案 0 :(得分:1)

在提出这个问题时,我想我已经说服自己解决方案是将预期值定义为常量,例如:

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

...然后在断言中使用这些值。这保留了命名键值的所有可读性,并且不鼓励产生预期输出的诱惑。在这种情况下,我仍然会使用循环来生成Name #MINName #MAX之间的每个预期名称,但边界本身将是显式静态的。

这是不是很好,还是有更好的方法来处理这种重复性?