Ir al contenido principal
Versión: 6.2 🚧

Introducción

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Cambios en el módulo

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.

nota

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í

precaución

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.

salida de ejemplo de prueba basada en datos

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.

salida de ejemplo de prueba fallida

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>

consejo

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
}
}
})

Ejemplo de salida para pruebas parametrizadas

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
}
}
}
})

ejemplo de salida de prueba de datos

precaución

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 StyleAvailable withXXX FunctionsLegacy withData Maps To
FunSpecwithContexts (creates container contexts)
withTests (creates leaf tests)
withContexts
StringSpecwithData (creates leaf tests)withData (native)
DescribeSpecwithContexts (creates container contexts)
withDescribes (creates container describes)
withIts (creates leaf tests)
withContexts
ShouldSpecwithContexts (creates container contexts)
withShoulds (creates leaf tests)
withContexts
WordSpecwithWhens (creates when containers)
withShoulds (creates should containers)
withWhens
BehaviorSpecwithContexts (creates container contexts)
withGivens (creates given containers)
withWhens (creates when containers)
withThens (creates then leaf tests)
withAnds (creates and containers in given scope)
withContexts
FreeSpecwithContexts (creates container contexts)
withTests (creates leaf tests)
withContexts
ExpectSpecwithContexts (creates container contexts)
withExpects (creates leaf expect tests)
withContexts
FeatureSpecwithFeatures (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