From 914e3bfbd5572959220d5781c52bef7a738a2334 Mon Sep 17 00:00:00 2001 From: Erik Behrends Date: Mon, 18 Dec 2023 09:11:08 +0100 Subject: [PATCH] Automated testing with Mocha --- .../3-pow-test-wrong/solution.md | 34 +- .../05-testing-mocha/3-pow-test-wrong/task.md | 8 +- .../05-testing-mocha/article.md | 312 +++++++++--------- .../05-testing-mocha/beforeafter.view/test.js | 8 +- .../05-testing-mocha/index.html | 18 +- .../05-testing-mocha/pow-1.view/test.js | 2 +- .../05-testing-mocha/pow-2.view/test.js | 4 +- .../05-testing-mocha/pow-3.view/test.js | 2 +- .../05-testing-mocha/pow-4.view/test.js | 4 +- .../05-testing-mocha/pow-full.view/test.js | 8 +- .../05-testing-mocha/pow-min.view/test.js | 2 +- .../05-testing-mocha/pow-nan.view/test.js | 8 +- 12 files changed, 205 insertions(+), 205 deletions(-) diff --git a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md index 4d0571b9d..c02e09de2 100644 --- a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md +++ b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md @@ -1,49 +1,49 @@ -The test demonstrates one of the temptations a developer meets when writing tests. +Der Test zeigt eine der Versuchungen, denen ein Entwickler beim Schreiben von Tests begegnet. -What we have here is actually 3 tests, but layed out as a single function with 3 asserts. +Was wir hier tatsächlich haben, sind eigentlich 3 Tests, aber angeordnet als einzelne Funktion mit 3 Assertions. -Sometimes it's easier to write this way, but if an error occurs, it's much less obvious what went wrong. +Manchmal ist es einfacher, auf diese Weise zu schreiben, aber wenn ein Fehler auftritt, ist es viel weniger offensichtlich, was schiefgelaufen ist. -If an error happens in the middle of a complex execution flow, then we'll have to figure out the data at that point. We'll actually have to *debug the test*. +Tritt ein Fehler in der Mitte eines komplexen Programmablaufs auf, dann müssen wir die Daten an diesem Punkt herausfinden. Wir müssen tatsächlich *den Test debuggen*. -It would be much better to break the test into multiple `it` blocks with clearly written inputs and outputs. +Es wäre viel besser, den Test in mehrere `it` Blöcke aufzubrechen, mit klar geschriebenen Eingaben und Ausgaben. -Like this: +So zum Beispiel: ```js -describe("Raises x to power n", function() { - it("5 in the power of 1 equals 5", function() { +describe("Erhöht x zur Potenz n", function() { + it("5 in der Potenz 1 gleich 5", function() { assert.equal(pow(5, 1), 5); }); - it("5 in the power of 2 equals 25", function() { + it("5 in der Potenz 2 gleich 25", function() { assert.equal(pow(5, 2), 25); }); - it("5 in the power of 3 equals 125", function() { + it("5 in der Potenz 3 gleich 125", function() { assert.equal(pow(5, 3), 125); }); }); ``` -We replaced the single `it` with `describe` and a group of `it` blocks. Now if something fails we would see clearly what the data was. +Wir haben das einzelnen `it` durch `describe` und eine Gruppe von `it` Blöcken ersetzt. Wenn jetzt etwas fehlschlägt, würden wir klar sehen, welche Daten es waren. -Also we can isolate a single test and run it in standalone mode by writing `it.only` instead of `it`: +Außerdem können wir einen einzelnen Test isolieren und ihn im Standalone-Modus ausführen, indem wir `it.only` statt `it` schreiben: ```js -describe("Raises x to power n", function() { - it("5 in the power of 1 equals 5", function() { +describe("Erhöht x zur Potenz n", function() { + it("5 in der Potenz 1 gleich 5", function() { assert.equal(pow(5, 1), 5); }); *!* - // Mocha will run only this block - it.only("5 in the power of 2 equals 25", function() { + // Mocha wird nur diesen Block ausführen + it.only("5 in der Potenz 2 gleich 25", function() { assert.equal(pow(5, 2), 25); }); */!* - it("5 in the power of 3 equals 125", function() { + it("5 in der Potenz 3 gleich 125", function() { assert.equal(pow(5, 3), 125); }); }); diff --git a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md index 66fece09a..432873bfb 100644 --- a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md +++ b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md @@ -2,12 +2,12 @@ importance: 5 --- -# What's wrong in the test? +# Was ist falsch mit dem Test? -What's wrong in the test of `pow` below? +Was ist falsch bei dem Test von `pow` unten? ```js -it("Raises x to the power n", function() { +it("Erhebt x zur Potenz n", function() { let x = 5; let result = x; @@ -21,4 +21,4 @@ it("Raises x to the power n", function() { }); ``` -P.S. Syntactically the test is correct and passes. +P.S. Syntaxmäßig ist der Test korrekt und besteht. diff --git a/1-js/03-code-quality/05-testing-mocha/article.md b/1-js/03-code-quality/05-testing-mocha/article.md index 4c2b1aa5e..9429d3922 100644 --- a/1-js/03-code-quality/05-testing-mocha/article.md +++ b/1-js/03-code-quality/05-testing-mocha/article.md @@ -1,147 +1,147 @@ -# Automated testing with Mocha +# Automatisiertes Testen mit Mocha -Automated testing will be used in further tasks, and it's also widely used in real projects. +Automatisiertes Testen wird in weiterführenden Aufgaben verwendet und ist auch in echten Projekten weit verbreitet. -## Why do we need tests? +## Warum brauchen wir Tests? -When we write a function, we can usually imagine what it should do: which parameters give which results. +Wenn wir eine Funktion schreiben, können wir uns normalerweise vorstellen, was sie tun soll: Welche Parameter welche Ergebnisse liefern. -During development, we can check the function by running it and comparing the outcome with the expected one. For instance, we can do it in the console. +Während der Entwicklung können wir die Funktion überprüfen, indem wir sie ausführen und das Ergebnis mit dem erwarteten vergleichen. Zum Beispiel können wir das in der Konsole tun. -If something is wrong -- then we fix the code, run again, check the result -- and so on till it works. +Wenn etwas nicht stimmt, dann reparieren wir den Code, führen ihn erneut aus, überprüfen das Ergebnis - und so weiter, bis es funktioniert. -But such manual "re-runs" are imperfect. +Aber solche manuellen "Neustarts" sind unvollkommen. -**When testing a code by manual re-runs, it's easy to miss something.** +**Beim Testen eines Codes durch manuelle Neustarts passiert es schnell, etwas zu übersehen.** -For instance, we're creating a function `f`. Wrote some code, testing: `f(1)` works, but `f(2)` doesn't work. We fix the code and now `f(2)` works. Looks complete? But we forgot to re-test `f(1)`. That may lead to an error. +Angenommen wir erstellen eine Funktion `f`. Wir haben Code geschrieben, übergeprüft: `f(1)` funktioniert, aber `f(2)` funktioniert nicht. Wir reparieren den Code und jetzt funktioniert `f(2)`. Sieht vollständig aus? Aber wir haben vergessen, `f(1)` erneut zu testen. Das könnte zu einem Fehler führen. -That's very typical. When we develop something, we keep a lot of possible use cases in mind. But it's hard to expect a programmer to check all of them manually after every change. So it becomes easy to fix one thing and break another one. +Das ist sehr typisch. Wenn wir etwas entwickeln, behalten wir viele mögliche Anwendungsfälle im Kopf. Aber es ist schwer zu erwarten, dass ein Programmierer sie nach jeder Änderung manuell überprüft. Daher wird es leicht, eine Sache zu reparieren und eine andere kaputtzumachen. -**Automated testing means that tests are written separately, in addition to the code. They run our functions in various ways and compare results with the expected.** +**Automatisiertes Testen bedeutet, dass Tests separat geschrieben werden, zusätzlich zum Code. Sie führen unsere Funktionen auf verschiedene Weise aus und vergleichen die Ergebnisse mit dem Erwarteten.** ## Behavior Driven Development (BDD) -Let's start with a technique named [Behavior Driven Development](http://en.wikipedia.org/wiki/Behavior-driven_development) or, in short, BDD. +Beginnen wir mit einer Technik namens [Behavior Driven Development](http://de.wikipedia.org/wiki/Behavior-driven_development) oder kurz BDD. -**BDD is three things in one: tests AND documentation AND examples.** +**BDD ist dreierlei in einem: Tests UND Dokumentation UND Beispiele.** -To understand BDD, we'll examine a practical case of development. +Um BDD zu verstehen, werden wir einen praktischen Fall der Entwicklung untersuchen. -## Development of "pow": the spec +## Entwicklung von "pow": die Spezifikation -Let's say we want to make a function `pow(x, n)` that raises `x` to an integer power `n`. We assume that `n≥0`. +Nehmen wir an, wir möchten eine Funktion `pow(x, n)` erstellen, die `x` auf die ganzzahlige Potenz `n` erhöht. Wir gehen davon aus, dass `n≥0`. -That task is just an example: there's the `**` operator in JavaScript that can do that, but here we concentrate on the development flow that can be applied to more complex tasks as well. +Diese Aufgabe ist nur ein Beispiel: Es gibt den Operator `**` in JavaScript, der das kann, aber hier konzentrieren wir uns auf den Entwicklungsfluss, der auch auf komplexere Aufgaben angewandt werden kann. -Before creating the code of `pow`, we can imagine what the function should do and describe it. +Bevor wir den Code von `pow` erstellen, können wir uns vorstellen, was die Funktion tun sollte und sie beschreiben. -Such description is called a *specification* or, in short, a spec, and contains descriptions of use cases together with tests for them, like this: +Diese Beschreibung wird als *Spezifikation* oder kurz *Spec* bezeichnet und enthält Beschreibungen der Anwendungsfälle zusammen mit Tests für diese, wie folgt: ```js describe("pow", function() { - it("raises to n-th power", function() { + it("erhöht auf die n-te Potenz", function() { assert.equal(pow(2, 3), 8); }); }); ``` -A spec has three main building blocks that you can see above: +Eine Spezifikation hat drei Hauptbestandteile, die du oben sehen kannst: -`describe("title", function() { ... })` -: What functionality we're describing? In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks. +`describe("titel", function() { ... })` +: Welche Funktionalität beschreiben wir? In unserem Fall beschreiben wir die Funktion `pow`. Wird verwendet um "Worker" -- die `it` Blöcke -- zu gruppieren. -`it("use case description", function() { ... })` -: In the title of `it` we *in a human-readable way* describe the particular use case, and the second argument is a function that tests it. +`it("Beschreibung des Anwendungsfalls", function() { ... })` +: Im Titel von `it` beschreiben wir *auf eine für den Menschen lesbare Weise* den speziellen Anwendungsfall, und das zweite Argument ist eine Funktion, die diesen testet. -`assert.equal(value1, value2)` -: The code inside `it` block, if the implementation is correct, should execute without errors. +`assert.equal(wert1, wert2)` +: Der Code im `it`-Block, wenn die Implementierung korrekt ist, sollte ohne Fehler ausgeführt werden. - Functions `assert.*` are used to check whether `pow` works as expected. Right here we're using one of them -- `assert.equal`, it compares arguments and yields an error if they are not equal. Here it checks that the result of `pow(2, 3)` equals `8`. There are other types of comparisons and checks, that we'll add later. + Funktionen `assert.*` werden benutzt, um zu überprüfen, ob `pow` wie erwartet funktioniert. Hier benutzen wir eine von ihnen -- `assert.equal`, die Argumente vergleicht und einen Fehler auslöst, wenn sie nicht gleich sind. Hier überprüft sie, dass das Resultat von `pow(2, 3)` gleich `8` ist. Es gibt andere Arten von Vergleichen und Überprüfungen, die wir später hinzufügen werden. -The specification can be executed, and it will run the test specified in `it` block. We'll see that later. +Die Spezifikation kann ausgeführt werden, und sie führt den Test aus, der im `it`-Block spezifiziert ist. Das werden wir später sehen. -## The development flow +## Der Entwicklungsablauf -The flow of development usually looks like this: +Der Entwicklungsablauf sieht normalerweise so aus: -1. An initial spec is written, with tests for the most basic functionality. -2. An initial implementation is created. -3. To check whether it works, we run the testing framework [Mocha](https://mochajs.org/) (more details soon) that runs the spec. While the functionality is not complete, errors are displayed. We make corrections until everything works. -4. Now we have a working initial implementation with tests. -5. We add more use cases to the spec, probably not yet supported by the implementations. Tests start to fail. -6. Go to 3, update the implementation till tests give no errors. -7. Repeat steps 3-6 till the functionality is ready. +1. Eine anfängliche Spezifikation wird geschrieben, mit Tests für die grundlegendste Funktionalität. +2. Eine Erstimplementierung wird erstellt. +3. Um zu überprüfen, ob sie funktioniert, führen wir das Test-Framework [Mocha](https://mochajs.org/) aus (mehr Details bald), das die Spec ausführt. Solange die Funktionalität nicht komplett ist, werden Fehler angezeigt. Wir machen Korrekturen, bis alles funktioniert. +4. Jetzt haben wir eine funktionierende Implementierung mit Tests. +5. Wir fügen mehr Anwendungsfälle zur Spezifikation hinzu, die wahrscheinlich noch nicht von der Implementierung unterstützt werden. Die Tests beginnen zu fehlzuschlagen. +6. Gehe zu 3, aktualisiere die Implementierung, bis Tests keine Fehler mehr anzeigen. +7. Wiederhole Schritte 3-6, bis die Funktionalität fertig ist. -So, the development is *iterative*. We write the spec, implement it, make sure tests pass, then write more tests, make sure they work etc. At the end we have both a working implementation and tests for it. +Die Entwicklung ist also *iterativ*. Wir schreiben die Spezifikation, implementieren sie, stellen sicher, dass die Tests bestehen, dann schreiben wir mehr Tests, stellen sicher, dass sie funktionieren usw. Am Ende haben wir sowohl eine funktionierende Implementierung als auch Tests dafür. -Let's see this development flow in our practical case. +Betrachten wir diesen Entwicklungsablauf anhand unseres praktischen Beispiels. -The first step is already complete: we have an initial spec for `pow`. Now, before making the implementation, let's use a few JavaScript libraries to run the tests, just to see that they are working (they will all fail). +Der erste Schritt ist bereits abgeschlossen: Wir haben eine erste Spezifikation für `pow`. Jetzt, bevor wir die Implementierung vornehmen, lass uns ein paar JavaScript-Bibliotheken verwenden, um die Tests auszuführen, nur um zu sehen, dass sie funktionieren (sie werden alle fehlschlagen). -## The spec in action +## Die Spezifikation in Aktion -Here in the tutorial we'll be using the following JavaScript libraries for tests: +Hier im Tutorial werden wir die folgenden JavaScript-Bibliotheken für Tests verwenden: -- [Mocha](https://mochajs.org/) -- the core framework: it provides common testing functions including `describe` and `it` and the main function that runs tests. -- [Chai](https://www.chaijs.com/) -- the library with many assertions. It allows to use a lot of different assertions, for now we need only `assert.equal`. -- [Sinon](https://sinonjs.org/) -- a library to spy over functions, emulate built-in functions and more, we'll need it much later. +- [Mocha](https://mochajs.org/) -- das Kernframework: Es bietet gemeinsame Testfunktionen, einschließlich `describe` und `it` und die Hauptfunktion, die Tests ausführt. +- [Chai](https://www.chaijs.com/) -- die Bibliothek mit vielen Assertions (Zusicherungen). Sie ermöglicht die Verwendung vieler verschiedener Assertions, im Moment benötigen wir nur `assert.equal`. +- [Sinon](https://sinonjs.org/) -- eine Bibliothek zum Überwachen von Funktionen, zum Emulieren von eingebauten Funktionen und mehr. Wir werden sie viel später benötigen. -These libraries are suitable for both in-browser and server-side testing. Here we'll consider the browser variant. +Diese Bibliotheken eignen sich sowohl für das Testen im Browser als auch auf der Serverseite. Hier werden wir die Browser-Variante betrachten. -The full HTML page with these frameworks and `pow` spec: +Die vollständige HTML-Seite mit diesen Frameworks und der `pow`-Spezifikation: ```html src="index.html" ``` -The page can be divided into five parts: +Die Seite kann in fünf Teile unterteilt werden: -1. The `` -- add third-party libraries and styles for tests. -2. The ` - + @@ -20,17 +20,17 @@ - + - +
- + diff --git a/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js index 89ba412ed..42731267e 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js @@ -1,6 +1,6 @@ describe("pow", function() { - it("raises to n-th power", function() { + it("erhöht auf die n-te Potenz", function() { assert.equal(pow(2, 3), 8); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js index c803f0e61..341841ef5 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js @@ -1,10 +1,10 @@ describe("pow", function() { - it("2 raised to power 3 is 8", function() { + it("2 erhöht auf Potenz 3 ist 8", function() { assert.equal(pow(2, 3), 8); }); - it("3 raised to power 4 is 81", function() { + it("3 erhöht auf Potenz 4 ist 81", function() { assert.equal(pow(3, 4), 81); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js index 8663952aa..7a0701803 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js @@ -2,7 +2,7 @@ describe("pow", function() { function makeTest(x) { let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { + it(`${x} zur Potenz 3 ist ${expected}`, function() { assert.equal(pow(x, 3), expected); }); } diff --git a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js index e5ce2ce43..244f439c0 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js @@ -1,10 +1,10 @@ describe("pow", function() { - describe("raises x to power 3", function() { + describe("erhöht x auf Potenz 3", function() { function makeTest(x) { let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { + it(`${x} zur Potenz 3 ist ${expected}`, function() { assert.equal(pow(x, 3), expected); }); } diff --git a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js index 75ff5e99f..fdb4912a1 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js @@ -1,10 +1,10 @@ describe("pow", function() { - describe("raises x to power 3", function() { + describe("erhöht x auf Potenz 3", function() { function makeTest(x) { let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { + it(`${x} zur Potenz 3 is ${expected}`, function() { assert.equal(pow(x, 3), expected); }); } @@ -15,11 +15,11 @@ describe("pow", function() { }); - it("if n is negative, the result is NaN", function() { + it("für negatives n ist das Ergebnis NaN", function() { assert.isNaN(pow(2, -1)); }); - it("if n is not integer, the result is NaN", function() { + it("für nicht-ganzzahliges n ist das Ergebnis NaN", function() { assert.isNaN(pow(2, 1.5)); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js index 89ba412ed..42731267e 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js @@ -1,6 +1,6 @@ describe("pow", function() { - it("raises to n-th power", function() { + it("erhöht auf die n-te Potenz", function() { assert.equal(pow(2, 3), 8); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js index 75ff5e99f..61f73424a 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js @@ -1,10 +1,10 @@ describe("pow", function() { - describe("raises x to power 3", function() { + describe("erhöht x auf Potenz 3", function() { function makeTest(x) { let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { + it(`${x} zur Potenz 3 ist ${expected}`, function() { assert.equal(pow(x, 3), expected); }); } @@ -15,11 +15,11 @@ describe("pow", function() { }); - it("if n is negative, the result is NaN", function() { + it("für negatives n ist das Ergebnis NaN", function() { assert.isNaN(pow(2, -1)); }); - it("if n is not integer, the result is NaN", function() { + it("für nicht-ganzzahliges n ist das Ergebnis NaN", function() { assert.isNaN(pow(2, 1.5)); });