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

aco*_*ton 1 php git phpunit unit-testing

对于我正在开发的PHP应用程序,我需要阅读当前的git修订版SHA,当然我可以通过使用shell_exec或反引号来执行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`;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,虽然我可以通过模拟git_sha来测试大部分类,但我很难看到如何测试实际的git_sha()方法,因为我没有看到为它创建已知状态的方法.我不认为单元测试中有任何实际价值也要求git rev-parse比较结果?我想知道至少断言命令已经运行,但是我看不到任何方法来获取PHP执行的shell命令的历史 - 即使我指定PHP应该使用BASH而不是SH,历史列表会出现空,我认为因为单独的反引号执行是单独的终端会话.

我很想听听有关我如何测试这一点的任何建议,或者是否可以将该方法保持未经测试并在将来维护应用程序时要小心它?

Sgo*_*kes 5

虽然你已经接受了答案,但是让我发布一些关于单元测试应该如何工作的东西,因为即使发布的解决方案确实有效并且确实很好,它也有一些退款.

首先,您不希望实际执行命令,因为这将测试外部软件.从这一刻起,你依赖于你无法控制的外部东西(如果我想在我的电脑上测试你的软件会怎么样?我必须安装git或任何git-mock吗?).你真正想要做的是查看命令行命令是否正确并且执行得好.

我之前一直在努力解决这个问题,这就是我所做的:我创建了一个执行shell_exec的类.我想要与shell进行交互,我注入了类并使用它.因此,对于测试,我可以模拟该类,看看是否执行了正确的方法以及是否设置了正确的参数.

这有很多好处:

  • 我有一点与shell进行交互.如果将来发生任何变化,或者在执行命令之前我需要做任何事情,我可以将该行为添加到类中.PHP函数很好地封装了.
  • 它适用于每台PC,即使shell_exec命令因任何原因无效.测试在每台PC(开发机器,测试服务器,集成服务器)上执行,无需担心外部依赖性.

当然,要验证您的软件是否作为一个整体工作,您必须进行不模拟任何东西的集成测试.但这是一个完全不同的情况.单元测试应该确保你的类(或方法)做它需要做的事情.有时这不是明确的,因为你可能决定在某个地方使用真正的类,因为嘲笑它会导致很多开销.但是,就我而言,如果它依赖于可能由于某些原因而无法安装或可能无法工作的外部库/软件,则它不再是任何单元测试.