Emscripten verfügt über eine umfassende Test-Suite, die praktisch alle Emscripten-Funktionen abdeckt. Diese Tests sind eine hervorragende Ressource für Entwickler, da sie praktische Beispiele für die meisten Funktionen bieten und dafür bekannt sind, auf dem Master-Branch erfolgreich zu bestehen. Zusätzlich zu Korrektheitstests gibt es auch Benchmarks, die Sie ausführen können.
Dieser Artikel erklärt, wie man die Test- und Benchmark-Suite ausführt, und bietet einen Überblick über die verfügbaren Tests.
Um die Tests auszuführen, benötigen Sie ein Emscripten-Setup, da emcc und andere Befehle ausgeführt werden. Siehe den Leitfaden für Entwickler für die beste Vorgehensweise.
Führen Sie den Test-Suite-Runner (test/runner) mit --help aus, um die Hilfemeldung anzuzeigen.
test/runner --help
Die Tests sind in Modi unterteilt. Sie können entweder einen gesamten Modus oder einen einzelnen Test ausführen oder Platzhalter (Wildcards) verwenden, um bestimmte Tests in bestimmten Modi auszuführen. Zum Beispiel:
# run one test (in the default mode)
test/runner test_foo
# run a bunch of tests in one mode (here, all i64 tests in -O3)
test/runner core3.test_*i64*
# run all tests in a specific mode (here, wasm2gs -O1)
test/runner wasm2js1
Die Core-Testmodi (definiert am Ende von test/test_core.py) ermöglichen es Ihnen, die Tests in einer Vielzahl von Konfigurationen und mit verschiedenen Optimierungs-Flags auszuführen. Zum Beispiel wasm2js oder wasm64. Es gibt auch Nicht-Core-Test-Suites, die Tests auf eine speziellere Weise ausführen (insbesondere ist es in diesen Tests nicht möglich zu sagen „führe den Test mit einem anderen Optimierungs-Flag aus“ - genau dafür sind die Core-Tests da). Die Nicht-Core-Test-Suites umfassen:
other: Nicht-Core-Tests, die in der Shell laufen.
browser: Tests, die in einem Browser laufen.
sockets: Netzwerktests, die in einem Browser laufen.
interactive: Browser-Tests, die nicht vollständig automatisiert sind und Benutzerinteraktion erfordern (diese sollten irgendwann automatisiert werden).
sanity: Tests für die Selbsteinrichtung von Emscripten. Dies verändert vorübergehend Ihre .emscripten-Datei.
benchmark: Führt Benchmarks aus und misst Geschwindigkeit sowie Codegröße.
Die oben erwähnten Platzhalter funktionieren auch für Nicht-Core-Testmodi, zum Beispiel:
# run one browser test
test/runner browser.test_sdl_image
# run all SDL2 browser tests
test/runner browser.test_sdl2*
# run all browser tests
test/runner browser
Ein einzelner Test kann übersprungen werden, indem das Präfix „skip:“ übergeben wird. Z.B.
test/runner other skip:other.test_cmake
Platzhalter können auch in skip übergeben werden, also
test/runner browser skip:browser.test_pthread_*
wird die gesamte Browser-Suite ausführen, außer allen darin enthaltenen Pthread-Tests.
Manchmal ist es nützlich, iterativ einen Test nach dem anderen beheben zu können. In diesem Fall kann die Option --failfast verwendet werden, um den Test-Runner nach dem ersten Fehler zu beenden.
Hinweis
Diese Option funktioniert nur mit dem seriellen Test-Runner. Für Test-Suites, die normalerweise parallel laufen, können Sie die serielle Ausführung mit -j1 erzwingen.
Sobald ein Test behoben ist, fahren Sie mit der Option --start-at an der Stelle fort, an der Sie aufgehört haben.
test/runner browser --start-at test_foo --failfast
Sie können eine zufällige Teilmenge der Test-Suite ausführen, indem Sie etwas verwenden wie:
test/runner random100
Ersetzen Sie 100 durch eine andere Zahl Ihrer Wahl. Dies führt die entsprechende Anzahl an zufälligen Tests aus und gibt Ihnen die statistische Wahrscheinlichkeit an, dass fast die gesamte Test-Suite besteht, vorausgesetzt, diese Tests tun es. Dies funktioniert genau wie bei Wahlumfragen – anhand einer kleinen Stichprobe können wir ziemlich gut vorhersagen, dass so-und-so viel Prozent der Öffentlichkeit für Kandidat A stimmen werden. In unserem Fall sind die „Kandidaten“ Bestehen oder Nichtbestehen, und wir können vorhersagen, wie viel der Test-Suite bestehen wird, basierend auf dieser Stichprobe. Angenommen, die Stichprobentests bestehen alle, können wir mit hoher Wahrscheinlichkeit sagen, dass tatsächlich der Großteil der Test-Suite bestehen wird. (Natürlich ist dies keine Garantie, und selbst ein einzelner Testfehler ist schwerwiegend; dies bietet jedoch eine schnelle Schätzung, dass Ihr Patch keine signifikanten und offensichtlichen Fehler verursacht.)
Bitte schauen Sie am Ende der Datei test/test_core.py nach den aktuellen Testmodi, da sich diese im Laufe der Zeit langsam ändern können. Wenn Sie die gesamte Test-Suite lokal ausführen möchten, sind dies derzeit die wichtigen Befehle:
# Run all core tests
test/runner core*
# Run "other" test suite
test/runner other
# Run "browser" test suite - this requires a web browser
test/runner browser
# Run "sockets" test suite - this requires a web browser too
test/runner sockets
# Run "sanity" test suite - this tests setting up emscripten during
# first run, etc., and so it modifies your .emscripten file temporarily.
test/runner sanity
# Optionally, also run benchmarks to check for regressions
test/runner benchmark
Emscripten verfügt über eine Benchmark-Suite, die sowohl die Geschwindigkeit als auch die Codegröße misst. Sie umfasst mehrere interessante reale Codebasen, von Physik-Engines über Kompressionsbibliotheken bis hin zu virtuellen Maschinen. Sie enthält auch einige bestehende Benchmarks wie CoreMark und LINPACK. Siehe zum Beispiel den Abschnitt über Geschwindigkeit in diesem Beitrag, der einen Überblick gibt.
Um die Benchmark-Suite auszuführen, geben Sie Folgendes ein:
# Run all benchmarks
test/runner benchmark
Wie bei allen Test-Suites können Sie auch einen spezifischen Benchmark ausführen:
# Run one specific benchmark
test/runner benchmark.test_skinning
Sie können auch festlegen, welche Benchmarker ausgeführt werden, indem Sie die Umgebungsvariable EMTEST_BENCHMARKERS verwenden. Sie akzeptiert eine durch Kommata getrennte Liste von benannten Benchmarkern (Namen finden sich in named_benchmarkers in test/test_benchmark.py).
# Run one specific benchmark and with clang and v8.
EMTEST_BENCHMARKERS=clang,v8 test/runner benchmark.test_skinning
Um die Ausführung der Benchmarks weiter anzupassen, können Sie die Datei test/test_benchmark.py bearbeiten. Zu den Optionen gehören:
DEFAULT_ARG bestimmt, wie lange der Benchmark laufen soll (alle versuchen für eine konsistente Zeitdauer zu laufen).
TEST_REPS gibt an, wie oft jeder Durchlauf wiederholt werden soll (mehr Wiederholungen dauern länger, sollten aber weniger Rauschen aufweisen).
PROFILING steuert, ob die Builds für das Profiling eingerichtet werden (was die Codegröße erhöhen kann und daher standardmäßig nicht aktiviert ist).
Das Einstellen des Debug-Modus (EMCC_DEBUG) ist nützlich für das Debugging von Tests, da es Debug-Ausgaben und Zwischendateien erzeugt (die Dateien werden in /tmp/emscripten_temp/ abgelegt).
# On Windows, use "set" to set and un-set the EMCC_DEBUG environment variable:
set EMCC_DEBUG=1
test/runner test_hello_world
set EMCC_DEBUG=0
# On Linux, you can do this all in one line
EMCC_DEBUG=1 test/runner test_hello_world
# EMCC_DEBUG=2 generates additional debug information.
EMCC_DEBUG=2 test/runner test_hello_world
Sie können auch --save-dir angeben, um das temporäre Verzeichnis, das der Test-Runner verwendet, in /out/test/ zu speichern. Dies ist eine spezifische Funktion der Test-Suite und nützlich zur Untersuchung von Testausgaben sowie von temporären Dateien, die durch den Test erzeugt wurden. Standardmäßig wird das temporäre Verzeichnis zwischen jedem Testlauf bereinigt, aber Sie können --no-clean hinzufügen, um dies zu verhindern.
Das Thema Debugging bietet weitere Anleitungen zum Debuggen von durch Emscripten generiertem Code.