Cómo Kotlin puede ayudar en las pruebas de API: el caso de Rusfinance Bank





El título de Kotlin afirmaba estar más asociado con el desarrollo de Android, pero ¿por qué no experimentar? Con su ayuda, encontramos una manera de simplificar ligeramente la automatización de las pruebas de la API de uno de nuestros servicios, así como para facilitar el trabajo de los probadores que no están familiarizados con la programación y los matices del lenguaje Java.



¿Que estamos haciendo? Estamos desarrollando un servicio para enviar cuestionarios de corretaje para calcular y recibir una decisión sobre ellos. Y a pesar de que se trata de una solución bancaria, el desarrollo lo lleva a cabo un pequeño equipo de scrum, en el que participan 1-2 especialistas en las pruebas, dependiendo de la carga y la situación del proyecto.



Debajo del corte, le informaremos sobre los resultados de nuestros experimentos, que con mucho gusto transferimos a producción.



No cara



Nuestro servicio fue desarrollado para integrarse con la interfaz de los socios y no tiene su propia interfaz de usuario. Por lo tanto, en este caso, probar la API directamente es la única opción disponible. Aunque las pruebas API tienen varias ventajas incluso con una interfaz:



  • le permite comenzar a probar ya en la etapa de desarrollo de servicios;
  • simplificar la localización de errores;
  • generalmente reduce el tiempo de prueba.


Nuestro servicio incluye un conjunto de API para transferir los datos del cuestionario del cliente para el cálculo y para obtener una solución para un préstamo de automóvil. Las siguientes comprobaciones se pueden distinguir como las principales tareas de prueba de alto nivel:



  • formato de campos y parámetros;
  • corrección de los códigos de estado y mensajes de error;
  • campos obligatorios y lógica de servicio.






Momento crucial



El equipo preparó el MVP del servicio en muy poco tiempo, y las pruebas automatizadas fueron originalmente escritas por el desarrollador del producto. Fue más rápido y más conveniente incluir pruebas automáticas en el proyecto, por lo que inicialmente estaban estrechamente relacionadas con su código y se basaban en la pila de Java, REST-asegurado y el marco de prueba TestNG.



Con el desarrollo del proyecto, creció la participación de los evaluadores en el proceso de automatización. Por el momento, las tareas de soporte y actualización de las pruebas automáticas recaen completamente en el departamento de pruebas. En este sentido, se hizo necesario ajustar el enfoque de la automatización: simplificar las pruebas tanto como sea posible y hacerlas independientes del código principal. Y, por lo tanto, para resolver las dificultades que surgen:



  • la comunicación con el código hace que las pruebas sean más vulnerables a cualquier cambio de diseño, requiere mucho trabajo para mantener el rendimiento;
  • las relaciones complejas aumentan el tiempo para encontrar información e investigar errores;
  • Es difícil involucrar a los nuevos empleados del departamento de pruebas en el trabajo con código Java, requiere capacitación de los probadores y una cantidad significativa de tiempo para ingresar al proyecto.


Por lo tanto, decidimos cambiar el enfoque de las pruebas y formulamos los siguientes requisitos para nuevas herramientas:



  • compatibilidad total con Java, que le permite reescribir cheques en etapas, mientras continúa trabajando con pruebas antiguas;
  • código simple e intuitivo;
  • lenguaje libre y estable;
  • selección de pruebas automáticas en un proyecto separado.




¿Qué tiene que ver Kotlin con eso?



El idioma Kotlin satisface nuestras necesidades tanto como sea posible.







Además de la compatibilidad total con Java en Kotlin, estábamos interesados ​​en las siguientes características:



  • la concisión del lenguaje hace que el código sea claro y fácil de leer;
  • azúcar sintáctica;
  • código intuitivo y entrada fácil de especialistas en el proyecto;
  • La capacidad de transferir pruebas automáticas de Java a Kotlin de forma gradual y sin dolor, en parte si es necesario.


Por supuesto, también hay desventajas, especialmente en comparación con Java. Primero, una comunidad relativamente pequeña: encontrar ayuda y respuestas a las preguntas de Java es mucho más fácil que con Kotlin. En segundo lugar, en general, Java es un lenguaje más universal con más capacidades y una gran cantidad de desarrollos y bibliotecas.



Pero, francamente, para fines de prueba, no necesitamos capacidades tan amplias que solo Java pueda proporcionar. Por lo tanto, preferimos la simplicidad y brevedad de Kotlin.



