如何为phpunit编写测试用例,其中被测试的代码使用可选模块,并且并不总是可用的


How to write a test case for phpunit where the code being tested uses optional modules and are not always available

我刚刚开始编写测试用例,我不确定如何处理某些测试。用非常基本的术语来说,我正在测试的类是各种操作码缓存的包装器。这些测试将被捆绑到软件中,这些软件将被下载并在许多不同的主机上使用,因此我对如何处理这些类的测试感到困惑,原因有两个。

以apc包装器

为例
class Storage_Container_Apc extends Storage_Container implements Storage_iContainer
{    
    protected $_id_prefix = '';   
    protected $_file_prefix = '';   
    function __construct($id_prefix='', $file_prefix='', $options=array())
    {               
        $this->_id_prefix = $id_prefix; 
        $this->_file_prefix = $file_prefix; 
    } 
    /**
     * @see Storage_iContainer::available
     */
    public static function available()
    { 
        return extension_loaded('apc') && ini_get('apc.enabled');
    } 
}

和这个基本的测试用例。

class StorageContainerApcTest extends 'PHPUnit_Framework_TestCase
{
    public function testAvailability()
    {
        $this->assertTrue(Storage_Container_Apc::available());
    }
}

在没有APC的系统上,这个测试显然会失败,但是它当然不是一个真正的失败,因为类是依赖于模块的,如果它在系统上不可用,就不会被使用。对于这个点,测试应该是什么,才能返回ok。会是这样吗?

class StorageContainerApcTest extends 'PHPUnit_Framework_TestCase
{
    public function testAvailability()
    {
        if(extension_loaded('apc') && ini_get('apc.enabled'))
        {
            $this->assertTrue(Storage_Container_Apc::available());
        }
        else
        {
            $this->assertFalse(Storage_Container_Apc::available());
        }
    }
}

我的最后一个问题涉及到如何用测试测试这些操作码包装器。因为在任何给定时间运行多个操作码是不可能的?

我已经意识到我应该使用

protected function setUp() {
    if (!(extension_loaded('apc') && ini_get('apc.enabled'))) {
        $this->markTestSkipped('The APC extension is not available.');
    }
}

也可以使用

@codeCoverageIgnore
例如:

/**
 * @see Storage_iContainer::available
 * @codeCoverageIgnore
 */
public static function available()
{ 
    return extension_loaded('apc') && ini_get('apc.enabled');
}

参见代码覆盖率分析