如果没有执行测试,PHPUnit 应该会失败

PHPUnit should fail if no test is executed

我使用 PHPUnit 在我的 Gitlab CI 服务器上执行单元测试。当没有执行任何测试时,尽管可能存在错误(例如自动加载器问题),但构建通过了。

有没有办法告诉 PHPUnit Command Line Runner 如果没有执行测试它应该以代码 1 退出?

如果没有测试,则没有任何 PHPUnit 可以标记为失败。因此,PHPUnit 不能这样做。您可以使用的是 Sebastian Bergmann 的另一个工具 phploc.

这个有a --count-tests option。 运行 在 运行 宁 phpunit 之前处理结果,如果计数为 0,则仅 exit 1 来自脚本。


更新,我刚刚意识到我错过了早一点做的显而易见的事情。

一个简单的方法是:

 count=$(./phploc.phar --count-tests src | awk '/Tests/{getline; print}' | awk '{print $NF}') && [ "${count}" -ne "0" ]
exit $?

下面的大部分命令细分都适用,所以我将保持原样。主要区别在最后:

[ "${count}" -ne "0" ]
exit $?

这基本上意味着:比较${count}0,如果不匹配0,比较将以状态0退出,如果为0,则退出状态为1。我们然后简单地在我们自己的 exit 语句中重用退出状态:exit $? 基本上是在说:以与我们上次所做的相同的退出状态退出。


可以使用以下命令获得获取您正在寻找的退出状态的简单命令:

 count=$(./phploc.phar --count-tests src | awk '/Tests/{getline; print}' | awk '{print $NF}') && [ "${count}" -eq "0" ] && exit 1 || exit 0

稍微分解一下:

./phploc.phar --count-tests src

这基本上是 运行s phploc 在 src 目录中,输出将包含一个看起来像这样的部分:

Tests
    classes      123
    methods      1234

我们在 Tests 之后的那一行。所以命令的输出被传递给 awk,它将匹配 Tests,获取下一行并打印它(即:classes 123)。这发生在这里:

| awk '/Tests/{getline; print}'

该字符串再次传递给 awk,以提取最后一部分(找到的实际测试数):

awk '{print $NF}'

该值将分配给 count,因为我们 运行 像这样执行这些命令:

count=$(phploc | awk | awk)

所以最终输出赋值给count。接下来,我们要查看测试计数是否为零,并基于此我们需要以零或非零状态退出。这是我们可以轻松做到的事情:

 [ "${count}" -eq "0" ] && exit 1 || exit 0

这基本上是 shorthand 用于:

if [ "${count}" -eq "0" ]; then
    exit 1
else
    exit 0
fi

这要归功于短路评估:如果[ "${count}" -eq "0" ]评估为真,则需要评估&&子句,这是一个exit 1语句,返回所需的非-零退出代码

如果我们省略 || exit 0,最后的状态代码将是 [ "${count}" -eq "0" ] && exit 1 评估的结果,它是错误的,导致状态代码为 1。为了避免这种情况,我们有添加 || exit 0.

您可以通过在 CLI 上编写如下内容轻松检查:

foo="bar" && [ "${foo}" -eq "123" ] && echo 'foo matched 123'
//run this, then run
echo $?

输出将为 1(最后一个命令的退出状态)


最后更新

如果 运行 单元测试的时间不超过几分钟,并且您不关心 运行 两次,您可以只检查输出phpunit.在删除测试目录后,我在我正在处理的项目之一上快速尝试了 运行ning phpunit 5.4.6。输出是这样的:

PHPUnit 5.4.6 by Sebastian Bergmann and contributors.



Time: 51 ms, Memory: 8.50MB

No tests executed!

所以运行宁:

vendor/bin/phpunit | grep -q 'No tests executed'

如果没有测试,则退出状态为 0,如果有,则为 1。只需检查退出状态并使用相反的代码退出即可。像这样的东西可能有效:

vendor/bin/phpunit | grep -q 'No tests executed' && exit 1 || exit 0