Hallo allerseits! Der
JavaScript Developer- Kurs beginnt diesen Donnerstag. In diesem Zusammenhang haben wir beschlossen, die Übersetzung eines anderen interessanten Materials zu teilen. Gute Lektüre.
Scherz war schon immer mein unverzichtbares Werkzeug für Unit-Tests. Es ist so zuverlässig, dass ich anfange zu denken, dass ich es immer zu wenig genutzt habe. Obwohl die Tests funktionierten, habe ich sie im Laufe der Zeit hier und da überarbeitet, weil ich nicht wusste, dass Jest das kann. Dies ist jedes Mal ein neuer Code, wenn ich die Jest-Dokumentation überprüfe.
Also werde ich einige meiner Lieblings-Jest-Tricks teilen, die einige von Ihnen vielleicht bereits kennen, weil Sie die Dokumentation gelesen haben und mich nicht mögen (schade), aber ich hoffe, dies hilft denen, die es gerade schnell durchlaufen haben !
Übrigens verwende ich Jest v24.8.0 als Referenzmaterial. Seien Sie also vorsichtig, einige Dinge funktionieren möglicherweise nicht mit der Version von Jest, die Sie derzeit verwenden. Außerdem stellen die Beispiele nicht den tatsächlichen Testcode dar, dies ist nur eine Demonstration.
# 1 .toBe vs .toEqual
Alle diese Aussagen sahen für mich zunächst normal aus:
expect('foo').toEqual('foo') expect(1).toEqual(1) expect(['foo']).toEqual(['foo'])
Basierend auf der Verwendung von
Chai für Gleichheitserklärungen (to.equal) ist dies nur natürlich. Tatsächlich wird sich Jest nicht beschweren, und diese Aussagen werden wie gewohnt weitergegeben.
Jest hat jedoch .toBe und .toEqual. Die erste dient dazu, die Gleichheit mit
Object.is zu gewährleisten , und die zweite dient dazu, einen umfassenden Vergleich von Objekten und Arrays zu ermöglichen. .toEqual hat einen Fallback bei der Verwendung von
Object.is, wenn sich herausstellt, dass Sie keinen umfassenden Vergleich benötigen, z. B. das Festlegen von Gleichheiten für primitive Werte, was erklärt, warum das vorherige Beispiel sehr gut gelaufen ist.
expect('foo').toBe('foo') expect(1).toBe(1) expect(['foo']).toEqual(['foo'])
Auf diese Weise können Sie alle
if-else
in
.toEqual
mit
.toBe
wenn Sie bereits wissen, welche Werte Sie testen.
Ein häufiger Fehler ist, dass Sie
.toBe
, um die Gleichheit primitiver Werte zu behaupten.
expect(['foo']).toBe(['foo'])
Wenn Sie sich den
Quellcode ansehen, wenn .toBe abstürzt, wird versucht, festzustellen, ob Sie diesen Fehler wirklich gemacht haben,
indem Sie die von .toEqual verwendete
Funktion aufrufen. Dies kann ein Engpass bei der Optimierung Ihres Tests sein.
Wenn Sie sicher sind, dass Sie primitive Werte verwenden, kann Ihr Code zu Optimierungszwecken als solcher neu organisiert werden:
expect(Object.is('foo', 'foo')).toBe(true)
Weitere Details in der
Dokumentation .
# 2 Besser geeignete Vergleiche
Technisch gesehen können Sie
.toBe
, um beliebige Werte zu validieren. Mit Jest können Sie bestimmte Vergleichstools speziell verwenden, um Ihren Test besser lesbar (und in einigen Fällen kürzer) zu machen.
Dies sind nur einige von denen, die ich aus der langen Liste der Jest-Compiler in der Dokumentation ausgewählt habe. Sie können sich den Rest selbst ansehen.
# 3 Schnappschuss-Test an Elementen ohne Benutzeroberfläche
Möglicherweise haben Sie von
Snapshot-Tests in Jest gehört , mit denen Sie Änderungen an den Elementen Ihrer Benutzeroberfläche nachverfolgen können. Das Testen mit Schnappschüssen ist jedoch nicht darauf beschränkt.
Betrachten Sie dieses Beispiel:
const allEmployees = getEmployees() const happyEmployees = giveIncrementByPosition(allEmployees) expect(happyEmployees[0].nextMonthPaycheck).toBe(1000) expect(happyEmployees[1].nextMonthPaycheck).toBe(5000) expect(happyEmployees[2].nextMonthPaycheck).toBe(4000)
Es wäre anstrengend, wenn Sie immer mehr Mitarbeiter beanspruchen würden. Wenn sich herausstellt, dass für jeden Mitarbeiter mehr Ansprüche erforderlich sind, multiplizieren Sie die Anzahl der neuen Ansprüche mit der Anzahl der Mitarbeiter, und Sie erhalten eine Vorstellung.
Mit Snapshot-Tests kann dies einfach so durchgeführt werden:
const allEmployees = getEmployees() const happyEmployees = giveIncrementByPosition(allEmployees) expect(happyEmployees).toMatchSnapshot()
Wann immer Regressionen auftreten, wissen Sie genau, welcher Baum im Knoten nicht mit dem Bild übereinstimmt.
Bequemlichkeit hat jedoch ihren Preis: Diese Methode ist fehleranfälliger. Es besteht die Möglichkeit, dass Sie nicht wissen, dass das Bild tatsächlich falsch ist, und dass Sie es am Ende trotzdem aufnehmen werden. Überprüfen Sie Ihren Schnappschuss also so, als wäre er Ihr eigener Genehmigungscode (weil er es ist).
Natürlich ist das Testen nicht auf Schnappschüsse beschränkt. Lesen Sie die vollständige
Dokumentation .
# 4 beschreiben.jeder und test.jeder
Haben Sie jemals einen ähnlichen Test geschrieben?
describe('When I am a supervisor', () => { test('I should have a supervisor badge', () => { const employee = new Employee({ level: 'supervisor' }) expect(employee.badges).toContain('badge-supervisor') }) test('I should have a supervisor level', () => { const employee = new Employee({ level: 'supervisor' }) expect(employee.level).toBe('supervisor') }) }) describe('When I am a manager', () => { test('I should have a manager badge', () => { const employee = new Employee({ level: 'manager' }) expect(employee.badges).toContain('badge-manager') }) test('I should have a manager level', () => { const employee = new Employee({ level: 'manager' }) expect(employee.level).toBe('manager') }) })
Das ist eintönig und routinemäßig, oder? Stellen Sie sich vor, Sie tun dies in vielen Fällen.
Mit
description.each
und
test.each
Sie den Code wie folgt komprimieren:
const levels = [['manager'], ['supervisor']] const privileges = [['badges', 'toContain', 'badge-'], ['level', 'toBe', '']] describe.each(levels)('When I am a %s', (level) => { test.each(privileges)(`I should have a ${level} %s`, (kind, assert, prefix) => { const employee = new Employee({ level }) expect(employee[kind])[assert](`${prefix}${level}`) }) })
Ich muss dies jedoch noch in meinem eigenen Test verwenden, da ich es vorziehe, dass mein Test detailliert ist, aber ich dachte nur, dass es ein interessanter Trick wäre.
Weitere Details zu den Argumenten finden Sie in der
Dokumentation (Spoiler: Die Tabellensyntax ist wirklich cool).
# 5 Einzelne Nachahmung globaler Funktionen
Irgendwann müssen Sie etwas testen, das von globalen Funktionen in einem bestimmten Testfall abhängt. Zum Beispiel eine Funktion, die mithilfe des Date-Javascript-Objekts Informationen zum aktuellen Datum empfängt, oder eine Bibliothek, die darauf angewiesen ist. Die Schwierigkeit besteht darin, dass Sie beim aktuellen Datum nie die richtige Aussage treffen können.
function foo () { return Date.now() } expect(foo()).toBe(Date.now())
Am Ende müssten Sie das globale Date-Objekt neu definieren, damit es konsistent und verwaltbar ist:
function foo () { return Date.now() } Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
Dies wird jedoch als schlechte Praxis angesehen, da die Neudefinition zwischen den Tests beibehalten wird. Sie werden dies nicht bemerken, wenn es keinen anderen Test gibt, der auf Date.now basiert, aber es wird auch auslaufen.
test('First test', () => { function foo () { return Date.now() Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
Ich habe es immer „geknackt“, damit es nicht ausläuft:
test('First test', () => { function foo () { return Date.now() const oriDateNow = Date.now Date.now = () => 1234567890123 expect(foo()).toBe(1234567890123)
Es gibt jedoch einen viel besseren und weniger hackenden Weg, dies zu tun:
test('First test', () => { function foo () { return Date.now() jest.spyOn(Date, 'now').mockImplementationOnce(() => 1234567890123) expect(foo()).toBe(1234567890123)
Somit folgt
jest.spyOn
dem globalen Date-Objekt und ahmt die Implementierung der now-Funktion für nur einen Aufruf nach. Dadurch bleibt Date.now für den Rest der Tests intakt.
Es gibt definitiv mehr Informationen über Stubs in Jest. Weitere Informationen finden Sie in der vollständigen
Dokumentation .
Dieser Artikel wird lang genug, also denke ich, das ist alles für jetzt. Dies betrifft nur einen kleinen Teil der Funktionen von Jest, und ich hebe nur meine Favoriten hervor. Wenn Sie andere interessante Fakten haben, lassen Sie es mich wissen.
Wenn Sie Jest häufig verwendet haben, schauen Sie sich
Majestic an , eine GUI-freie GUI für Jest, eine wirklich gute Alternative zur langweiligen Terminalausgabe. Ich bin mir nicht sicher, ob der Autor in dev.to ist, aber dennoch Respekt für diese Person.
Wie immer vielen Dank für Ihre Aufmerksamkeit!
Das ist alles. Wir sehen uns auf dem Kurs.