Kotlin test

En la comunidad de typescript una de las razones por las que comentan que se debe usar es por que usa types y que eso reduce la introducción de errores en el codigo, y para ciertos errores muy muy simples puede que sea verdad. Pero si he notado que la mayoría de los errores vienen cuando modificamos algo y ese algo se usa en otro lado que no sabemos; e introducimos bugs al código, esto ni con lenguajes typados lo solventas. Pero si hay una herramienta que puede al menos decirte que estas provocando side effects en partes del código que ni esperabas. Y esas son las pruebas unitarias.

Todos deberíamos saber los beneficios que estas conllevan y aunque muchos los sabemos la verdad como desarrolladores no nos gusta escribirlas (al menos a mi no) las vemos como tiempo extra, ademas casi siempre los project managers tambien y piden las pruebas unitarias aunque no den tiempo para poder escribirlas.

Pero esa es otra historia y no importa si sigues una metodología BDD o TDD o simplemente escribes pruebas cuando se te antoja, es importante crearlas.

A continuation veremos un ejemplo de como crear pruebas unitarias para Kotlin:

El codigo a probar

El codigo al que le haremos pruebas unitarias sera el saludador que escribimos la vez pasada

package main

val saludador = { content: String ->
    { content2: String ->
        content + content2
    }
}

fun main() {
    val diBuenosDias = main.saludador("Buenos dias, ")

    println(diBuenosDias("Juan"))
}

Ahora bien, queremos verificar que la función saludador saluda para varias personas, funcionara así ?

La prueba unitaria

Para escribir la prueba vamos a necesitar 2 cosas, datos de prueba y nuestras esperanzas de que esos datos sean procesados adecuadamente.

En kotlin hay varias formas de escribir pruebas unitarias, entre ellas junit y la que veremos a continuación kotlintest

El coding es el siguiente:

package main

import io.kotlintest.data.suspend.forall
import io.kotlintest.shouldBe
import io.kotlintest.specs.StringSpec
import io.kotlintest.tables.row

class MainTest: StringSpec({
    "string concat" {
        val hello = "Hola, "
        val saluda = main.saludador(hello)
        forall(
            row("Juan", "Hola, Juan"),
            row("Pedro", "Hola, Pedro")
        ) { a, b ->
            println(saluda(a))
            saluda(a) shouldBe  b
        }
    }
})

Necesitamos agregar estas dependencias al archivo build.gradle

testImplementation 'io.kotlintest:kotlintest-runner-junit5:3.3.2'

Y agregar esta sección en el mismo archivo

test {
    useJUnitPlatform()

    testLogging {
        events "PASSED", "FAILED", "SKIPPED", "STANDARD_OUT", "STANDARD_ERROR"
    }
}

La prueba es bastante sencilla creamos una función con “Hola, “ y después creamos una tabla de datos, la primera columna sera la entrada y la segunda la salida esperada. Estoy imprimiendo la salida del saludo pero no es necesario, si falla lo sabremos.

Ejecutando la prueba

Desde IntelliJ solo damos click secudario en el archivo y damos run dará la siguiente salida:

Testing started at 12:30 ...
12:30:42: Executing tasks ':cleanTest :test --tests "main.MainTest"'...

> Task :cleanTest
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileTestKotlin UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test
Hola, Juan
Hola, Pedro
main.MainTest > string concat PASSED
BUILD SUCCESSFUL in 7s
4 actionable tasks: 2 executed, 2 up-to-date
12:30:50: Tasks execution finished ':cleanTest :test --tests "main.MainTest"'.

Todo funciona bien y vemos que saluda a varias personas

Desde la consola solo debemos ejecutar gradle test --tests "main.MainTest” y la salida sera

> Task :test

main.MainTest > string concat STANDARD_OUT
    Hola, Juan
    Hola, Pedro

main.MainTest > string concat PASSED

BUILD SUCCESSFUL in 2s
3 actionable tasks: 2 executed, 1 up-to-date

Es curioso que si vuelves a ejecutar gradle esta es la salida:

BUILD SUCCESSFUL in 0s
3 actionable tasks: 3 up-to-date

Ya que nada cambio y por tanto no hay nada que reportar.

En conclusion hay que incrementar el uso de pruebas unitarias, por bien de todos (nosotros mismos, nuestros clientes y porque no, el planeta).