Introducción
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Antes de Kotest 6.0, las pruebas basadas en datos eran un módulo separado. A partir de Kotest 6.0, esta funcionalidad está
incluida en el framework principal, por lo que no existe un módulo kotest-framework-datatest que añadir. Por favor, elimínalo de tu configuración de compilación.
Esta sección cubre el nuevo y mejorado soporte para pruebas basadas en datos lanzado con Kotest 4.6.0. Para ver la documentación del soporte anterior de pruebas basadas en datos, haz clic aquí
Si estás utilizando pruebas basadas en datos en plataformas Kotlin/Native, consulta la sección sobre Soporte para Native.
Al escribir pruebas basadas en lógica, tiene sentido utilizar rutas de código específicas que cubran escenarios particulares. Otras veces tenemos pruebas más orientadas a ejemplos, donde sería útil probar múltiples combinaciones de parámetros.
En estos casos, las pruebas basadas en datos (también llamadas pruebas basadas en tablas) son una técnica sencilla para evitar código repetitivo tedioso.
Kotest incluye soporte nativo para pruebas basadas en datos integrado en el framework. Esto significa que Kotest generará automáticamente casos de prueba basados en los valores de entrada que proporciones.
Primeros pasos
Al crear pruebas basadas en datos, necesitamos proporcionar cada conjunto de entradas (llamado fila) envuelto en una clase que se pasa a una
función de prueba de datos. Dependiendo del estilo de spec en uso, estas funciones de prueba de datos se denominan withXXX, que reflejan
el DSL proporcionado por cada estilo de spec. Por ejemplo, si estamos usando el estilo fun spec, que
utiliza la palabra clave test para definir pruebas, entonces usaríamos la función withTests para pruebas basadas en datos.
Consideremos escribir pruebas para una función de conversión de Celsius a Fahrenheit. La entrada será el valor en Celsius y la salida esperada será el valor en Fahrenheit.
fun cToF(celsius: Int): Int = (celsius * 9 / 5) + 32
Como en este ejemplo necesitamos dos argumentos por fila, podemos envolver las entradas en un objeto Pair de Kotlin. Si tuviéramos
más de dos argumentos, podríamos usar una clase de datos personalizada.
Creamos una prueba basada en datos usando la función withTests, pasando las filas y también una lambda que ejecuta la lógica
de prueba para cada fila dada.
Por ejemplo:
class MyTests : FunSpec({
withTests(
Pair(0, 32),
Pair(100, 212),
Pair(-40, -40),
Pair(-30, -22),
)
{ (celsius, fahrenheit) ->
cToF(celsius) shouldBe fahrenheit
}
})
Observa que la fila de entrada se puede desestructurar directamente en las propiedades del miembro.
Kotest generará automáticamente un caso de prueba por cada fila de entrada, como si hubieras escrito cada prueba manualmente. Así, en este ejemplo al ejecutar la prueba basada en datos, obtendremos cuatro resultados de prueba independientes.
Los nombres de las pruebas se generan a partir de las clases de datos, pero se pueden personalizar si se desea.
Si hay un error en cualquier fila de entrada específica, la prueba fallará y Kotest mostrará los valores que
fallaron. Por ejemplo, si modificamos el ejemplo anterior para incluir la fila Pair(15, 20)
entonces esa prueba se marcará como fallida ya que 15°C no equivale a 20°F.

El mensaje de error contendrá el fallo y los detalles de la fila de entrada:
Test failed for (a, 5), (b, 4), (c, 3) expected:<9> but was:<41>
Las versiones de Kotest anteriores a la 6.1 proporcionaban una única función withData. Esta función aún existe y apunta a una
variante apropiada para ese estilo de spec. Sin embargo, se prefieren las nuevas variantes withXXX porque te permiten controlar
si estás definiendo una prueba contenedora o una prueba hoja.
Anidamiento
En el ejemplo anterior, colocamos las pruebas basadas en datos en el nivel raíz. También podemos anidar pruebas basadas en datos dentro de contenedores.
Por ejemplo, podemos envolver el ejemplo anterior en el bloque context que proporciona FunSpec para tener más
información cuando aparezcan los resultados de las pruebas.
Por ejemplo:
class MyTests : FunSpec({
context("celsius to fahrenheit") {
withTests(
Pair(0, 32),
Pair(100, 212),
Pair(-40, -4),
Pair(-30, -30),
)
{ (celsius, fahrenheit) ->
cToF(celsius) shouldBe fahrenheit
}
}
})

