带有MP3库的TDD

时间:2013-09-08 21:01:29

标签: unit-testing tdd

我正在尝试学习TDD,我的第一个项目是一个基于PHP的项目,帮助我组织一些有点小的MP3收藏。我知道还有很多其他更好的解决方案,但这只是为了掌握TDD。

我需要一个接受文件名的方法,并使用命令行调用ffmpeg返回MP3的持续时间。是否可以测试这种方法,而不是将其指向真正的MP3?我应该只测试简单的事情,比如文件是否存在?我应该费心去测试吗?

我很感激你的想法。

非常感谢提前。

编辑:我很抱歉没有提到对ffmpeg的调用不是通过类或API本身,而是通过CLI。

$output = shell_exec("{$ffmpeg_exe} -i \"{$file_path}\" 2>&1");

这是我在测试时遇到的问题。我不认为有没有办法在不使用Runkit的情况下模拟它,我想避免使用它,因为它无法通过Composer安装,我想避免需要编译的依赖项。

2 个答案:

答案 0 :(得分:1)

这取决于你想称之为“单元测试”:)

在我看来,单元测试不应该依赖于被测课程之外的任何东西。绝对不应该进行网络请求,数据库调用或触摸文件系统

您描述的测试是我称之为集成或验收测试的测试 - 编写失败的验收测试通常是我个人TDD周期的开始。然后,如果合适的话,我将其分解成更小的部分,并编写一个失败的单元测试,并在多个单元测试中循环红绿重构,直到验收测试通过。

使测试更加孤立的另一种方法是使用测试双打(模拟,存根,假货,间谍等的通用术语)。在您的情况下,这可能是最好的方法 - 让一个像对象一样的模拟对象与文件系统交互,但您可以控制以某种方式操作。我会有一个参数来传递它,如果没有传递任何内容,请使用内置的文件交互库。

我有一段时间没有完成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

再次,超伪代码!祝你好运!!


对您的修改的回复:

Aaahhh我明白了。我假设您正在解析$output以提取所需的信息并处理运行此命令可能返回的任何错误。那个,IMO,是你应该测试的代码中有趣的部分。所以我可能会将shell_exec放在一个我不打扰测试的函数中,但是在你的解析逻辑的测试中,我会将这个函数的返回值存根,以便能够测试你在做什么时你得到各种输出。

我还会进行至少一次实际调用shell_exec的集成或验收测试,并且实际上需要$file_path处的文件。

这条shell_exec行基本上是在进行字符串连接,所以它不值得测试。 TDD并不是一个规则作为指导,有时有时你必须决定不测试:)

答案 1 :(得分:0)

你可以将ffmpeg存根为不使用真实文件。