De las palabras a los hechos



Como resultado de una transición parcial a un nuevo idioma, recibimos un aumento notable en los costos laborales para especialistas, una simplificación significativa del código y una reducción en su volumen. Esto se ve claramente en ejemplos específicos de las pruebas de nuestro servicio para procesar perfiles de corretaje.



En Kotlin, puede inicializar un objeto de solicitud con una línea de código. Por ejemplo, la clase ApplicationDTO (para enviar un cuestionario a la solución) y ErrorDTO (errores provenientes del servicio) se ven así:







Kotlin le permite establecer valores de campo durante la inicialización. Esto ahorra mucho tiempo al escribir pruebas: al crear un objeto, los campos ya están llenos de datos válidos, solo cambiamos los valores que se refieren a la verificación actual.



La anotación JsonIgnoreProperties le permite no especificar todos los campos de una clase si no son necesarios para las pruebas y no es necesario verificarlos. Si se recibe un campo que no se especifica en la descripción, la prueba no fallará con un error.



El signo de interrogación en el tipo de una variable indica que en algún momento puede ser nulo. Pero cuando se usa una variable, esto deberá tenerse en cuenta y procesarse. Finalmente, a diferencia de las pruebas de Java, NullPointerException se puede evitar con gracia aquí.



Permítanos ilustrarlo con un ejemplo simple de comprobación de errores para un inicio de sesión incorrecto:



class ApplicationTests {

    val DEFAULT_LOGIN = "consLogin"
    val ERROR_CODE = "3"
    val BASE_URI = "https://base_url.com"

    @Test
    fun incorrectLogin() {
        val incorrectLogin = DEFAULT_LOGIN + "INCORRECT";
        val res = given()
                .spec(spec)
                .body(ApplicationDTO)
                .`when`()
                .post(endpointApplication(incorrectLogin)
                        .then()
                        .statusCode(400)
                        .extract().`as`(ErrorDTO::class.java)
                        assertThat(res.error_message).containsIgnoringCase("    ")
                        assertThat(res.error_code).isEqualToIgnoringCase(ERROR_CODE)
    }

    companion object{
        private var spec: RequestSpecification? = null

        @JvmStatic
        @BeforeClass
        fun initSpec() {
            spec = RequestSpecBuilder()
                    .setContentType(ContentType.JSON)
                    .setBaseUri(BASE_URI)
                    .addFilter(ResponseLoggingFilter())
                    .addFilter(RequestLoggingFilter())
                    .build()
        }
    }
}


Creamos una especificación para consultas en BeforeClass, que reutilizamos en todas las pruebas de esta clase. Jackson serializa y deserializa los objetos json, lo que simplifica las cosas: no es necesario trabajar con ellos como con las cadenas, debido a esto, la cantidad de errores se reduce significativamente.







Con Kotlin, reducimos significativamente la cantidad de código, lo que significa que hacemos la vida más fácil tanto para "escritores" como para "lectores". La clase ApplicationDTO ya contiene un constructor y algunos otros métodos (hashCode (), copy (), etc.); no necesitamos "sobrecargar" el código con ellos y los desarrolladores novatos de autotest no se distraen con ellos. No necesitan actualizarse en caso de cambios, lo que reduce el tiempo para realizar modificaciones en las pruebas.



También es muy conveniente que Kotlin admita argumentos con nombre: el código es bastante fácil de leer y no es necesario escribir definidores para las clases de objetos json.



Prueba cosas nuevas gratis



Me gustaría señalar la apertura y libertad de Kotlin y todas las bibliotecas que utilizamos, lo que simplifica enormemente el trabajo y amplía las posibilidades de experimentar e introducir nuevos enfoques. De acuerdo, siempre es más fácil probar cosas nuevas de forma gratuita y, en caso de falla, volver a las prácticas antiguas.



En el futuro, planeamos desarrollar un nuevo enfoque y escalarlo a otros proyectos, traducir el resto de la API y las pruebas de interfaz de usuario a Kotlin.



PD: A pesar de que Kotlin se asocia principalmente con el desarrollo de Android, el alcance de su uso, como comprenderá, no se limita a esto. Al reducir el tiempo dedicado a escribir código, su simplicidad y concisión ayudarán a reducir los costos laborales para resolver muchos problemas. Si tenemos nuevos casos con Kotlin, definitivamente le informaremos sobre ellos.Aquí .



All Articles