Testing
Testing
Abschnitt betitelt „Testing“Schreibe und führe Tests für deinen Lua-Code mit dem Framework wippy/test aus — ein
Runner im BDD-Stil mit Assertions, Lifecycle-Hooks und Mocking, ausgeführt über den
Befehl wippy run test.
Was du bauen wirst
Abschnitt betitelt „Was du bauen wirst“Eine kleine Bibliothek und eine Test-Suite, die sie abdeckt:
- Eine
calc-Bibliothek mit den Funktionenaddunddiv. - Ein Test-Entry, das Fälle beschreibt, Verhalten prüft und einen ausstehenden Fall überspringt.
- Ein grüner Testlauf via
wippy run test.
Voraussetzungen
Abschnitt betitelt „Voraussetzungen“-
Ein Wippy-Projekt (klone app-template oder führe
wippy initin einem leeren Verzeichnis aus). -
Das Test-Framework und ein Terminal-Host sind installiert:
Terminal-Fenster wippy add wippy/testwippy add wippy/terminalwippy installDer Runner rendert eine Live-Terminal-UI, daher ist
wippy/terminalnebenwippy/testerforderlich.
Der zu testende Code
Abschnitt betitelt „Der zu testende Code“-- src/calc.lualocal function add(a, b) return a + bend
local function div(a, b) if b == 0 then return nil, "division by zero" end return a / bend
return { add = add, div = div }Der Test
Abschnitt betitelt „Der Test“Ein Test ist ein gewöhnliches function.lua-Entry, das mit meta.type: test getaggt ist.
Seine Methode gibt den von test.run_cases(...) erzeugten Wert zurück, den der Runner
aufruft:
-- src/calc_test.lualocal test = require("test")local calc = require("calc")
local function define_tests() test.describe("calculator", function() local started = false
test.before_all(function() started = true end)
test.it("setup ran", function() test.is_true(started) end)
test.it("adds numbers", function() test.eq(calc.add(2, 3), 5) end)
test.it("returns error on divide by zero", function() local result, err = calc.div(1, 0) test.has_error(result, err) test.contains(err, "division by zero") end)
test.it_skip("not implemented yet", function() test.fail("should not run") end) end)end
return { run = test.run_cases(define_tests) }Registriere beide Einträge. Die Erkennung knüpft an meta.type: test an; meta.suite
gruppiert die Ergebnisse in der Ausgabe:
version: "1.0"namespace: app
entries: - name: calc kind: library.lua source: file://calc.lua
- name: calc_test kind: function.lua meta: name: Calculator Test type: test suite: calculator source: file://calc_test.lua method: run imports: test: wippy.test:test calc: app:calcDie imports-Map steuert, worauf require(...) innerhalb des Tests aufgelöst wird:
test bindet das Framework, calc bindet die zu testende Einheit.
Ausführen
Abschnitt betitelt „Ausführen“wippy run testFiltere während des Iterierens auf eine einzelne Suite (passt zur Entry-ID oder zum Suite-Namen):
wippy run test calculatorAusgabe für die obige Suite:
calculator (4) 3/4 1 skipped 1ms o setup ran o adds numbers o returns error on divide by zero - not implemented yet (skipped)
PASSED 3 tests 1 skipped 1mswippy run test beendet sich mit 0, wenn jeder Fall besteht, und mit 1 bei
jedem Fehlschlag, sodass es sich direkt in CI einfügt.
Assertions
Abschnitt betitelt „Assertions“Jede Assertion wirft bei einem Fehlschlag; die Typ-Guards geben zudem den validierten Wert zurück.
| Assertion | Prüft |
|---|---|
test.eq(a, b) / test.neq(a, b) | Gleichheit / Ungleichheit |
test.ok(v) / test.fail(msg) | Truthy / Fehlschlag erzwingen |
test.is_nil(v) / test.not_nil(v) | Nil / nicht-nil |
test.is_true(v) / test.is_false(v) | Boolescher Wert |
test.is_string/number/table/function/boolean(v) | Typ-Guards (geben v zurück) |
test.contains(str, sub) / test.matches(str, pattern) | Teilstring / Lua-Pattern |
test.has_key(tbl, key) / test.len(v, n) | Map-Schlüssel / Länge |
test.gt/gte/lt/lte(a, b) | Numerischer Vergleich |
test.throws(fn) / test.has_error(val, err) / test.no_error(val, err) | Fehlerbehandlung |
Alle nehmen ein optionales abschließendes Nachrichtenargument entgegen.
Lifecycle und Mocking
Abschnitt betitelt „Lifecycle und Mocking“Rufe diese innerhalb eines describe-Blocks auf:
test.before_all/test.after_all— laufen einmal pro Block.test.before_each/test.after_each— laufen rund um jeden Fall.test.mock("module.field", fn)— ersetzt eine Funktion für den aktuellen Fall; Mocks werden nach jedem Fall automatisch wiederhergestellt. Verwendetest.restore_all_mocks(), um sie frühzeitig zu löschen.
Verschachtelte describe-Blöcke erben die Hooks des übergeordneten Blocks (äußere
before_* zuerst, innere after_* zuerst).
Nächste Schritte
Abschnitt betitelt „Nächste Schritte“- Hello World — das minimale Projekt-Layout
- Entry-Arten —
function.lua,library.luaund Verwandte - Test-Framework — vollständige Referenz für den Runner und das Event-Protokoll