PHPUnit-Abdeckung: Zulässige Speichergröße von 536870912 Bytes erschöpft

Lesezeit: 6 Minuten

Benutzer-Avatar
Sasan Rose

Ich versuche, Code-Testabdeckung für mein PHP-Projekt mit PHPUnit und phpdbg mit dem folgenden Befehl zu generieren:

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

Das funktioniert einwandfrei:

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

Wenn ich jedoch genau denselben Befehl in einem Docker-Container verwende:

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

Ich bekomme folgenden Fehler:

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]

Ich verstehe nicht, warum PHPUnit 561514763337856 Bytes Speicher zuweisen muss. Ich vermute, es bleibt in einer Schleife hängen, aber warum passiert das nicht außerhalb des Containers? Hier ist meine PHP-Version auf meinem Rechner:

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

Und hier ist die Datei .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>

— Edit1 —

Ich habe festgestellt, dass es etwas mit @runInSeparateProcess zu tun hat. Wenn ich den Test mit @runInSeparateProcess entferne, beginnt er zu funktionieren. Aber ich weiß immer noch nicht, was das Problem ist

— Edit2 —

Außerdem habe ich herausgefunden, dass alles einwandfrei funktioniert, wenn ich mein Codeverzeichnis nicht im Docker-Container mounte

  • Welches Docker-Image verwendest du? ist PHP als Dienst oder als Apache-Modul? , versuchen Sie, den PHP-Speicher in der php.ini zu erhöhen

    – Joaquín Javi

    27. September 2017 um 12:51 Uhr

  • Auf welchem ​​Betriebssystem läuft das?

    – Tarun Lalwani

    27. September 2017 um 17:15 Uhr

  • @JoaquinJavi Wie Sie sehen können, ist es php:7.0-apache: 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 Ich kann mein Speicherlimit nicht auf 561514763337856 Bytes erhöhen

    – SasanRose

    27. September 2017 um 23:21 Uhr


  • @TarunLalwani nein das ist nicht der Fall

    – SasanRose

    3. Oktober 2017 um 5:27 Uhr

  • Können Sie ein Git-Repo mit einem Mindestbeispiel bereitstellen, mit dem ich dies reproduzieren kann?

    – Tarun Lalwani

    6. Oktober 2017 um 9:28 Uhr

Fügen Sie vor Ihrem Test ‘-d memory_limit=-1’ hinzu

Wenn Sie Composer verwenden, verwenden Sie den folgenden Code

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

Wenn Sie phpdbg verwenden, verwenden Sie den folgenden Code

phpdbg -d memory_limit=-1 -qrr vendor/bin/phpunit --coverage-text

  • Ich hatte einen Bug in vermutet phpdbg oder eine rekursive Schleife in meinem Code, die sich nur beim Testen manifestiert, aber leider war die Lösung genau so, wie Sie es beschreiben: phpdbg brauchte nur mehr Speicher! Ich musste den Standardwert von 128 MB verdoppeln und 256 MB verwenden (ich mag die Idee nicht, unbegrenzt zu verwenden).

    – Ben Johnson

    17. Dezember 2019 um 14:01 Uhr

Benutzer-Avatar
Cy Rossignol

Wenn wir verwenden @runInSeparateProcess, versucht PHPUnit, enthaltene Dateien, INI-Einstellungen, globale Variablen und Konstanten zu serialisieren, um sie an den neuen Prozess zu übergeben. In diesem Fall sieht es so aus, als ob PHPUnit beim Serialisieren eines dieser Elemente auf ein rekursives Szenario gestoßen ist, das den für den PHP-Prozess verfügbaren Speicher erschöpft hat. Wir müssen feststellen, was sich zwischen Ihrer lokalen Umgebung und dem Docker-Container geändert hat.

Zunächst können wir versuchen, dieses Serialisierungsverhalten zu deaktivieren, um zu überprüfen, ob wir auf diesem Weg fortfahren sollten. Fügen Sie Folgendes hinzu @preserveGlobalState Anmerkung zur fehlgeschlagenen Prüfmethode:

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

