Tester sur le parcours Arturo

Apprends à tester tes exercices Arturo sur Exercism


Le parcours Arturo utilise le paquet de tests unitaires Unitt 3.0.0 pour tous les tests des exercices. Ce paquet fournit un framework de tests qui prend en charge à la fois la syntaxe moderne inspirée de RSpec et la syntaxe héritée inspirée de XUnit. Lancer arturo tester.art ou exercism test depuis le dossier de ton exercice en local devrait installer le paquet depuis Internet au premier lancement. Sinon, tu peux installer Unitt en lançant arturo --package install unitt 3.0.0. Seul le premier test sera exécuté et son résultat te sera renvoyé. Une fois ce test réussi, réactive le suivant et relance les tests jusqu'à ce que chaque test passe. Pour les configurations RSpec et XUnit, il suffit de retirer .skip de it.skip ou de test.skip respectivement. Une fois que tous les tests passent, soumets ta solution, mais sache que l'exécuteur de tests exécute tous les tests, même ceux qui sont ignorés.

Pour commencer

Le dossier de ton exercice téléchargé contiendra plusieurs fichiers, mais voici les trois essentiels.

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

Lancer arturo tester.art va installer Unitt puis exécuter les tests qui se trouvent dans tests/test-leap.art. Les tests vont importer src/leap.art, qui contient ta solution, puis faire une série d'assertions sur ce que ta solution doit renvoyer pour des entrées précises.

Le fichier de solution

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

Quand tu commences un exercice, ton fichier de solution contient un modèle avec la structure de base de ce qui est attendu. Dans cet exemple tiré de Leap, le fichier contient une définition minimale de la fonction isLeap? attendue, et notamment un panic qui interrompt l'exécution des tests. Supprime la ligne panic, puis commence à coder ton implémentation de isLeap?.

La structure des tests RSpec

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]
    ]
]
  • describe définit un bloc de cas de test qui vérifient un même point. Ces blocs peuvent être imbriqués.
  • it et it.skip définissent tous les deux un cas de test unique, qui est respectivement exécuté ou ignoré.
  • expects introduit l'assertion qui est au cœur d'un cas de test. expects.be prend une fonction prédicat qui sert à faire l'assertion.

Dans expects.be:'false? @[isLeap? 2015], la suite de tests affirme que la fonction isLeap? doit renvoyer false pour l'année 2015. Une autre façon d'écrire cela est expects.be:'equal? @[false isLeapYear? 2015], où l'on affirme que la valeur renvoyée par isLeapYear? 2015 est égale à false. Cette forme plus longue, qui compare deux valeurs, est le type d'assertion le plus courant sur le parcours Arturo. La valeur attendue vient toujours en premier dans le bloc, avant la valeur obtenue.

La structure des tests XUnit

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
    ]
]

L'API de type XUnit, introduite dans la v1 d'Unitt, est prise en charge pour la rétrocompatibilité et elle est globalement équivalente à l'API moderne de type RSpec, à ceci près que ses assertions sont moins souples.

  • suite définit un bloc de cas de test qui vérifient un même point. Ces blocs peuvent être imbriqués.
  • test et test.skip définissent tous les deux un cas de test unique, qui est respectivement exécuté ou ignoré.
  • assert introduit l'assertion qui est au cœur d'un cas de test. L'expression à droite du -> qui suit doit être vraie.

Avec les tests XUnit, on crée généralement des variables représentant le résultat, et éventuellement la valeur attendue, avant la ligne assert.

La sortie des tests

Que tu utilises l'API RSpec ou l'API XUnit, la sortie des tests sera globalement la même. La seule différence sera ce qui s'affiche sous le nom de chaque test. XUnit rapporte l'assertion avec les valeurs évaluées, tu verras donc false = false. RSpec, lui, la rapporte sous la forme false? false, parce qu'on a utilisé la fonction false? avec expects.

Pour commencer par le début, Arturo signalera une erreur si le panic du fichier de départ n'a pas été supprimé, et n'évaluera aucun test.

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

Une fois le panic remplacé, Arturo indiquera le statut de chaque assertion faite dans un test. Maintenant, le premier test passe, mais le second est ignoré.

======== .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

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

Une fois le second test réactivé manuellement, les deux tests seront exécutés. Cependant, l'implémentation actuelle du code de isLeap? renvoie seulement false, donc le second test échoue à son assertion.

======== .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

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

Ce processus se poursuivra à mesure que tu réactives d'autres tests. Une fois que tous les tests passent, tu as terminé l'exercice et tu peux soumettre la solution. Note bien que l'exécuteur de tests exécutera tous les tests, qu'ils soient ignorés ou non en local.