Tesztelés az Arturo-kurzuson

Tanuld meg, hogyan tesztelheted az Arturo-feladataidat az Exercism-ön


Az Arturo-kurzus minden feladat tesztjéhez a Unitt 3.0.0 egységtesztelő csomagot használja. Ez a csomag olyan tesztelési keretrendszert ad, amely egyszerre támogatja a modern, RSpec ihlette szintaxist és a régi, XUnit ihlette szintaxist. Ha a helyi feladatmappádból futtatod az arturo tester.art vagy az exercism test parancsot, az első futáskor a csomag telepítődik az internetről. A Unitt-et úgy is telepítheted, hogy lefuttatod az arturo --package install unitt 3.0.0 parancsot. Először csak az első teszt fut le, és annak az eredményét kapod vissza. Amint az a teszt sikeres, a következőnél szüntesd meg a kihagyást, és futtasd újra a teszteket, amíg minden teszt sikeres nem lesz. Az RSpec és az XUnit esetében ez annyit tesz, hogy törlöd a .skip részt az it.skip-ből, illetve a test.skip-ből. Amint minden teszt sikeres, küldd be a megoldásodat, de vedd figyelembe, hogy a tesztfuttató az összes tesztet lefuttatja, még a kihagyottakat is.

Első lépések

A letöltött feladatmappádban több fájl is lesz, de ez a három a lényeges.

leap/
├── src/leap.art         # Your solution file
├── tests/test-leap.art  # Test cases for the exercise
└── tester.art           # Test runner entry point

Az arturo tester.art futtatása beállítja a Unitt-et, majd lefuttatja a tests/test-leap.art fájlban lévő teszteket. A tesztek beimportálják a src/leap.art fájlt, amely a megoldásodat tartalmazza, majd egy sor állítást fogalmaznak meg arról, hogy a megoldásodnak mit kell visszaadnia adott bemenetekre.

A megoldásfájl

isLeap?: function [year][
    panic "please implement the isLeap? function"
]

Amikor elkezdesz egy feladatot, a megoldásfájlod egy sablonnal érkezik, amely az elvárt alapstruktúrát tartalmazza. Ebben a Leap-ből vett példában a fájl az elvárt isLeap? függvény csontvázszerű definícióját tartalmazza, és ami igazán fontos, egy panic-et, amely leállítja a teszt végrehajtását. Töröld a panic sort, és kezdd el megírni az isLeap? implementációját.

Az RSpec tesztek felépítése

import.version:3.0.0 {unitt}!
import {src/leap}!

describe "Leap" [
    it "a year not divisible by 4 is a common year" [
        expects.be:'false? @[isLeap? 2015]
    ]

    it.skip "a year divisible by 4 and not divisible by 100 is a leap year" [
        expects.be:'true? @[isLeap? 1996]
    ]
]
  • A describe olyan tesztesetek blokkját definiálja, amelyek ugyanazt a dolgot ellenőrzik. Ezek egymásba is ágyazhatók.
  • Az it és az it.skip egyaránt egyetlen tesztesetet definiál, amely rendre lefut vagy ki van hagyva.
  • Az expects vezeti be az állítást, amely a teszteset lényege. Az expects.be egy predikátumfüggvényt kap, amellyel megfogalmazza az állítást.

Az expects.be:'false? @[isLeap? 2015] esetében a tesztkészlet azt állítja, hogy az isLeap? függvénynek false-t kell visszaadnia a 2015-ös évre. Ezt így is leírhatod: expects.be:'equal? @[false isLeapYear? 2015], ahol azt állítjuk, hogy az isLeapYear? 2015 visszatérési értéke egyenlő false-tal. Ez a két értéket összehasonlító, hosszabb forma a leggyakoribb állítástípus az Arturo-kurzuson. Az elvárt érték mindig elöl, a kapott érték előtt szerepel a blokkban.

Az XUnit tesztek felépítése

suite "Leap" [
    test "a year not divisible by 4 is a common year" [
        result: isLeap? 2015
        assert -> false = result
    ]

    test.skip "a year divisible by 4 and not divisible by 100 is a leap year" [
        result: isLeap? 1996
        assert -> true = result
    ]
]

A Unitt v1-ében bevezetett XUnit-szerű API-t a visszafelé kompatibilitás miatt támogatjuk, és nagyjából egyenértékű a modern, RSpec-szerű API-val, leszámítva a kevésbé rugalmas állításait.

  • A suite olyan tesztesetek blokkját definiálja, amelyek ugyanazt a dolgot ellenőrzik. Ezek egymásba is ágyazhatók.
  • A test és a test.skip egyaránt egyetlen tesztesetet definiál, amely rendre lefut vagy ki van hagyva.
  • Az assert vezeti be az állítást, amely a teszteset lényege. Az utána következő -> jobb oldalán álló kifejezésnek igaznak kell lennie.

Az XUnit-teszteknél jellemzően az assert sor előtt hozunk létre változókat az eredményhez, és opcionálisan az elvárt értékhez.

A tesztek kimenete

Akár az RSpec, akár az XUnit API-t használod, a tesztek kimenete nagyjából hasonló lesz. Az egyetlen különbség az lesz, hogy mi jelenik meg az egyes tesztek neve alatt. Az XUnit a kiértékelt értékekkel jelenti az állítást, így például false = false jelenik meg. Az RSpec viszont false? false formában jelenti, mert az expects-szel a false? függvényt használtuk.

Kezdetben, ha a kiinduló fájlból nem távolítottad el a panic-et, az Arturo hibát jelez, és egyetlen tesztet sem értékel ki.

Uncaught error in tests/test-leap.art:
#[
        output: {
                
                ══╡ Program Error ╞═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ <script> ══
                
                  Please implement the isLeap? function
                
                
        }
        code: 1
]

Amint a panic-et lecserélted, az Arturo minden egyes teszten belüli állítás állapotát jelenti. Most az első teszt sikeres, a második viszont ki van hagyva.

======== .unitt/tests/test-leap.art ========

Describe: Leap

    ✅ - assert that a year not divisible by 4 is a common year
         ✅: false? false

    ⏩ - assert that a year divisible by 4 and not divisible by 100 is a leap year
         skipped!


========== Summary ==========

⏏️   TOTAL: 2 assertions
✅  PASSED: 1 assertion
⏩ SKIPPED: 1 assertion
❌  FAILED: 0 assertion

========== ======= ==========

Miután a második teszt kihagyását manuálisan megszüntetted, mindkét teszt lefut. A jelenlegi isLeap? implementáció azonban csak false-t ad vissza, ezért a második teszt megbukik az állításán.

======== .unitt/tests/test-leap.art ========

Describe: Leap

    ✅ - assert that a year not divisible by 4 is a common year
         ✅: false? false

    ❌ - assert that a year divisible by 4 and not divisible by 100 is a leap year
         ❌: true? false


========== Summary ==========

⏏️   TOTAL: 2 assertions
✅  PASSED: 1 assertion
⏩ SKIPPED: 0 assertion
❌  FAILED: 1 assertion

========== ======= ==========

Ez a folyamat addig tart, ahogy egyre több teszt kihagyását szünteted meg. Amint minden teszt sikeres, készen vagy a feladattal, és beküldheted a megoldást. Ne feledd, hogy a tesztfuttató helyben az összes tesztet lefuttatja, akár ki vannak hagyva, akár nem.