Wenn das Problem dadurch behoben wird oder wir einen neuen Fehler erhalten, können wir damit beginnen, nach Unterschieden im Docker-Container zu suchen, die das Problem verursachen könnten. Ohne mehr Einblick in den Code und die Umgebung ist es schwer vorzuschlagen, wo man anfangen soll, aber hier sind einige Ideen:

  • Vergleichen Sie die Ausgabe von php -i aus jeder Umgebung. Achten Sie auf PHP-Erweiterungen, die in der einen, aber nicht in der anderen vorhanden sind.
  • Verwenden phpdbg um einen Haltepunkt zu setzen und den Code schrittweise zu durchlaufen. Wir verwenden es bereits, um Abdeckung zu generieren, aber es ist auch ein nützliches Debugging-Tool. Wir suchen nach dem Element, das die unendliche Rekursion verursacht. Beachten Sie, dass wir den Haltepunkt setzen müssen Vor PHPUnit führt den Testfall wie in der Bootstrap-Datei oder im PHPUnit-Quellcode aus (Zeile 810 der TestCase könnte funktionieren).
  • Stellen Sie beim Bind-Mounten eines Volumes sicher, dass die www-data Der Benutzer im Container hat dieselbe UID wie der Benutzer, dem die Dateien auf dem Host gehören.
  • Versuchen Sie, den Test ohne die Speicherbegrenzung auszuführen. Offensichtlich können wir nicht so viel zuweisen, wie der Fehler vermuten lässt, aber die Speicherbegrenzung kann ein anderes zugrunde liegendes Problem verbergen. Wir können den Container bei Bedarf töten.

Ich konnte dieses Problem nicht mit einem Dummy-Test in einer ähnlichen Umgebung reproduzieren (so nah wie möglich – gleicher Container mit Volume), sodass der zu testende Code möglicherweise zu dem Problem beiträgt.

Ihr gemounteter Ordner enthält wahrscheinlich alle Anbieter und Cache-Dateien. Versuchen Sie, nur den Quellordner zu mounten.

  • Aber alle phpunit-Dateien und Dateien von Drittanbietern, die in meinen Tests benötigt werden, befinden sich in den Anbietern. Was bringt es, sie nicht zu montieren?

    – SasanRose

    9. Oktober 2017 um 10:07 Uhr


  • Sie können weiterhin auf Anbieter und phpunit zugreifen. Das Volume ist eine Art symbolischer Link zu den Dateien, was bedeutet, dass die Änderungen an diesen Dateien auch nach dem Stoppen des Containers beibehalten werden. damit kannst du es versuchen docker run -it --name YM4UPltmiPMjObaVULwsIPIkPL2bGL0T -e USER=sasan -v "/home/sasan/Project/phpredmin/src:/phpredmin/src" -w "/phpredmin" --user "1000:www-data" php:7.0-apache phpdbg -dmemory_limit=512M -qrr ./bin/phpunit -c .phpunit.cover.xml docs.docker.com/glossary/?term=volume

    – Ascha

    10. Oktober 2017 um 10:50 Uhr


Dies ist ein phpdbg-Fehler. Beachten Sie, wie viel Speicher versucht wird, zuzuweisen? Es ist verrückt. Ich habe mich bemüht herauszufinden, wo genau der Fehler liegt: Wenn der vollständige Name des Testskripts (Verzeichnis + Name der Skriptdatei) eine bestimmte Größe überschreitet, überläuft es den Stapel (ja, Stapelüberlauf 😉 und überschreibt eine ganze Zahl, die angibt, wie viel Speicher zugewiesen werden muss. Dann setzt die normale Fehlerbehandlung ein: nicht genug Speicher, um eine so verrückte Menge zuzuweisen. Das muss also Krakjoe beheben. Oder vielleicht mache ich in meiner Freizeit einen Patch dafür. Wenn Sie sofort eine Lösung benötigen: Stellen Sie sicher, dass der Verzeichnispfad, in dem sich Ihr Skript befindet, kurz ist.

1029750cookie-checkPHPUnit-Abdeckung: Zulässige Speichergröße von 536870912 Bytes erschöpft

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy