2010-12-09 37 views
3

我正在写一些对文件系统进行大量使用的对象。我不确定什么是测试它们的正确方法。我在理论上知道我应该在某些对象中抽象文件系统的功能,然后嘲笑它们,但在我的情况下它将毫无意义:我想测试的类的主要用途是管理文件。所以当测试新对象时,我会遇到同样的问题,只是移动了一个层次。具有文件系统功能的测试对象

我可以考虑进行测试的唯一方法是实际上使用文件系统。问题是测试将在浏览器和命令行中都运行,因此我需要在每个人都可以写入的目录中工作。而且,这似乎不是一个非常便携的解决方案。

任何想法?

回答

5

您可以mock the filesystem with vfsStreamsuggested in the PHPUnit Manual

vfsStream是可能有益的单元测试来模拟真实的文件系统的虚拟文件系统中的流包装[...]如果PEAR安装程序是适用于您的系统,你只需要执行下面的命令:

$ pear channel-discover pear.bovigo.org 
$ pear install bovigo/vfsStream-beta 

examples at Github,也是一个Wiki

+8

'哈 - 你是一个垃圾文件系统。我拥有的最后一个文件系统比你好多了,哈哈。那种嘲笑? ;) – PaulJWilliams 2010-12-09 16:13:26

+2

PHPUnit文档不完整。有更好的参考吗?它缺少关于如何模拟文件系统的信息(如模拟文件存在,指定模拟文件的内容等) – 2012-11-14 22:18:01

1

引入非常低级别的php函数,除了调用文件系统函数之外什么都不做,并在代码中使用这些函数。

然后,在您的测试工具中,用存根(可能记录它们已被调用)重写此函数。这样你就可以验证你的代码在实时系统中调用正确的低级PHP函数。对于你所能做的单元测试,真的。

+0

原来的问题没有提及单元测试,这似乎是专门集成相关的问题。我会认为嘲笑任何东西都会破坏测试的目的? – 2013-11-09 19:17:16

1

当我看到它,你有三种选择:

  • 接受一些测试是最好的集成测试。通过创建一个用于测试运行的小世界来开始测试(在%TEMP%中,基于类/方法名称),然后在完成时将其销毁。
  • 检查你的抽象层,并从类中提取文件IO。为此创建一个接口。其余的使用集成测试(但这将是非常小的)。这与上面的不同之处在于,不是在执行file.Read你写意图,说ioThingie.loadSettings()。
  • 模拟IO(如上面Gordon所示)。

我通常用的选项之一,二,只用三为边缘的情况下,我在C#中嘲讽的原始IO层(有System.IO.File)真的只能说明你可以写嘲讽语句找到一个组合去,并且让你的测试过于依赖实现,但是上面的vfs看起来像是嘲笑FS,而不是对象。

1

另一个变种是模拟使用文件系统的PHP函数runkit。不知道这是最好的解决方案,但它的工作原理。 有phpunit-mockfunction - PHPUnit扩展,简化了模拟PHP功能。

因此例子是:

class Tests extends PHPUnit_Framework_TestCase { 
    // ... setUp, tearDown, other tests... 

    function test_1(){ 
     $file_size_to_return = 10; 

     $fake_filesize = new PHPUnit_Extensions_MockFunction('filesize', $this->obj->tested_method); 
     $fake_filesize->expects($this->once())->will($this->returnValue($file_size_to_return)); 

     $this->obj->tested_method(); // actually run method we want test that contains filesize() function... 
    } 
}