单元测试:给出一个不破坏PHP的无效数组键。可能的
我正在为一个小班做单元测试。我正在使用这个类来处理PHPUnit,这样我就可以开始正确地测试我将来编写的更大的代码了 考虑我正在尝试测试的以下代码:单元测试:给出一个不破坏PHP的无效数组键。可能的,php,arrays,unit-testing,phpunit,array-key,Php,Arrays,Unit Testing,Phpunit,Array Key,我正在为一个小班做单元测试。我正在使用这个类来处理PHPUnit,这样我就可以开始正确地测试我将来编写的更大的代码了 考虑我正在尝试测试的以下代码: /** * Registers a starting benchmark tick. * * Registers a tick with the ticks registry representing the start of a benchmark timeframe. * * @param string $id The identif
/**
* 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
我在想,因为我是为了管理目的而添加文本的,所以我总是提供某种类型的密钥,无论我以$id的价格提供什么,PHP都会接受
有什么想法吗
提前谢谢 如何编辑代码,在使用前验证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))
}
您将需要使用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。
这样,您将仅针对该测试模拟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可能会产生一些魔力,有时不会将密钥添加到数组中,但我从你的评论中了解到情况并非如此。因此,在您的情况下,我的答案确实不正确,最好按照建议删除代码,您知道这些代码永远是正确的。谢谢您的回复。我正在寻找一个不涉及编辑代码的解决方案。如果我所追求的是不可能的,那么我可以简单地返回值,因为它不是真正需要的。我相信你所追求的是不可能的,因为串联会导致$id被转换为字符串。谢谢。看来这让我走得更远了。我现在唯一的问题是,我得到的返回值是null,而不是false。有什么想法吗?@cracketastic我为你更新了答案。问题是你们需要一个局部模拟。当您向getMock添加一个以函数名作为第二个参数的数组时,它将只模拟那些函数,否则它将模拟一切运行良好的函数,非常感谢!我在PHPUnit网站上查找API参考,但乍一看,我只看到一本包含各种用例场景的手册。如果你想阅读模拟,你可以做更多的事情,也许我遗漏了一些东西,但代码永远不会返回false,因为在调用getStart之前,密钥总是设置好的,因此,对我来说,模拟对象使getStart返回false是没有意义的。你不是在测试对象,只是在改变它的工作方式。勾号方法实际上是做什么的?这就是你问题中缺失的谜题。如果您在测试中调用start,我们无法看到整个代码路径,因为此方法中可能会发生任何情况。包括使测试用例无法成功运行的代码。例如,如果tick在ticks[]数组中注册了该键,则对start的调用将永远不会返回false,模拟将模拟不存在的现实。在这种情况下,整个if都过时了,您可以始终返回true。@Sven这就是$this->tick的全部功能,这也是我提出问题的部分原因。我很好奇,是否有可能为PHP提供一个不能用作数组键的值,但不会同时让PHP屈服。如果这是不可能的,那么我已经在想你已经触及的,是真的,我永远不能从$this->start中得到false。因此,最终的解决办法是在我的测试中放弃模拟对象,并删除if.PHP将总是尽可能地接受变量作为数组键,或者致命地失败。请注意,仅包含数字的字符串将始终转换为 整数。如果您想验证是否传递了一个有效值作为键,那么您必须在代码中亲自验证以避免致命错误,例如If is_string$id{/*add to array*/},这将产生不同。