Parameterized Tests con JUnit en Kotlin
parameterized tests junit kotlin

Parameterized Tests con JUnit en Kotlin

Los parameterized tests o tests parametrizados son una funcionalidad que podemos usar con JUnit en Kotlin (o Java) para cubrir un montón de casos de tests de una pasada.

En lugar de escribirlos uno por uno para un SUT (Subject Under Test) determinado, escribimos uno solo, y le pasamos parámetros.

Es muy útil para testear mappers, validadores, diferentes casuísticas con Feature Flags, use cases, etc. Pero hay que andar con ojo, porque pueden volver el código de test más complicado de lo que nos gustaría.

Los miembros de "Los androides Premium" escuchan contenido adicional en audio sobre este artículo... ¡y otros más de 100!

Suena muy bien

Hay que suscribirse para disfrutar de todo el contenido premium desde la web y la app, así como participar en las actividades premium: videoconferencias y canales premium en Discord.

Se pueden emplear tanto con JUnit 4 como con JUnit 5. Por lo que sobra que digamos que se pueden emplear en nuestros tests unitarios.

Para que esto sea lo más práctico posible, he hecho un repo de ejemplo que puedes clonarte fácilmente. Y este sería el código principal que quiero mostrarte.

import org.amshove.kluent.shouldBe
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized

@RunWith(Parameterized::class)
class IsValidEmailUseCaseTest(
    private val email: String,
    private val expected: Boolean,
) {

    private lateinit var useCase: IsValidEmailUseCase

    @Before
    fun setUp() {
        useCase = IsValidEmailUseCase()
    }

    @Test
    fun `GIVEN an email WHEN invoke THEN get the expected result`() {
        val result = useCase(email)

        result shouldBe expected
    }

    companion object {
        @JvmStatic
        @Parameterized.Parameters
        fun data() = listOf(
            arrayOf("foo", false),
            arrayOf("foo@", false),
            arrayOf("foo@foo", false),
            arrayOf("foo@foo.", false),
            arrayOf("foo@foo.com", true),
        )
    }
}

Como puedes observar, es un validador de emails.

En los parámetros indico 4 casos en los que el email no es válido, y el 5º, sí lo es.

Sencillo, ¿verdad?

Y potente. 🎯

Una de las ventajas que mola mogollón es que no hace falta que limpies los mocks, como por ejemplo cuando hacer un forEach dentro de un test. ya que se corren tantos tests como arrays de parámetros haya dentro del listado.

Y a ver, doble disclaimer:

Por un lado, lo de limpiar mocks, sería por ejemplo con MockK usando clearMocks. Y nos serviría para asegurar que el estado se resetea al correr un nuevo test.

Y por el otro, si lo de shouldBe no sabes de donde viene, puedes sustituir result shouldBe expected por esto:

assertTrue(result == expected)

Haciendo el import correspondiente, claro: import org.junit.Assert.assertTrue.

Ahora bien, Kluent es una biblioteca de aserciones que hacen los tests mucho más legibles. Y te la recomiendo un montón. Hay otras también. Pero vamos, que esta es de esas que personalmente uso a diario y que me parece una pasada.

Si quieres ir un paso más allá, podrías hacer que los nombres de los tests fueran más legibles así:

@Parameterized.Parameters(name = "email: {0} expected: {1}")

Con lo que el reporte quedaría así:

test report

Por cierto, ¿tú usas los parameterized tests en tus proyectos? Coméntalo dentro de la comunidad, que nos encantará saberlo. 🚀

Publicado: 2023-07-24 Actualizado: 2023-08-24