PHPUnit覆盖:允许内存大小536870912字节用尽

我试图用PHPUnit和phpdbg使用下面的命令为我的PHP项目生成代码testing覆盖:

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的testing时,它开始工作。 但是我仍然不知道是什么问题

– 编辑2 –

另外我发现,如果我不在我的代码目录在Docker容器中安装一切正常

您的挂载文件夹可能包含所有供应商和caching文件。 尝试只安装源文件夹。

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

首先,我们可以尝试禁用这个序列化行为来validation我们应该沿着这条路走下去。 将以下@preserveGlobalState批注添加到失败的testing方法:

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

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

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

我不能在类似的环境中使用虚拟testing来重现此问题(尽可能地接近容量相同的容器),所以testing中的代码可能会导致问题。