我很好奇人们如何处理测试之间的耦合以及“cascaing failure”。我不知道还有什么可以称之为,所以我会用一些代码来解释。
我有一个我想测试的简单缓存类。
class Cache
{
private $data = array();
public function set($key, $data)
{
$this->data[$key] = $data;
return true;
}
public function get($key)
{
if (!isset($this->data[$key])) {
return false;
}
return $this->data[$key];
}
}
现在我想测试类,以及类中的两个方法。这是问题所在; get()方法依赖于set()方法。所以我可以用两种方式之一编写我的测试用例。
class TestCache extends Test
{
private $cache = null;
public function setup()
{
$this->cache = new Cache();
}
public function testSet()
{
$result = $this->cache->set('foo', 'bar');
$this->asserTrue($result);
}
public function testGet()
{
$result = $this->cache->get('foo');
$this->assertEquals($result, 'bar');
}
}
这里的问题是第二个测试,testGet(),在第一个测试,testSet()上回复。如果testSet()失败,testGet()也会失败。两个测试之间有一种耦合。另外,如果我改变测试方法的顺序,testGet()测试将失败。所以我写这样的测试用例:
class TestCache extends Test
{
private $cache = null;
public function setup()
{
$this->cache = new Cache();
}
public function testSet()
{
$result = $this->cache->set('foo', 'bar');
$this->asserTrue($result);
}
public function testGet()
{
$this->cache->set('foo', 'bar');
$result = $this->cache->get('foo');
$this->assertEquals($result, 'bar');
}
}
现在两个测试之间没有耦合,但仍然存在问题。如果Cache :: set()方法失败,那么第二个测试也将与第一个一起失败,因为第二个测试对Cache :: get()的调用在Cache :: set()上的回复没有失败。
所以我想知道你通常如何应对这种情况。由于一个不好的测试,您是否只是接受了测试输出中的几十个故障?如果重要测试失败,你是否在课堂上进一步测试?
答案 0 :(得分:2)
这是phpunit中@depends指令的用法:请参阅“测试依赖关系”一节。如果依赖项失败,则将跳过依赖于初始测试的后续测试。
答案 1 :(得分:0)
你是如何运行测试的?你打电话给TestCache::testSet()
后跟TestCache::testGet()
吗? assertTrue()
和assertEquals()
做了什么?他们是否使用异常来打破当前的执行路径?如果没有,这将是一个分组相互依赖的测试的好方法,例如Test::assertTrue()
是这样实现的:
public function assertTrue( $value, $method = "" )
{
if ( $value !== true )
{
throw new Exception( "assertTrue() failed on $method, Value $value does not evaluate to true" );
}
}
然后,您将测试结合起来(在testSet()& testGet()内部将方法名称“Cache :: set”或“Cache :: get”传递给断言函数:
try
{
TestCache::testSet();
TestCache::testGet();
}
catch ( $e )
{
echo( "Failed - " . $e->getMessage() );
}
现在,如果testSet()
失败,执行会跳过testGet()