douzhang2680 2015-03-05 07:58
浏览 34
已采纳

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

For the following function I need to write more test cases, I have already written one, can someone give some ideas, Perhaps to test return values of intermediate function calls.

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

I have written following case already,

 /**
 * 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)
    );
}
  • 写回答

1条回答 默认 最新

  • dtkyayvldeaqhl7151 2015-03-05 09:51
    关注

    As a general rule, unit tests should exhibit two traits:

    • Each test should test one and only one thing
    • Each test should be as dumb as humanly possible

    The reason for the first trait is that if a test fails it will log which test case method triggered the failure. If that method tests lots of things it makes it more of a nuisance to determine the exact failure.

    The second trait exists because every time a test fails, then there must be a problem. The problem can only exist in one of two places (ignoring bugs in PHP and its extensions, or in the unit tester): in the code under test, or in the test itself. "Clever" tests will make it difficult to determine which case it is, and you don't want to spend an hour or two hunting down a bug in your class when it turns out it's actually the test that's buggy.

    In your example above your current test is pretty good, but it breaks the first rule (there's two tests happening at once). Unless running the method under test is really expensive it might be worth having this test case twice, with the first run asserting the expected shortest path and the second one asserting the expected cost (and if your method does have an expensive run time then there's an incentive to try and optimise it right there :) ).

    Your test may also break the second rule because I have no idea what $this -> graph is or how it's set up. Is this an actual business object or just a mockup of it? You might want to look into the mocking an stubbing capabilities of PHPUnit.

    Regarding test strategies, there are two general approaches - Black box testing (where you test a unit against its specifications but treat it like you have no knowledge of its internal workings) and glass box (where you use your knowledge of the unit's internal workings to devise tests). My preferred approach it to mainly adopt a black box strategy, build tests around the specs, and then once I've got the spec fully covered move to a glass box strategy to write additional tests that will cover any code paths that the black box test doesn't exercise.

    Testing is often about boundaries, as in testing responses to input when that input is both valid and invalid. So for each method your class has, you want one typical case (what's often called the "happy path") that demonstrates typical usage, a number of extreme but still valid inputs, a range of inputs that are just outside the valid range (if your method excepts numbers in the range 1-10 then a test case with 0 and a test case with 11 would cover those cases) and a test case with data wildly outside of the valid range. Many errors in programming occur at the transition between valid and invalid input (the off-by-one error is probably the most notorious example) so your tests should cover those regions thoroughly.

    One nice thing about black box testing is that if you know the specs, you can write the tests before there's any code to even test. Then you can start implementing code, test it, correct it for failed tests and repeat this process until you get a 100% pass rate. This is called Test Driven Development.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥30 python代码,帮调试,帮帮忙吧