01.02 — ISTQB vs pytest / Jest / Mocha#
Le constat méthodologique#
Au-delà du pari technique sur la barrière techniques / non-techniques (voir 01-flip-the-problem.md), il y a un second pari : celui du vocabulaire métier.
L’ISTQB et les testeurs professionnels ont construit, depuis des décennies, un vocabulaire précis et éprouvé : cycles de test, campagnes, suites de test, cas de test, pas de test. Une hiérarchie claire, pensée pour organiser, tracer et piloter la qualité logicielle.
Les outils automatisés, eux, ont largement ignoré cet héritage.
pytest, Jest, Mocha… tous sont un mix hybride où les testeurs doivent apprendre à penser comme des développeurs, et où personne ne parle vraiment la même langue.
La conséquence architecturale#
Ocarina prend ce vocabulaire au sérieux et le transpose littéralement dans la hiérarchie de classes.
| Vocabulaire ISTQB | Classe Ocarina | Fichier source |
|---|---|---|
| Pas de test | act() (verbe utilisateur, retourne ActionStart[TPOM]) | src/ocarina/dsl/testing_with_railway/constructors/create_act.py |
| Cas de test | Test[Driver] | src/ocarina/dsl/testing/oc_test.py |
| Suite de test | TestSuite[Driver] | src/ocarina/dsl/testing/oc_test_suite.py |
| Campagne | TestCampaign[Driver] | src/ocarina/dsl/testing/oc_test_campaign.py |
| Cycle | TestCycle[Driver] | src/ocarina/dsl/testing/oc_test_cycle.py |
Ce ne sont pas des « namespaces décoratifs » : chaque niveau a une responsabilité distincte (cf. ../02-ocarina/05-orchestration/) :
| Niveau | Responsabilité |
|---|---|
act | Une action atomique sur une page. |
Test | Métadonnées (name, test_id, skipped) + scénario + fragments pre/post + watchers. |
TestSuite | Pool de drivers, parallélisation, saturation, filtrage IDs, retries policy. |
TestCampaign | Séquence de suites avec config workers partagée. |
TestCycle | Smoke + main, mode appliqué aux smokes tests (fail-fast | wait-for-all). |
La rupture avec pytest#
Ocarina n’est pas un plugin pytest. Le README l’affirme explicitement :
Ships its own test runner: Ocarina is NOT a pytest plugin.
Pourquoi ?
- Le vocabulaire pytest n’est pas l’ISTQB. pytest a
test_function,parametrize,fixture,conftest. C’est cohérent en interne mais c’est un autre univers. Faire d’Ocarina un plugin pytest aurait obligé à traduire, exactement ce que la philosophie refuse (cf.01-flip-the-problem.md). - Indépendance. Un plugin dépend de l’API de son hôte. Ocarina veut être auditable en une après-midi, sans connaître pytest.
- Posture envers les fixtures. Ocarina remplace les fixtures par des closures + scenario fragments + Effect pour
setup/teardown. La posture est celle du « poor man’s rich » : un seul mécanisme, la closure, pour toutes les injections. Une closure suffit là où la POO classique invoquerait fixtures + scopes + héritage.
La rupture avec Cucumber / Gherkin#
Aucun fichier .feature, aucune step definition, aucun glue layer. Le scénario est du Python, exécutable directement, typé directement, refactorisable directement. Aucune traduction permanente à maintenir.
Le « langage » qu’expose Ocarina aux scénarios n’est pas un DSL textuel ; c’est un DSL Python embedded :
return [
drive_page(
act(on_homepage, open_then_verify_homepage)
.failure(just_log_error("Failed to reach the homepage..."))
.success(log_success_with_current_url_and_take_screenshot("On the homepage!")),
act(on_homepage, click_book_call_page_cta)
.failure(just_log_error("Failed to click on the 'Book a call' CTA..."))
.success(just_log_success("Clicked on the 'Book a call' CTA!")),
),
drive_page(
act(on_book_a_call_page, verify_book_call_page)
.failure(just_log_error("Failed to verify the 'Book a call' page..."))
.success(log_success_with_current_url_and_take_screenshot("On the 'Book a call' page!")),
),
]C’est du Python pur. Aucun lexer, aucun runtime tiers, aucune traduction. Et c’est typé : la moindre incompatibilité est une erreur mypy (cf. ../02-ocarina/03-railway/02-action-chain-states.md).
Conséquence sur le reporting#
Le reporting aussi colle au vocabulaire ISTQB. pretty_print_results produit :
Campaign
• Suite
> Test case 1
» PASSED
> Test case 2
» FAILED
→ Error message
⫸ At step 3Trois indentations, trois niveaux : campagne, suite, cas. Le step est mentionné comme contexte d’échec (« At step 3 »). Aucun nom de classe Python n’apparaît dans la sortie : l’utilisateur final voit du vocabulaire métier, pas du code.
Glossaire ISTQB ↔ Ocarina#
| Terme ISTQB | Terme Ocarina | Note |
|---|---|---|
| Test step | act() | Action atomique. |
| Test case | Test[Driver] | Encapsule un scénario. |
| Test scenario | Scenario[Driver] | Composé d’une test_chain, d’un setup, d’un teardown, de watchers. |
| Test suite | TestSuite[Driver] | Parallélisé. |
| Test campaign | TestCampaign[Driver] | Séquentiel (entre suites). |
| Test cycle | TestCycle[Driver] | Smoke + main, fail-fast ou wait-for-all. |
| Smoke test | smoke_tests_campaigns= | Gate. |
| Setup | Scenario.setup: Effect | Effect. |
| Teardown | Scenario.teardown: Effect | Effect également ; toujours exécuté, erreurs ignorées. |
| Test report | pretty_print_results, generate_docx_proof, generate_json_results | Plugins post-exec. |
Lien avec l’évolution du système de types Python#
Le Holy Book trace une dépendance fine : ce vocabulaire ne pouvait pas être incarné aussi rigoureusement avant les generics PEP 695, parce qu’il faut pouvoir paramétrer TestSuite[Driver] avec un type de driver précis :
Les récentes évolutions du système de types de Python, sur lequel Ocarina s’appuie profondément, font partie de la raison-même de sa faisabilité.
C’est aussi pour cette raison que le framework est en requires-python = ">=3.14" (cf. ../00-big-picture/02-stack-matrix.md).