【问题标题】:PHPUnit should fail if no test is executed如果没有执行任何测试,PHPUnit 应该会失败
【发布时间】:2017-03-18 05:33:30
【问题描述】:

我使用 PHPUnit 在我的 Gitlab CI 服务器上执行单元测试。如果未执行任何测试,则构建通过可能会出现错误(例如自动加载器问题)。

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

【问题讨论】:

    标签: php phpunit gitlab


    【解决方案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
    

    这基本上在 src 目录上运行 phploc,输出将包含一个类似于以下内容的部分:

    Tests
        classes      123
        methods      1234
    

    我们所追求的是 after 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
    

    这基本上是以下的简写:

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

    这要归功于短路评估:如果 [ "${count}" -eq "0" ] 评估为 true,则需要评估 && 子句,这是一个 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 的输出。在删除测试目录后,我很快尝试在我正在处理的项目之一上运行 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
    

    【讨论】:

    • 非常感谢您的广泛回答。我一定会试试这个!您认为将这个功能添加到 phpunit 是否值得?也许带有参数 --fail-on-no-tests 和退出代码 1。
    • @wuethrich44:极不可能添加类似的东西。它超出了测试框架的范围(即它用于测试代码,如果未测试某些内容,则不会导致构建失败)。那个,以及 PHPUnit 背后的人为此创建了一个单独的工具这一事实告诉我,它不太可能很快发生......即便如此,除非你深入了解静态,否则几乎不可能确定测试的数量代码分析。在 PHP 7 之前完全不可能的事情......
    • 也许可以在此相关答案下方发表评论,由 Bergmann himeslf 发布以获得明确的答案(或打开 github 问题):stackoverflow.com/a/30909517/1230836
    • 你是对的。再次感谢你的帮助。我将使用最后一次更新。
    猜你喜欢
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    相关资源
    最近更新 更多