Jest 30: Schneller, schlanker, besser
Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →
Heute freuen wir uns, die Veröffentlichung von Jest 30 bekannt zu geben. Dieses Release umfasst eine beträchtliche Anzahl von Änderungen, Fehlerbehebungen und Verbesserungen. Obwohl es sich um eines der größten Major-Releases in der Jest-Geschichte handelt, geben wir zu, dass drei Jahre für ein Major-Release zu lang sind. Künftig streben wir häufigere Major-Releases an, um Jest auch im nächsten Jahrzehnt erstklassig zu halten.
Wenn Sie direkt loslegen möchten, ohne die Neuerungen zu lesen, führen Sie npm install jest@^30.0.0 aus und folgen Sie dem Migrationsleitfaden: Upgrading from Jest 29 to 30.
Was ist neu?
Jest 30 ist spürbar schneller, verbraucht weniger Speicher und bringt zahlreiche neue Funktionen mit. Zunächst werfen wir einen Blick auf die Breaking Changes:
Breaking Changes
-
Jest 30 stellt die Unterstützung für Node 14, 16, 19 und 21 ein.
-
jest-environment-jsdomwurde von jsdom 21 auf 26 aktualisiert. -
Die minimal unterstützte TypeScript-Version ist nun 5.4.
-
Verschiedene
expect-Aliase wurden entfernt. Dereslint-plugin-jestbietet einen Autofixer, den Sie ausführen können, um Ihre Codebase automatisch zu aktualisieren. -
Nicht aufzählbare Objekteigenschaften werden standardmäßig von Objekt-Matchern wie
toEqualausgeschlossen. -
Jest unterstützt nun standardmäßig
.mts- und.cts-Dateien. -
--testPathPatternwurde in--testPathPatternsumbenannt. -
Jest behandelt Promises nun korrekt, die zunächst abgelehnt und später abgefangen werden, um falsch-positive Testfehler zu vermeiden.
-
Wir haben verschiedene Verbesserungen an Jests Snapshot-Darstellung vorgenommen, die möglicherweise Snapshot-Updates erfordern. Google hat
goo.gl-Links eingestellt, die wir in Snapshots verwendet haben. Das gefällt uns auch nicht, aber Sie müssen alle Ihre Snapshots aktualisieren. -
Jest selbst wird nun pro Paket in eine einzelne Datei gebündelt. Dies verbessert die Leistung, kann aber Probleme verursachen, wenn Sie Tools entwickelt haben, die auf Jests interne Struktur zugreifen.
Dies sind nur einige Highlights. Die vollständige Liste der Breaking Changes finden Sie im CHANGELOG und im Jest 30 Migrationsleitfaden.
Leistung & Speicherverbesserungen
Jest 30 bietet spürbare Leistungssteigerungen durch zahlreiche Optimierungen, insbesondere bei der Modulauflösung, Speichernutzung und Testisolierung. Durch die Verwendung des neuen unrs-resolver wurde die Modulauflösung in Jest funktionsreicher, standardkonformer und schneller. Dank an @JounQin für die Migration. Je nach Projekt können Sie deutlich schnellere Testläufe und reduzierten Speicherverbrauch beobachten. Beispielsweise verzeichnete eine große TypeScript-Anwendung mit Client und Server in einem Teil ihrer Codebase 37% schnellere Testläufe und 77% geringeren Speicherverbrauch:
| Jest 29 | Jest 30 | |
|---|---|---|
| Server tests | ~1350s / 7.8 GB max | ~850s / 1.8 GB max |
| Client tests | ~49s / 1.0 GB max | ~44s / 0.8 GB max |
Jest ist schnell, aber aufgrund der Testisolierung können langsame Benutzercodes Leistungsprobleme verschärfen und zu langsamen Testläufen führen. Wenn Tests offene Handles wie ungeschlossene Timer oder Verbindungen zu anderen Diensten hinterlassen, kann dies zu Hängern oder Verlangsamungen von Jest führen. Jest 30 erkennt und meldet solche Probleme besser, was Ihnen hilft, langsame oder problematische Tests leichter zu identifizieren und zu beheben. Bei Happo wurden Tests beispielsweise durch Bereinigung offener Handles und ein Upgrade auf Jest 30 um 50% beschleunigt – von 14 auf 9 Minuten.
Wenn Sie Dateien verwenden, die Exporte mehrerer Module in einer einzigen Datei konsolidieren (sogenannte "Barrel-Dateien"), empfehlen wir Tools wie babel-jest-boost, babel-plugin-transform-barrels oder no-barrel-file. Diese vermeiden das Laden großer Teile des Anwendungscodes für jede Testdatei und können zu Leistungssteigerungen von bis zu 100x führen.
Bereinigung von Globals zwischen Testdateien
Jest erreicht Testisolierung zwischen Dateien, indem jeder Test in einem separaten VM-Kontext läuft, was jeder Datei eine frische globale Umgebung bietet. Wenn Ihr Code jedoch Globals nach jeder Testdatei nicht bereinigt, kann dies zu Speicherlecks in Jest führen und Ihre Testläufe verlangsamen. Jest 30 führt ein neues Feature ein, das Sie über nicht korrekt bereinigte Globals nach einem Testlauf informiert.
Zukünftig wird Jest Globals automatisch nach jedem Testlauf bereinigen. Falls Sie mit Jest 30 keine Warnungen zu unbereinigten Globals erhalten, können Sie den Bereinigungsmodus bereits jetzt auf "on" setzen, um dieses Feature vollständig zu aktivieren und von erheblichen Speichereinsparungen und Leistungsverbesserungen zu profitieren:
export default {
testEnvironmentOptions: {
globalsCleanup: 'on',
},
};
Die Standardeinstellung in Jest ist globalsCleanup: 'soft'. Um dieses Feature zu deaktivieren, können Sie es auf off setzen. Wenn Sie bestimmte globale Objekte vor der Bereinigung schützen müssen – beispielsweise gemeinsame Hilfsfunktionen oder Caches – können Sie diese mit jest-util als geschützt markieren:
import {protectProperties} from 'jest-util';
protectProperties(globalThis['my-property']);
Ein Dank geht an @eyalroth für die Implementierung dieses Features!
Neue Funktionen
Verbesserte Unterstützung für ECMAScript-Module & TypeScript
Die Unterstützung für import.meta.* und file:// wurde bei der Verwendung von nativen ESM mit Jest hinzugefügt. Zusätzlich können Sie nun Ihre Jest-Konfigurationsdateien in TypeScript schreiben, und .mts- sowie .cts-Dateien werden nativ unterstützt, ohne zusätzliche Konfiguration zu benötigen. Falls Sie Node's native TypeScript-Typenentfernungsfunktion nutzen, laden wir den TypeScript-Transformer nicht mehr, was zu schnelleren Testläufen führt.
Spies und das using-Schlüsselwort
Sie können nun JavaScripts neue explizite Ressourcenverwaltungssyntax (using) mit Jest-Spies verwenden. Wenn Ihre Umgebung dies unterstützt, wird durch using jest.spyOn(obj, 'method') der Spy automatisch beim Verlassen des Blocks zurückgesetzt, sodass keine manuelle Bereinigung nötig ist.
test('logs a warning', () => {
using spy = jest.spyOn(console, 'warn');
doSomeThingWarnWorthy();
expect(spy).toHaveBeenCalled();
});
expect.arrayOf
Jest 30 führt einen neuen asymmetrischen Matcher ein: expect.arrayOf. Dieser ermöglicht die Validierung jedes Elements eines Arrays gegen eine Bedingung oder einen Typ. Beispielsweise können Sie ein Zahlenarray prüfen, bei dem alle Elemente Zahlen sind:
expect(someArray).toEqual(expect.arrayOf(expect.any(Number)));
Neuer test.each-Platzhalter: %$
Bei datengesteuerten Tests mit test.each können Sie jetzt den speziellen Platzhalter %$ in Ihren Testtiteln verwenden, um die laufende Nummer des Testfalls einzufügen. Beispiel:
test.each(cases)('Case %$ works as expected', () => {});
ersetzt %$ durch die laufende Nummer des Testfalls.
jest.advanceTimersToNextFrame()
@sinonjs/fake-timers wurde auf v13 aktualisiert und fügt jest.advanceTimersToNextFrame() hinzu. Diese neue Funktion ermöglicht es, alle ausstehenden requestAnimationFrame-Callbacks zur nächsten Frame-Grenze vorzurücken. Dadurch lassen sich Animationen oder Code, der auf requestAnimationFrame angewiesen ist, leichter testen, ohne Millisekunden schätzen zu müssen.
Konfigurierbare Test-Wiederholungen
Jest 30 erweitert jest.retryTimes() mit neuen Optionen, die Ihnen mehr Kontrolle über den Umgang mit Wiederholungen geben. Sie können eine Verzögerung festlegen oder einen fehlgeschlagenen Test sofort wiederholen, anstatt auf das Ende der gesamten Testsuite zu warten:
// Retry failed tests up to 3 times, waiting 1 second between attempts:
jest.retryTimes(3, {waitBeforeRetry: 1000});
// Immediately retry without waiting for other tests to finish:
jest.retryTimes(3, {retryImmediately: true});
jest.unstable_unmockModule()
Jest 30 führt die neue experimentelle API jest.unstable_unmockModule() für eine präzisere Steuerung beim Aufheben von Mocks ein (insbesondere bei Verwendung von nativen ESM).
jest.onGenerateMock(callback)
Eine neue Methode onGenerateMock wurde hinzugefügt. Sie registriert eine Callback-Funktion, die immer dann aufgerufen wird, wenn Jest einen Mock für ein Modul generiert. Dieser Callback ermöglicht es Ihnen, den Mock zu modifizieren, bevor er an Ihre Testumgebung zurückgegeben wird:
jest.onGenerateMock((modulePath, moduleMock) => {
if (modulePath.includes('Database')) {
moduleMock.connect = jest.fn().mockImplementation(() => {
console.log('Connected to mock DB');
});
}
return moduleMock;
});
Weitere Verbesserungen
Benutzerdefinierte Objektserialisierung
Jest's Matcher-Utilities unterstützen nun die Definition einer statischen SERIALIZABLE_PROPERTIES auf benutzerdefinierten Objekten. Dadurch können Sie steuern, welche Eigenschaften eines benutzerdefinierten Objekts in Snapshots und Fehlermeldungen einbezogen werden, was die Ausgabe fokussierter und relevanter macht.
Asynchrone Setup-Unterstützung
Testdateien, die in setupFilesAfterEnv aufgelistet sind, können nun eine asynchrone Funktion exportieren oder Top-Level-await verwenden, ähnlich wie setupFiles.
Und so viel mehr…
Werfen Sie einen Blick in das vollständige CHANGELOG, um alle Änderungen, Verbesserungen und neuen Funktionen zu sehen.
Bekannte Probleme
jsdom hat Änderungen vorgenommen, um spezkonformer zu werden. Dies könnte einige Anwendungsfälle beeinträchtigen, insbesondere das Mocking von window.location in Tests. Jest liefert nun @jest/environment-jsdom-abstract mit, um die Erstellung eigener benutzerdefinierter Testumgebungen auf jsdom-Basis zu vereinfachen. Wenn Sie nur einen Patch für jsdom suchen, können Sie diesen jsdom-Patch in Ihrem Projekt anwenden. In Zukunft könnten wir Alternativen zu jsdom erwägen, die besser für Tests geeignet sind.
Was kommt als Nächstes?
Jest ist seit einem Jahrzehnt das beliebteste JavaScript-Testframework. Es wird von Millionen Entwicklern genutzt und unterstützt Projekte von kleinen Bibliotheken bis zu den größten Codebasen der Welt. Jest wurde kontinuierlich verbessert, aber wie bei allen langlebigen Softwareprojekten im realen Einsatz haben wir technische Schulden angehäuft. Wir unterstützen Funktionen, die nur wenige Personen oder Unternehmen nutzen, und haben Breaking Changes minimiert, um Nutzer nicht zu stören. Einige Features sollten durch Jest ermöglicht werden, aber nicht als Teil des Kernframeworks. Andere fördern falsche Testansätze und gehören vielleicht gar nicht zu Jest. Zudem haben einige Teammitglieder gewechselt, was zu langsamerem Fortschritt und weniger Releases führte. So gehen wir diese Probleme zukünftig an:
-
Performance/Technische Schulden: Schlankeres Jest-Kernframework mit Fokus auf Leistung. Entfernung weniger genutzter Funktionen und Konzentration auf die Kernstärken.
-
Konsistente Release-Zyklen: Wir streben konsistentere Release-Zyklen und klare Deprecation-Richtlinien an.
-
Transparenz: Entwicklung vollständig im Open Source, transparente Planung. Mehr Mitwirkungsmöglichkeiten und Wachstum der Contributor-Community.
-
Seien wir mutig: Als Jest-Team sollten wir mutiger sein. Es gibt einige Faktoren, die Jest davon abhalten, sein volles Potenzial zu erreichen. Es ist Zeit zu handeln.
Die gute Nachricht ist, dass Jest bereits seit seiner Konzeption als modulares System mit klarer Aufgabentrennung ideal aufgestellt war, um diese Prinzipien umzusetzen. Jetzt geht es an die Umsetzung. Mehr dazu in Kürze!
Danksagung
Diese Veröffentlichung wäre ohne die harte Arbeit unserer Community nicht möglich gewesen. Vielen Dank.
@SimenB, @mrazauskas, @Connormiha, @liuxingbaoyu, @k-rajat19, @G-Rath, @charpeni, @dubzzz, @stekycz, @yinm, @lencioni, @phawxby, @lukeapage, @robhogan, @fisker, @k-rajat19, @connectdotz, @alesmenzel, @rickhanlonii, @mbelsky, @brunocabral88, @brandon-leapyear, @nicolo-ribaudo, @dj-stormtrooper, @eryue0220
Besonderen Dank an alle, die in dieser Version ihren ersten Beitrag zu Jest geleistet haben. Vielen Dank, dass ihr Jest für alle besser macht!
@eyalroth, @KhaledElmorsy, @mohammednumaan, @bensternthal, @BondarenkoAlex, @phryneas, @jayvdb, @brandonchinn178, @latin-1, @rmartine-ias, @fa93hws, @Dunqing, @gustav0d, @noritaka1166, @andreibereczki, @Dreamsorcerer, @satanTime, @icholy, @ecraig12345, @cgm-16, @sebastiancarlos, @dancer1325, @loganrosen, @zakingslayerv22, @dev-intj, @tez3998, @anbnyc, @pengqiseven, @thypon, @co63oc, @danielrentz, @jonasongg, @andrew-the-drawer, @phryneas, @hyperupcall, @tonyd33, @madcapnmckay, @dongwa, @gagan-bhullar-tech, @ikonst, @ZuBB, @jzaefferer, @brandonnorsworthy, @henny1105, @DmitryMakhnev, @askoufis, @RahulARanger, @Jon-Biz, @fynsta, @KonnorRogers, @BondarenkoAlex, @mouadhbb, @kemuridama, @Avi-E-Koenig, @davidroeca, @akwodkiewicz, @mukul-turing, @dnicolson, @colinacassidy, @ofekm97, @haze, @Vadimchesh, @peterdenham, @ShuZhong, @manoraj, @nicolo-ribaudo, @georgekaran, @MathieuFedrigo, @hkdobrev, @Germandrummer92, @CheadleCheadle, @notaphplover, @danbeam, @arescrimson, @yepitschunked, @JimminiKin, @DerTimonius, @vkml, @ginabethrussell, @jeremiah-snee-openx, @WillianAgostini, @casey-lentz, @faizanu94, @someone635, @rafaelrabelos, @RayBrokeSomething, @DaniAcu, @mattkubej, @tr1ckydev, @shresthasurav, @the-ress, @Mutesa-Cedric, @nolddor, @alexreardon, @Peeja, @verycosy, @mknight-atl, @maro1993, @Eric-Tyrrell22






