繁体   English   中英

如何对执行命令行程序的PHP类方法进行单元测试?

[英]How can I unit test a PHP class method that executes a command-line program?

对于我正在开发的PHP应用程序,我需要阅读当前的git修订版SHA,当然可以通过使用shell_exec或backticks执行git命令行客户端来轻松获得它。

显然,我已经将此调用放入了它自己的方法中,这样我就可以在其余的单元测试中轻松地隔离和模拟此调用。 所以我的课看起来像这样:

class Task_Bundle
{

    public function execute()
    {
        // Do things
        $revision = $this->git_sha();
        // Do more things
    }

    protected function git_sha()
    {
        return `git rev-parse --short HEAD`;
    }
}

当然,尽管我可以通过模拟git_sha来测试大多数类,但是我仍在努力查看如何测试实际的git_sha()方法,因为我看不到为其创建已知状态的方法。 我认为在单元测试中还没有真正的价值可以调用git rev-parse来比较结果吗? 我想知道至少是断言该命令已运行,但是我看不到任何获取PHP执行的Shell命令历史记录的方法-即使我指定PHP应该使用BASH而不是SH,历史记录列表也会出现我认为是空的,因为单独的反引号执行是单独的终端会话。

我很想听听有关如何测试此方法的任何建议,还是可以保留该方法未经测试并在将来维护应用程序时小心一点即可吗?

尽管您已经接受了答案,但是让我发布一些有关单元测试应该如何工作的信息,因为即使发布的解决方案确实有效并且确实不错,它也有一些缺点。

首先,您不想实际执行命令,因为这会测试外部软件。 从现在开始,您将依赖无法控制的外部内容(如果我想在PC上测试您的软件会发生什么情况?我是否必须安装git或任何git-mock?)。 您真正想做的是查看命令行命令是否正确并且执行是否正确。

正如我之前为此所做的努力一样,这是我做的事情 :我创建了一个执行shell_exec的类。 我想与外壳进行交互的任何地方,都注入类并使用它。 因此,为了进行测试,我可以模拟该类并查看是否执行了正确的方法以及是否设置了正确的参数。

这有很多好处:

  • 我与外壳交互有一点。 如果将来发生任何更改,或者在执行命令之前需要执行任何操作,则可以将行为添加到类中。 PHP函数被很好地封装。
  • 即使shell_exec命令由于任何原因不起作用,它也可以在每台PC上运行。 测试可以在每台PC(开发机,测试服务器,集成服务器)上执行,而无需担心外部依赖关系。

当然,要验证您的软件可以整体运行,您必须执行集成测试,而该测试不会模拟任何东西。 但这是完全不同的情况。 单元测试应确保您的类(或方法)完成了所需的工作。 有时这不是很明确的方法,因为您可能决定在某个地方使用真实的类,因为对其进行模拟会导致大量的开销。 但是,就我而言,如果它依赖于可能未安装或由于某些原因而无法运行的外部库/软件,则无论如何都不再是单元测试。

至少您可以执行类似检查已匹配字符串以匹配/ ^ [abcdef0-9] {7} $ /的操作。

我想如果您真的愿意,可以编写一个虚拟git并将其位置放在环境的PATH 让它进行所需的任何验证,然后生成与实际操作一致的输出。 可以想象,如果您愿意的话,甚至可以将其转发到真正的git ,但是您不能保证结果。

但是,您必须要小心...。您只需要做足够的工作,就可以使该类误以为它确实是git ,但是如果您使它的行为像真实的一样,那等于编写自己的半屁股版Git。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM