Ir al contenido principal
Versión: 6.0

Modos de Aislamiento

[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 →

peligro

El modo de aislamiento InstancePerRoot solo está disponible en Kotest 6.0 y versiones posteriores. InstancePerTest e InstancePerLeaf están obsoletos debido a comportamientos indefinidos en casos límite.

Todas las especificaciones permiten controlar cómo el motor de pruebas crea instancias de Specs para los casos de prueba. Este comportamiento se denomina modo de aislamiento y se controla mediante una enumeración IsolationMode. Existen cuatro valores: SingleInstance, InstancePerRoot, InstancePerLeaf e InstancePerTest. Ten en cuenta que InstancePerLeaf e InstancePerTest están obsoletos en favor de InstancePerRoot.

Si deseas que las pruebas se ejecuten en instancias nuevas de la especificación - para permitir que el estado compartido entre pruebas se reinicie - puedes cambiar el modo de aislamiento.

Esto se puede hacer mediante DSL como:

class MyTestClass : WordSpec({
isolationMode = IsolationMode.SingleInstance
// tests here
})

O si prefieres sobrescribir funciones, puedes anular fun isolationMode(): IsolationMode:

class MyTestClass : WordSpec() {
override fun isolationMode() = IsolationMode.SingleInstance

init {
// tests here
}
}
consejo

El valor predeterminado en Kotest es Single Instance, igual que en ScalaTest (la inspiración de este framework), Jest, Jasmine y otros frameworks JavaScript, pero diferente a JUnit.

Instancia Única

El modo de aislamiento predeterminado es SingleInstance, donde se crea una instancia de la clase Spec y luego cada caso de prueba se ejecuta sucesivamente hasta completar todas las pruebas.

Por ejemplo, en la siguiente especificación, se imprimiría el mismo ID cuatro veces porque se usa la misma instancia para todas las pruebas.

class SingleInstanceExample : WordSpec({
val id = UUID.randomUUID()
"a" should {
println(id)
"b" {
println(id)
}
"c" {
println(id)
}
}
"d" should {
println(id)
}
})

Instancia por Raíz

El modo InstancePerRoot crea una nueva instancia de la clase Spec para cada caso de prueba de nivel superior (raíz). Cada prueba raíz se ejecuta en su propia instancia asociada.

Este modo se recomienda cuando quieres aislar tus pruebas manteniendo una estructura limpia.

class InstancePerRootExample : WordSpec() {

override fun isolationMode(): IsolationMode = IsolationMode.InstancePerRoot

val id = UUID.randomUUID()

init {
"a" should {
println(id)
"b" {
println(id)
}
"c" {
println(id)
}
}

"d" should {
println(id)
}
}
}

En este ejemplo, las pruebas a, b y c imprimirán el mismo UUID, pero la prueba d mostrará un UUID diferente porque se ejecuta en una nueva instancia al ser un caso de prueba de nivel superior (también llamado raíz).

Instancia por Prueba

peligro

Este modo está obsoleto debido a comportamientos indefinidos en casos límite. Se recomienda usar InstancePerRoot en su lugar.

El siguiente modo es IsolationMode.InstancePerTest, donde se crea una nueva especificación para cada caso de prueba, incluyendo contextos internos. En otras palabras, los contextos externos se ejecutarán como pruebas "independientes" en su propia instancia de la especificación. Un ejemplo lo aclarará:

class InstancePerTestExample : WordSpec() {

override fun isolationMode(): IsolationMode = IsolationMode.InstancePerTest

init {
"a" should {
println("Hello")
"b" {
println("From")
}
"c" {
println("Sam")
}
}
}
}

Fíjate cómo hemos sobrescrito aquí la función isolationMode.

Al ejecutarse, se imprimirá lo siguiente:

Hello
Hello
From
Hello
Sam

Esto ocurre porque primero se ejecuta el contexto externo (prueba "a"). Luego se ejecuta de nuevo para la prueba "b", y después para la prueba "c". Cada vez en una instancia limpia de la clase Spec. Esto es muy útil cuando queremos reutilizar variables.

Otro ejemplo mostrará cómo se reinician las variables.

class InstancePerTestExample : WordSpec() {

override fun isolationMode(): IsolationMode = IsolationMode.InstancePerTest

val counter = AtomicInteger(0)

init {
"a" should {
println("a=" + counter.getAndIncrement())
"b" {
println("b=" + counter.getAndIncrement())
}
"c" {
println("c=" + counter.getAndIncrement())
}
}
}
}

Esta vez, la salida será:

a=0 a=0 b=1 a=0 c=1

Instancia por Hoja

peligro

Este modo está obsoleto debido a comportamientos indefinidos en casos límite. Se recomienda usar InstancePerRoot en su lugar.

El siguiente modo es IsolationMode.InstancePerLeaf, donde se crea una nueva especificación para cada caso de prueba hoja - excluyendo contextos internos. Es decir, los contextos internos solo se ejecutan como parte de la "ruta" hacia una prueba externa. Un ejemplo lo aclarará:

class InstancePerLeafExample : WordSpec() {

override fun isolationMode(): IsolationMode = IsolationMode.InstancePerLeaf

init {
"a" should {
println("Hello")
"b" {
println("From")
}
"c" {
println("Sam")
}
}
}
}

Al ejecutarse, se imprimirá lo siguiente:

Hello
From
Hello
Sam

Esto se debe a que primero se ejecuta el contexto externo - prueba "a" - seguido de la prueba "b" en la misma instancia. Luego se crea una nueva especificación, se ejecuta nuevamente la prueba "a", seguida de la prueba "c".

Otro ejemplo mostrará cómo se reinician las variables.

class InstancePerLeafExample : WordSpec() {

override fun isolationMode(): IsolationMode = IsolationMode.InstancePerLeaf

val counter = AtomicInteger(0)

init {
"a" should {
println("a=" + counter.getAndIncrement())
"b" {
println("b=" + counter.getAndIncrement())
}
"c" {
println("c=" + counter.getAndIncrement())
}
}
}
}

Esta vez, la salida será:

a=0 b=1 a=0 c=1

Modo de Aislamiento Global

En lugar de configurar el modo de aislamiento en cada especificación, podemos establecerlo globalmente en la configuración del proyecto o mediante una propiedad del sistema.

Configuración

Consulta la documentación sobre cómo configurar la configuración global del proyecto y luego añade el modo de aislamiento que quieras como predeterminado. Por ejemplo:

class ProjectConfig : AbstractProjectConfig() {
override val isolationMode = IsolationMode.InstancePerRoot
}
nota

Configurar un modo de aislamiento en un Spec siempre tendrá prioridad sobre la configuración global del proyecto.

Propiedad del Sistema

Para establecer el modo de aislamiento global en la línea de comandos, usa la propiedad del sistema kotest.framework.isolation.mode con uno de los valores:

  • SingleInstance

  • InstancePerRoot

  • InstancePerTest (obsoleto)

  • InstancePerLeaf (obsoleto)

nota

Los valores distinguen entre mayúsculas y minúsculas.