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