Given-When-Then est un modèle structurel pour décrire des scénarios de test, emprunté par le BDD au domain-driven design et adapté pour le Behaviour-Driven Development. Le format divise le scénario en trois parties logiques : préconditions (Given), action (When) et résultat attendu (Then). Selon Martin Fowler (2023), Given-When-Then n'est pas qu'un simple format de test, mais un outil de réflexion qui discipline l'analyse des exigences et la conception de scénarios avant le début de l'implémentation.
Points clés
Given-When-Then est un modèle de description de comportement, formulé pour la première fois par Dan North en 2006 dans le cadre de la méthodologie Behavior-Driven Development. Ce modèle résout le problème des descriptions non structurées de scénarios de test, qui contiennent souvent un mélange de préconditions, d'actions et de vérifications dans un ordre arbitraire.
L'idée principale du modèle est la séparation des responsabilités entre trois blocs. Chaque bloc est responsable d'un seul aspect du scénario : l'état avant, l'événement pendant et la vérification après. Cela rend le scénario lisible, vérifiable et automatisable. Selon une étude des développeurs du framework Cucumber (2024), les scénarios qui suivent strictement le modèle Given-When-Then nécessitent 42% moins de temps pour être compris par un nouveau membre de l'équipe.
Dan North a emprunté l'idée de la structure en trois parties à la formulation de tests en TDD et à la méthodologie Test-by-Example (créée par Brian Marick). Marick a proposé de décrire les exigences par des exemples (examples) qui servent simultanément de tests. Given-When-Then a formalisé cette idée, transformant des exemples non structurés en un modèle répétable.
Le modèle Given-When-Then ne s'applique pas seulement aux scénarios BDD en Gherkin, mais aussi aux tests unitaires classiques avec JUnit, XCTest et d'autres frameworks. Les commentaires dans le code qui divisent le test en trois blocs sont une pratique courante pour améliorer la lisibilité de la base de tests. Google recommande cette approche dans son livre « Software Engineering at Google » (2020).
Chaque bloc de Given-When-Then a une sémantique strictement définie et des règles de contenu. La violation de ces règles produit des scénarios difficiles à automatiser ou à comprendre.
Le bloc Given décrit l'état du système avant d'exécuter l'action testée. Il inclut : les objets existants (utilisateur, commande, paramètres), les états actifs (authentifié, connecté au réseau) et les valeurs initiales des données. Chaque Given doit être vérifiable — si l'état du système ne correspond pas au Given, le scénario doit être ignoré ou l'environnement de test préparé à l'avance.
Le bloc When décrit l'événement unique qui déclenche le comportement testé. Il peut s'agir d'un appel de méthode, d'un clic sur un bouton, de la réception d'une notification ou d'une réponse du serveur. La règle clé est un When par scénario. Si une séquence d'actions doit être vérifiée, créez des scénarios séparés, pas une chaîne de When.
// Given : création des données de test
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When : exécution de l'action
val result = PurchaseUseCase().buy(user, product)
// Then : vérification du résultat
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
Le bloc Then vérifie que le système est passé à l'état attendu. Cela inclut : les valeurs retournées, les changements d'état des objets, les appels aux services externes (via la vérification de mocks) et les modifications de l'interface utilisateur. Chaque bloc Then peut contenir plusieurs vérifications, mais toutes se rapportent à une seule action.
Given-When-Then et Arrange-Act-Assert (AAA) sont deux variantes du même modèle en trois parties, mais avec des publics cibles différents. Comprendre leurs différences aide à choisir le format approprié pour chaque tâche.
| Aspect | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Origine | BDD, analyse métier | Tests unitaires |
| Langage | Naturel (Gherkin) | Code (Kotlin, Swift, Java) |
| Public | Toute l'équipe + client | Développeurs |
| Niveau de détail | Haut niveau | Détaillé |
| Automatisation | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
Le modèle Given-When-Then est optimal pour les scénarios discutés avec le client ou l'analyste : critères d'acceptation des fonctionnalités, cas d'utilisation, vérifications de régression. La syntaxe Gherkin permet d'écrire ces scénarios sans connaissance en programmation.
Arrange-Act-Assert est le choix naturel pour les tests unitaires qui vérifient une méthode ou une classe spécifique. Le format AAA ne nécessite pas de frameworks supplémentaires et fonctionne dans n'importe quel langage de programmation. Pour le développement iOS, Apple recommande AAA dans la documentation XCTest (2024).
Examinons des exemples pratiques de Given-When-Then en Kotlin pour une application Android. Le premier exemple est un test de panier d'achat avec MockK. Le second est un test de la logique de notifications push.
class CartTest {
fun `apply discount when total exceeds threshold`() {
// Given
val cart = Cart()
cart.addItem(Item("Laptop", price = 1000.0))
cart.addItem(Item("Mouse", price = 50.0))
val discount = DiscountCalculator(0.1)
// When
val total = discount.applyIfEligible(cart)
// Then
assertEquals(945.0, total)
assertTrue("Discount was not applied", total < 1050.0)
}
}
Le deuxième exemple démontre Given-When-Then avec du code asynchrone. Ici, Given définit l'état de Firebase Cloud Messaging, When — la réception d'une notification push, Then — la vérification du traitement.
class PushNotificationTest {
fun `handle push notification when app in background`() = runTest {
// Given
val prefs = mockk<SharedPreferences>()
every { prefs.getString("token", null) } returns "fcm-token-abc"
val handler = PushHandler(prefs)
// When
val data = RemoteMessage().apply {
putData("type", "order_update")
putData("order_id", "123")
}
val result = handler.handleNotification(data)
// Then
assertEquals(NotificationAction.OpenOrder("123"), result)
}
}
Le troisième exemple est un scénario BDD en Gherkin montrant Given-When-Then dans le contexte de tests d'acceptation :
Feature: User Authorization
Scenario: User cannot login with expired token
Given the user has an expired refresh token
When they try to access the protected profile screen
Then they should see the login screen
And the app should clear all cached data
L'application efficace de Given-When-Then nécessite de suivre plusieurs pratiques éprouvées. Elles garantissent la lisibilité, la maintenabilité et l'automatisation des scénarios.
Règle stricte : un scénario — une action. Si une séquence de plusieurs When doit être vérifiée, créez plusieurs scénarios où le résultat du précédent devient la précondition du suivant. Cela rend le scénario atomique et compréhensible.
Given doit décrire l'essence, pas des chiffres concrets. Au lieu de « Given l'utilisateur Ivanov avec un solde de 500 roubles » — « Given un utilisateur avec un solde suffisant ». Les données concrètes sont déplacées dans un Scenario Outline avec une table d'Examples. Cela rend le scénario universel et réutilisable.
L'intégration de scénarios Given-When-Then dans le pipeline d'intégration continue les transforme de documentation en protection contre les régressions. Chaque merge request dans un projet mobile exécute automatiquement les scénarios BDD et bloque la fusion si au moins un scénario échoue.
Les scénarios BDD avec Cucumber pour Android sont exécutés via la tâche Gradle ./gradlew cucumber. Pour iOS (Quick/Nimble) — via xcodebuild test. Dans les systèmes CI (GitHub Actions, GitLab CI, Bitrise), les tests BDD sont exécutés sur des émulateurs ou des appareils réels. Le rapport est généré au format HTML compréhensible par les managers : scénarios verts — réussis, rouges — échec avec indication de l'étape.
Les fichiers .feature sont stockés dans le dépôt à côté du code et passent par une revue de code. L'analyste crée une merge request avec de nouveaux scénarios avant le début du développement (BDD-first). Le développeur écrit les définitions d'étapes (step definitions) et l'implémentation pour que ces scénarios deviennent verts. Quand tous les scénarios passent — la fonctionnalité est prête. Cette approche, décrite dans le livre de Gojko Adzic « Specification by Example » (2011), transforme les exigences en un artefact exécutable.
Questions fréquentes
Structurellement oui, c'est le même modèle en trois parties. La différence réside dans le public : Given-When-Then est orienté vers le langage métier et utilisé en BDD avec Gherkin, tandis que Arrange-Act-Assert est un format technique pour les tests unitaires. Le choix dépend du contexte et de l'équipe.
Il n'y a pas de limite, mais il est recommandé de ne pas dépasser 3 à 5 vérifications par Then. S'il y a plus de vérifications, le scénario vérifie probablement trop de choses en une seule action. Divisez-le en plusieurs scénarios avec différents Then.
Non. Le modèle peut être utilisé dans n'importe quel framework de test, en divisant simplement le test avec des commentaires ou des lignes vides en trois blocs. Gherkin n'est nécessaire que si les scénarios sont écrits au format .feature pour Cucumber ou SpecFlow.
Il est recommandé d'extraire les préconditions répétitives dans Background (Gherkin) ou les méthodes @Before (JUnit). Si les préconditions sont complexes, utilisez le modèle Builder pour créer des données de test. Cela maintient Given court et lisible.
Non. When est un bloc obligatoire qui décrit l'action. Si le scénario ne vérifie qu'un état sans action (par exemple, « au chargement de l'application, les données doivent être mises en cache »), When décrit le déclencheur : « quand l'application démarre ».
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi