这取决于您要称为“单元测试”的内容:)
在我看来,单元测试不应该依赖于被测类之外的任何东西。它绝对不应该发出网络请求、数据库调用或接触文件系统。
您描述的测试是我称之为集成或验收测试的测试——编写失败的验收测试通常是我个人 TDD 周期的开始。然后,如果合适,我将其分解为更小的部分并编写一个失败的单元测试,并在多个单元测试上循环 red-green-refactor 直到验收测试通过。
使您的测试更加孤立的另一种方法是使用测试替身(模拟、存根、伪造、间谍等的通用术语)。在您的情况下,这可能是最好的方法——拥有一个模拟对象,其行为类似于与文件系统交互的对象,但您可以控制它以某种方式进行操作。我会有一个参数来传递它,如果没有为此传递任何东西,请使用内置的文件交互库。
我有一段时间没有做 PHP,但这里有一些伪代码:
function duration(filename, filesystem)
filesystem = PHP File interacting object if filesystem isn't passed in
file = filesystem.find(filename)
return file.duration
这样,在您的测试中,您可以执行以下操作:
test that the duration function returns the duration of the file whose name is passed in
fake_file = stub that returns 3:08 when we call duration on it
fake_filesystem = stub that returns fake_file when we call find on it with a filename
assert_equal duration("some_filename.mp3", fake_filesystem), 3:08
再次,超级伪代码!!!祝你好运!!
回复您的编辑:
啊啊啊我明白了。我假设您正在解析$output
以提取您想要的信息并处理运行此命令可能返回的任何错误。那,IMO,是你的代码中应该测试的有趣部分。所以我可能会把它shell_exec
放在一个我不会打扰测试的函数中,但是在你的解析逻辑测试中,我会存根这个函数的返回值,以便能够测试你在得到各种输出时所做的事情。
我还有至少一个集成或验收测试,它实际上会调用shell_exec
并且实际上需要一个文件存在于$file_path
.
这一shell_exec
行基本上是在做字符串连接,所以不值得测试。TDD 与其说是一种规则,不如说是一种指导,有时你不得不决定不测试:)