繁体   English   中英

许多测试用例涵盖了一个函数 - phpunit

[英]Many test cases to cover a function - phpunit

对于以下函数,我需要编写更多的测试用例,我已经编写了一个,可以有人给出一些想法,也许是为了测试中间函数调用的返回值。

 public function calculateShortestPath($graphObj, $start, $destination)
{
    $shortestPath = null;

    if ($this->validateParams($graphObj, $start, $destination) == true) {

        $result = $this->getAllVerticesAndNeighbours($graphObj);

        $vertices = $result[self::VERTICES];
        $neighbours = $result[self::NEIGHBOURS];

        $vertexCost = array_fill_keys($vertices, self::INFINITY);
        $visitedVertices = array_fill_keys($vertices, null);

        $vertexCost[$start] = 0;
        $vertexQueue = $vertices;

        $result = $this->getShortestPath($vertexQueue, $vertexCost, $neighbours, $visitedVertices, $destination);

        $vertexCost = $result[self::VERTEX_COST];
        $shortestPathVertices = $result[self::SHORTEST_PATH_VERTICES];

        $path = $this->getRefinedShortestPath($shortestPathVertices, $destination);

        $shortestPath = new ShortestPath($path, $vertexCost[$destination]);

    }

    return $shortestPath;
}

我已经写了以下案例,

 /**
 * Test for calculateShortestPath function
 *
 * @param string|int $start starting point
 * @param string|int $destination destination point
 * @param array $expectedShortestPath expected shortest path
 * @param int|float $expectedCost expected cost
 * @dataProvider testCalculateShortestPathDataProvider
 */
public function testCalculateShortestPath($start, $destination, $expectedShortestPath, $expectedCost)
{
    $actualResult = $this->shortestPathCalc->calculateShortestPath($this->graph, $start, $destination);

    /* @var $actualResult ShortestPath */
    $this->assertEquals(
        $expectedShortestPath,
        $actualResult->getPath(),
        sprintf('Incorrect shortest path from %d to %d !', $start, $destination)
    );

    $this->assertEquals(
        $expectedCost,
        $actualResult->getCost(),
        sprintf('Incorrect shortest path cost from %d to %d !', $start, $destination)
    );
}

作为一般规则,单元测试应该表现出两个特征:

  • 每个测试都应测试一个且只测试一件事
  • 每项测试都应尽可能愚蠢

第一个特征的原因是如果测试失败,它将记录哪个测试用例方法触发了失败。 如果该方法测试了很多东西,那么确定确切的失败就更加麻烦了。

存在第二个特征是因为每次测试失败,都必定存在问题。 问题只能存在于两个地方之一(忽略PHP及其扩展中的错误,或单元测试程序中):在测试代码中,或在测试本身中。 “聪明”的测试将很难确定它是哪种情况,并且你不想花一两个小时追捕你班上的一个错误,而事实证明它实际上是测试的错误。

在上面的示例中,您当前的测试非常好,但它打破了第一条规则(一次发生了两次测试)。 除非运行测试中的方法非常昂贵,否则可能值得将此测试用例两次,第一次运行断言预期的最短路径,第二次断言预期成本(如果您的方法确实有一个昂贵的运行时间,那么有一个激励尝试并优化它在那里:))。

你的测试也可能会破坏第二条规则,因为我不知道$ this - > graph是什么或它是如何设置的。 这是一个实际的业务对象还是仅仅是一个模型? 您可能希望研究模拟PHPUnit的存根功能。

关于测试策略,有两种常规方法 - 黑盒测试(根据其规格测试单元,但对待它就像你不了解其内部工作原理)和玻璃盒(在那里你使用你对单元内部工作的了解)设计测试)。 我首选的方法是主要采用黑盒策略,围绕规范构建测试,然后一旦我完全覆盖规范,就转向玻璃盒策略,编写额外的测试,覆盖黑盒测试的任何代码路径不运动。

测试通常与边界有关,如在输入有效且无效时测试对输入的响应。 因此,对于您的课程所具有的每种方法,您需要一个典型的案例(通常称为“快乐路径”)来演示典型用法,一些极端但仍然有效的输入,一系列输入超出有效范围(如果你的方法除了1-10范围内的数字,然后是0的测试用例和11的测试用例将覆盖这些情况)和一个测试用例,其数据大大超出有效范围。 编程中的许多错误发生在有效输入和无效输入之间的转换(逐个错误可能是最臭名昭着的例子),因此您的测试应该彻底覆盖这些区域。

黑盒测试的一个好处是,如果你知道规格,你可以在任何代码甚至测试之前编写测试。 然后,您可以开始实现代码,对其进行测试,针对失败的测试进行更正并重复此过程,直到获得100%的通过率。 这称为测试驱动开发。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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