De hecho, las pruebas basadas en datos se pueden anidar dentro de cualquier número de contenedores, incluyendo otras pruebas basadas en datos. Esto nos permite construir combinaciones complejas de entradas.
Por ejemplo, imagina que queremos probar una llamada HTTP con múltiples métodos. Podríamos tener los servicios en un nivel, y los métodos en el siguiente nivel.
class MyTests : FunSpec({
context("each service should support all http methods") {
val services = listOf(
"http://internal.foo",
"http://internal.bar",
"http://public.baz"
)
val methods = listOf("GET", "POST", "PUT")
// First level of data nesting
withData(services) { service ->
// Second level of data nesting (Cartesian product)
withData(methods) { method ->
// Test logic: check if 'service' supports 'method'
// e.g., apiClient.call(service, method).status shouldBe 200
}
}
}
})

Las pruebas basadas en datos solo se pueden definir en el nivel raíz o en ámbitos de contenedores. No se pueden definir dentro de ámbitos hoja.
Soporte para Native
Si estás utilizando pruebas basadas en datos en plataformas Kotlin/Native o Kotlin/JS, debes asegurarte de que el ámbito más interno sea
un ámbito de nivel hoja. Esto se debe a que las plataformas native y js no admiten pruebas contenedoras sin una prueba hoja
en su interior. Esto simplemente significa que, por ejemplo, si estás usando fun spec, debes usar withTests como tu nivel final de anidamiento.
Hooks del ciclo de vida
Si deseas que los hooks before/after se apliquen por cada fila en una prueba basada en datos, puedes usar los hooks estándar
de Kotest como beforeTest y afterTest. Cada prueba generada mediante pruebas basadas en datos
se comporta igual que una prueba regular equivalente, por lo que todas las callbacks funcionan como si hubieras escrito las pruebas manualmente.
Consulta la documentación de hooks del ciclo de vida
Por ejemplo:
beforeTest {
// reset test setup
}
context("...") {
withTests(X, Y, Z) { x,y,z ->
// test code
}
}
Variantes WithXXX
Cada estilo de Spec tiene su propio conjunto de withXXX que definen un contenedor o un contexto hoja.
Las combinaciones por estilo de Spec se enumeran a continuación:
| Test Style | Available withXXX Functions | Legacy withData Maps To |
|---|---|---|
| FunSpec | withContexts (creates container contexts)withTests (creates leaf tests) | withContexts |
| StringSpec | withData (creates leaf tests) | withData (native) |
| DescribeSpec | withContexts (creates container contexts)withDescribes (creates container describes)withIts (creates leaf tests) | withContexts |
| ShouldSpec | withContexts (creates container contexts)withShoulds (creates leaf tests) | withContexts |
| WordSpec | withWhens (creates when containers)withShoulds (creates should containers) | withWhens |
| BehaviorSpec | withContexts (creates container contexts)withGivens (creates given containers)withWhens (creates when containers)withThens (creates then leaf tests)withAnds (creates and containers in given scope) | withContexts |
| FreeSpec | withContexts (creates container contexts)withTests (creates leaf tests) | withContexts |
| ExpectSpec | withContexts (creates container contexts)withExpects (creates leaf expect tests) | withContexts |
| FeatureSpec | withFeatures (creates feature containers)withScenarios (creates leaf scenario tests) | withFeatures |
Puedes encontrar ejemplos completos de cómo utilizar cada uno de estos en estas pruebas de Kotest