在编写PHPUnit测试一段时间后,我遇到了一个模式,我想找到一个优雅的解决方案。我项目的单元测试使用了大量的临时文件。我将有一个输出文件的函数,我需要在输出(temp)文件上做几个断言。之后我想确保临时文件得到清理,即使某些断言失败了。
这是一个示例测试文件,使用一些cruft来处理临时文件:
class FooTest extends AhshayTestUnit
{
function setUp()
{
$this->tmps[] = array();
}
function tearDown()
{
foreach ($this->tmps as $tmp)
{
@unlink($tmp);
}
}
function tmp()
{
$this->tmps[] = $tmp = tempnam('/tmp', 'test_foo');
unlink($tmp);
return $tmp;
}
function testFoo()
{
$in = 'html2pdf.html';
$out = $this->tmp();
$success = html2Pdf($in, $out);
$this->assertFileExists($out, "should create PDF file");
$this->assertGreaterThan(1024, filesize($out), "output file should be atleast 1k");
# and so on
}
}
这样,即使第一个断言失败,每个测试函数也不必担心删除$out
。
现在我已经说了所有这些,我想将这些辅助函数烘焙到我拥有的每个测试对象中。我已经有了自己的类PHPUnit_Framework_TestCase
。我可以将我的自定义setUp()
和tearDown()
放在我的子类中,但要求所有我自己的设置/拆卸的测试都记得调用parent::__construct()
似乎有点蹩脚。有没有更优雅的方式来做到这一点?是否已经在PHPUnit中内置了一些东西来处理这个问题?似乎最好的方法是让PHPUnit链接设置/拆卸回调。
答案 0 :(得分:2)
您可以使用vfsstream来模拟文件系统。这是一个很好的解决方案,可以避免任何垃圾设计。
自定义解决方案可能是注册一个正在删除临时文件的关闭函数,即使发生了致命错误,例如这个(简单)示例:
class MyTest extends PHPUnit_Framework_TestCase
{
public function setUp() {
register_shutdown_function(function() {
if(file_exists('temp.file')) {
unlink('temp.file');
}
});
}
... the tests
}
答案 1 :(得分:0)
如果您的测试不能自行清理(因为在集成测试期间可能没有),注册关闭功能进行清理非常有用。
话虽如此,如果你确实发现你多次重复相同的逻辑,你可以使用PHP traits制作类似于TempTrait
的东西,只需要你需要的功能在测试期间或在每个测试的tearDown
功能期间运行。