21

我正在尝试使用以下命令使用 PHPUnit 和 phpdbg 为我的 PHP 项目生成代码测试覆盖率:

phpdbg -dmemory_limit=512M -qrr ./bin/phpunit -c .phpunit.cover.xml

这工作得很好:

PHPUnit 6.2.4 by Sebastian Bergmann and contributors.

........                                                            8 / 8 (100%)

Time: 114 ms, Memory: 14.00MB

OK (8 tests, 13 assertions)

Generating code coverage report in HTML format ... done

但是,当我在 docker 容器中使用完全相同的命令时:

docker run -it --name YM4UPltmiPMjObaVULwsIPIkPL2bGL0T -e USER=sasan -v "/home/sasan/Project/phpredmin:/phpredmin" -w "/phpredmin" --user "1000:www-data" php:7.0-apache phpdbg -dmemory_limit=512M -qrr ./bin/phpunit -c .phpunit.cover.xml

我收到以下错误:

PHPUnit 6.2.4 by Sebastian Bergmann and contributors.

[PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 561514763337856 bytes) in /phpredmin/vendor/phpunit/phpunit/src/Util/GlobalState.php on line 166]

我不明白为什么 PHPUnit 需要分配 561514763337856 字节的内存。我怀疑它陷入了一个循环,但为什么这不会发生在容器之外?这是我机器上的 PHP 版本:

PHP 7.0.22-0ubuntu0.17.04.1 (cli) (built: Aug  8 2017 22:03:30) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.22-0ubuntu0.17.04.1, Copyright (c) 1999-2017, by Zend Technologies

这是 .phpunit.cover.xml 文件:

<phpunit
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
        backupGlobals="false"
        backupStaticAttributes="false"
        bootstrap="vendor/autoload.php"
        cacheTokens="false"
        colors="false"
        convertErrorsToExceptions="true"
        convertNoticesToExceptions="true"
        convertWarningsToExceptions="true"
        processIsolation="false"
        stopOnError="true"
        stopOnFailure="true"
        stopOnIncomplete="false"
        stopOnSkipped="false"
        stopOnRisky="false"
        timeoutForSmallTests="1"
        timeoutForMediumTests="10"
        timeoutForLargeTests="60"
        verbose="false">
    <testsuites>
            <testsuite name="PhpRedmin PHP source">
            <directory>src-test/</directory>
            </testsuite>
    </testsuites>
    <logging>
        <log type="coverage-html" target="cover/" lowUpperBound="35" 
highLowerBound="70"/>
    </logging>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">src-test/</directory>
            <directory suffix=".php">src/</directory>
        </whitelist>
    </filter>
</phpunit>

-- 编辑1 --

我发现它与@runInSeparateProcess 有关。当我删除具有 @runInSeparateProcess 的测试时,它开始工作。但我仍然不知道是什么问题

-- 编辑2 --

我还发现,如果我不在 Docker 容器中挂载我的代码目录,一切正常

4

4 回答 4

6

在测试前添加“-d memory_limit=-1”

如果使用作曲家使用下面的代码

./vendor/bin/simple-phpunit -d memory_limit=-1 tests/

如果您使用 phpdbg,请使用以下代码

phpdbg -d memory_limit=-1 -qrr vendor/bin/phpunit --coverage-text
于 2019-12-10T14:13:09.913 回答
5

当我们使用 时@runInSeparateProcess,PHPUnit 将尝试序列化包含的文件、ini 设置、全局变量和常量,以将它们传递给新进程。在这种情况下,看起来 PHPUnit 在序列化这些项目之一时遇到了递归场景,这耗尽​​了 PHP 进程可用的内存。我们需要确定您的本地环境和 Docker 容器之间发生了什么变化。

首先,我们可以尝试禁用这种序列化行为,以验证我们应该沿着这条路径继续。将以下@preserveGlobalState注解添加到失败的测试方法中:

/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function testInSeparateProcess()
{
    // ...
}

如果这解决了问题,或者如果我们得到一个新的错误,我们可以开始寻找可能导致问题的 Docker 容器中的差异。如果没有更多的代码和环境可见性,很难建议从哪里开始,但这里有一些想法:

  • 比较php -i每个环境的输出。寻找存在于一个中的 PHP 扩展,而不是另一个。
  • 用于phpdbg设置断点并单步执行代码。我们已经在使用它来生成覆盖率,但它也是一个有用的调试工具。我们正在寻找导致无限递归的项目。请注意,我们需要在PHPUnit 执行测试用例之前TestCase设置断点,例如在引导文件或 PHPUnit 源代码中(第 810 行可能有效)。
  • 绑定挂载卷时,请确保www-data容器中的用户与拥有主机上文件的用户具有相同的 UID。
  • 尝试在没有内存限制的情况下运行测试。显然我们不能分配错误提示我们可能需要的那么多,但是内存限制可能掩盖了另一个潜在的问题。如果需要,我们可以杀死容器。

我无法在类似环境中使用虚拟测试重现此问题(尽可能接近 - 具有体积的相同容器),因此被测代码可能会导致问题。

于 2017-10-10T01:56:41.933 回答
2

您安装的文件夹可能包含所有供应商和缓存文件。尝试仅安装源文件夹。

于 2017-10-08T07:41:27.250 回答
0

这是 phpdbg 错误。注意它尝试分配多少内存?这太疯狂了。我努力找出错误的确切位置:如果测试脚本全名(目录+脚本文件名)超过一定大小,那么它会溢出堆栈(是的,stackoverflow ;)并覆盖指定必须分配多少内存的整数。然后开始正常的错误处理:没有足够的内存来分配如此疯狂的数量。所以这是由 Krakjoe 解决的。或者我可能会在业余时间为它做一个补丁。如果您现在需要解决:确保您的脚本所在的目录路径很短。

于 2018-07-12T13:12:04.390 回答