Given-When-Then es un patrón estructural para describir escenarios de prueba, tomado por BDD del domain-driven design y adaptado para Behaviour-Driven Development. El formato divide el escenario en tres partes lógicas: precondiciones (Given), acción (When) y resultado esperado (Then). Según Martin Fowler (2023), Given-When-Then no es solo un formato de pruebas, sino una herramienta de pensamiento que disciplina el análisis de requisitos y el diseño de escenarios antes de comenzar la implementación.
Lo principal
Given-When-Then es un patrón de descripción de comportamiento, formulado por primera vez por Dan North en 2006 como parte de la metodología Behavior-Driven Development. El patrón resuelve el problema de las descripciones no estructuradas de escenarios de prueba, que a menudo contienen una mezcla de precondiciones, acciones y verificaciones en orden arbitrario.
La idea principal del patrón es la separación de responsabilidades entre tres bloques. Cada bloque responde exactamente por un aspecto del escenario: estado antes, evento durante y verificación después. Esto hace que el escenario sea legible, verificable y automatizable. Según un estudio de los desarrolladores del framework Cucumber (2024), los escenarios que siguen estrictamente el patrón Given-When-Then requieren un 42% menos de tiempo para ser comprendidos por un nuevo miembro del equipo.
Dan North tomó prestada la idea de la estructura de tres partes de la formulación de pruebas en TDD y de la metodología Test-by-Example (creada por Brian Marick). Marick propuso describir los requisitos mediante ejemplos (examples) que al mismo tiempo sirven como pruebas. Given-When-Then formalizó esta idea, convirtiendo ejemplos no estructurados en un patrón repetible.
El patrón Given-When-Then no solo se aplica en escenarios BDD con Gherkin, sino también en pruebas unitarias comunes con JUnit, XCTest y otros frameworks. Los comentarios en el código que dividen la prueba en tres bloques son una práctica común para mejorar la legibilidad de la base de pruebas. Google recomienda este enfoque en su libro «Software Engineering at Google» (2020).
Cada bloque de Given-When-Then tiene una semántica estrictamente definida y reglas de contenido. La violación de estas reglas produce escenarios difíciles de automatizar o entender.
El bloque Given describe el estado del sistema antes de ejecutar la acción bajo prueba. Incluye: objetos existentes (usuario, pedido, configuraciones), estados activos (autenticado, conectado a la red) y valores iniciales de datos. Cada Given debe ser verificable — si el estado del sistema no coincide con Given, el escenario debe omitirse o prepararse previamente el entorno de prueba.
El bloque When describe el único evento que inicia el comportamiento bajo prueba. Puede ser una llamada a un método, un clic en un botón, la recepción de una notificación o una respuesta del servidor. La regla clave es un When por escenario. Si es necesario verificar una secuencia de acciones, se crean escenarios separados, no una cadena de When.
// Given: creamos datos de prueba
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When: ejecutamos la acción
val result = PurchaseUseCase().buy(user, product)
// Then: verificamos el resultado
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
El bloque Then verifica que el sistema haya pasado al estado esperado. Esto incluye: valores devueltos, cambios en el estado de objetos, llamadas a servicios externos (mediante verificación de mocks) y cambios en la UI. Cada bloque Then puede contener varias verificaciones, pero todas se refieren a una sola acción.
Given-When-Then y Arrange-Act-Assert (AAA) son dos variantes del mismo patrón de tres partes, pero con diferentes audiencias objetivo. Comprender sus diferencias ayuda a elegir el formato correcto para cada tarea.
| Aspecto | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Origen | BDD, análisis de negocio | Pruebas unitarias |
| Lenguaje | Natural (Gherkin) | Código (Kotlin, Swift, Java) |
| Audiencia | Todo el equipo + cliente | Desarrolladores |
| Nivel de detalle | Alto nivel | Detallado |
| Automatización | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
El patrón Given-When-Then es óptimo para escenarios que se discuten con el cliente o analista: criterios de aceptación de funcionalidades, casos de uso, verificaciones de regresión. La sintaxis de Gherkin permite escribir estos escenarios sin conocimientos de programación.
Arrange-Act-Assert es la elección natural para pruebas unitarias que verifican un método o clase específica. El formato AAA no requiere frameworks adicionales y funciona en cualquier lenguaje de programación. Para el desarrollo en iOS, Apple recomienda AAA en la documentación de XCTest (2024).
Veamos ejemplos prácticos de Given-When-Then en Kotlin para una aplicación Android. El primer ejemplo es una prueba del carrito de compras con MockK. El segundo es una prueba de la lógica de notificaciones 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)
}
}
El segundo ejemplo demuestra Given-When-Then con código asíncrono. Aquí Given establece el estado de Firebase Cloud Messaging, When — la recepción de una notificación push, Then — la verificación del procesamiento.
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)
}
}
El tercer ejemplo es un escenario BDD en Gherkin que muestra Given-When-Then en el contexto de pruebas de aceptación:
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
La aplicación efectiva de Given-When-Then requiere seguir varias prácticas probadas. Estas garantizan legibilidad, mantenibilidad y automatización de los escenarios.
Regla estricta: un escenario — una acción. Si es necesario verificar una secuencia de varios When, cree varios escenarios donde el resultado del anterior se convierta en precondición del siguiente. Esto hace que el escenario sea atómico y comprensible.
Given debe describir la esencia, no números concretos. En lugar de «Given el usuario Ivanov con saldo de 500 rublos» — «Given un usuario con saldo suficiente». Los datos concretos se trasladan a Scenario Outline con una tabla de Examples. Esto hace que el escenario sea universal y reutilizable.
La integración de escenarios Given-When-Then en el pipeline de integración continua los convierte de documentación en una protección contra regresiones. Cada merge request en un proyecto móvil ejecuta automáticamente los escenarios BDD y bloquea la fusión si al menos un escenario falla.
Los escenarios BDD con Cucumber para Android se ejecutan mediante la tarea de Gradle ./gradlew cucumber. Para iOS (Quick/Nimble) — mediante xcodebuild test. En sistemas CI (GitHub Actions, GitLab CI, Bitrise), las pruebas BDD se ejecutan en emuladores o dispositivos reales. El informe se genera en formato HTML comprensible para los gerentes: escenarios verdes — aprobados, rojos — fallo con indicación del paso.
Los archivos .feature se almacenan en el repositorio junto al código y pasan por code review. El analista crea un merge request con nuevos escenarios antes de comenzar el desarrollo (BDD-first). El desarrollador escribe las definiciones de pasos (step definitions) y la implementación para que estos escenarios se vuelvan verdes. Cuando todos los escenarios pasan — la funcionalidad está lista. Este enfoque, descrito en el libro de Gojko Adzic «Specification by Example» (2011), convierte los requisitos en un artefacto ejecutable.
Preguntas frecuentes
Estructuralmente sí, es el mismo patrón de tres partes. La diferencia está en la audiencia: Given-When-Then está orientado al lenguaje de negocio y se usa en BDD con Gherkin, mientras que Arrange-Act-Assert es un formato técnico para pruebas unitarias. La elección depende del contexto y del equipo.
No hay límite, pero se recomienda no más de 3–5 verificaciones por cada Then. Si hay más verificaciones, probablemente el escenario está comprobando demasiadas cosas en una sola acción. Divídalo en varios escenarios con diferentes Then.
No. El patrón se puede usar en cualquier framework de pruebas, simplemente dividiendo la prueba con comentarios o líneas en blanco en tres bloques. Gherkin solo es necesario si los escenarios se escriben en formato .feature para Cucumber o SpecFlow.
Se recomienda extraer las precondiciones repetitivas en Background (Gherkin) o métodos @Before (JUnit). Si las precondiciones son complejas, use el patrón Builder para crear datos de prueba. Esto mantiene Given breve y legible.
No. When es un bloque obligatorio que describe la acción. Si el escenario solo verifica un estado sin acción (por ejemplo, «al cargar la aplicación los datos deben estar en caché»), When describe el desencadenante: «cuando la aplicación se inicia».
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también