单元测试:给出一个无效的数组键,但不会破坏PHP.可能的


Unit Testing: Give an invalid array key that doesn't break PHP. Possible?

我正在为一个小班做单元测试。我正在使用这个类来深入了解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什么。

任何想法吗?

提前感谢!

您将需要使用mock来完成此操作。

这将要求你做这两部分,以获得全面的覆盖。

但是你必须这样做

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代替你实际的类名(如果需要的话用namespace)。像这样,您将模拟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()可能会做一些魔术,有时不会将键添加到数组中,但我从你的评论中了解到情况并非如此。所以确实在你的情况下,我的答案是不正确的,最好遵循删除代码的建议,你知道将永远是正确的。

如何编辑您的代码来验证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))
}