0

我正在为一个小班进行单元测试。我正在使用这个类来使用 PHPUnit,这样我就可以开始正确地测试我将来编写的更大的代码片段。

考虑我正在尝试测试的以下代码:

/**
 * Registers a starting benchmark tick.
 *
 * Registers a tick with the ticks registry representing the start of a benchmark timeframe.
 *
 * @param string $id The identifier to assign to the starting tick.  Ending tick must be the same.
 * @return bool Returns TRUE if a tick was registered successfully or FALSE if it was not.
 * @since 0.1
 */
public function start($id)
{
    $this->tick($id . "_start");
    if($this->getStart($id) != false) {
        return true;
    }
    return false;
}

/**
 * Retrieves a registered start tick.
 *
 * Checks to see if a start tick is registered.  If found the microtime value (as a float) is
 * returned, otherwise FALSE is returned.
 *
 * @param string $id The identifier to lookup the tick under.
 * @return mixed The microtime (as a float) assigned to the specified tick or FALSE if the tick
 * start hasn't been registered.
 * @since 0.1
 */
public function getStart($id)
{
    if(isset($this->ticks[$id . "_start"])) {
        return $this->ticks[$id . "_start"];
    }
    return false;
}

以下是实际的测试代码:

public function testBadStartTick()
{
    $this->assertFalse($this->bm->start("What_Invalid_Key_Fits_Here?"))
}

问题是这个测试函数总是返回,true无论我试图让它返回多少次false。我尝试过给出空值、300 多个字符的键、空数组,甚至是新对象的实例。在所有情况下,PHP 要么中断,要么抛出某种警告。当 PHP 没有中断时,我的值将转换为 PHP 将在数组键中接受的值,然后我的测试在尝试执行$this->assertFalse().

我想实现尽可能多的代码覆盖率。

所以我的问题是,如果这些方法,给定它们当前的代码,是否会false在正常操作下返回?

我在想,因为我正在附加文本(这是出于管理目的),所以我总是提供某种 PHP 将接受的密钥,无论我提供什么$id

有什么想法吗?

提前致谢!

4

2 回答 2

0

编辑代码如何start在使用之前验证接收到的数据?

public function start($id)
{
    if ($id !== null) { // perhaps more validation is needed?
        $this->tick($id . "_start");
        if($this->getStart($id) != false) {
            return true;
        }
    }

    return false;
}

public function getStart($id)
{
    if(isset($this->ticks[$id . "_start"])) {
        return $this->ticks[$id . "_start"];
    }
    return false
}

然后你可以像这样测试:

public function testBadStartTick()
{
    $this->assertFalse($this->bm->start(null))
}
于 2014-05-07T19:21:16.467 回答
0

您将需要使用模拟来执行此操作。

它将要求您执行这 2 个部分才能获得全面覆盖。

但是你必须这样做

public function testBadStartTick()
{
    $bm = $this->getMock('bm', array('getStart'));

    $bm->expects($this->any())
         ->method('getStart')
         ->will($this->returnValue(false));

    $this->assertFalse($bm->start("What_Invalid_Key_Fits_Here"))
}

当然,将 bm 替换为您的实际类名(如果需要使用命名空间)。像这样,您将仅为该测试模拟 getStart 的功能,并且您可以测试您的结果。

当然,如果您想要全面覆盖并测试您需要的所有内容

public function testGoodStartTick()
{
    $this->assertTrue($this->bm->start("What_Invalid_Key_Fits_Here"))
}

如果一切顺利,这将测试路径。因为您不再在那里模拟,所以它将使用实际的 getStart 函数。

public function testMissingStartTick()
{
    $this->assertFalse($this->bm->getStart("What_Invalid_Key_Fits_Here"));
}

这将独立于其他函数测试 getStart(),因此该键将不存在并将返回 false。

您不必单独测试真正的路径,因为您将使用 testGoodStartTick() 进行测试

编辑:正如人们在评论中所说,我应该把它放在这里作为警告,拥有永远不会执行的代码是不明智的。当您在那里进行检查时,我认为 tick() 可能会做一些魔术,有时不会将密钥添加到数组中,但我从您的评论中了解到情况并非如此。因此,确实在您的情况下,我的答案不是正确的,最好遵循删除您知道永远正确的代码的建议。

于 2014-05-07T19:53:33.880 回答