Logo 1 Logo 2

Ciencia al descubierto


Automatización de pruebas en el desarrollo de productos de software

*Versión pdf

Software

El software, según la Real Academia Española (RAE), es el "conjunto de programas, instrucciones y reglas informáticas para ejecutar ciertas tareas en una computadora". Es decir, se trata de todos aquellos componentes lógicos (ceros y unos) que permiten la realización de tareas o funciones específicas; el software es el encargado de enviar instrucciones que el hardware ejecuta, lo que hace posible que los artefactos de hardware funcionen, es decir, computadoras, teléfonos celulares, impresoras, bocinas inteligentes, satélites, sistemas de navegación de los aviones, sistemas de control para las centrales de generación de energía eléctrica, entre muchos otros ejemplos del mundo real.

En general, existe un acuerdo en que hay tres grandes tipos de software:

  • Software de sistema. Permiten la interacción directa con el hardware, por ejemplo: sistemas operativos, controladores de dispositivos, herramientas de diagnóstico, etcétera.
  • Software de programación. Se trata del software que permite desarrollar software, es decir, son las herramientas, lenguajes de programación y utilerías para desarrollar software de aplicación, como: compiladores, intérpretes, enlazadores, depuradores, entornos de desarrollo integrados, librerías, entre otros.
  • Software de aplicación. Son todos los paquetes, plataformas, herramientas y productos para los usuarios finales; realizan tareas específicas en cualquier ámbito de aplicación, por ejemplo: herramientas ofimáticas, control de procesos industriales, software educativo, software empresarial, bases de datos, páginas Web, videojuegos, asistentes médicos, diseño asistido, entre muchos otros.

En el ambiente del desarrollo de software, los principales actores son los llamados "desarrolladores"; quienes son expertos en software de programación, que conocen y dominan alguno o varios lenguajes de programación, pero en este mundo, saber programar no es suficiente para desarrollar productos de software de alta gama, con características específicas para el ámbito en el que debe funcionar, por ejemplo:

  • Software para la industria militar, petrolera o energética.
  • Software para vehículos terrestres, aéreos o espaciales.
  • Software de alto rendimiento para supercomputadoras.
  • Software de aplicación crítica, en tiempo real y con tolerancia a fallas.
  • Software de grado empresarial.

Este tipo de "productos de software" se diferencia de las "aplicaciones de software" en su grado de cumplimiento funcional requerido. En los productos de software de alta gama, las funciones integradas siempre deben ejecutarse correctamente y hacer bien las secuencias, cálculos o algoritmos que deben realizar. Se escucha muy sencillo y lógico, pero esta característica es justamente la más compleja de cumplir.

Para que un producto de software ejecute sus funciones correctamente se requiere integrar un estricto control de calidad durante todas las fases del desarrollo, desde el inicio hasta el final.

Una función se especifica o define antes de empezar a desarrollarla, para poder planear adecuadamente su comportamiento y la manera en que debe resolver todos los pasos o secuencias internas, sus entradas, algoritmos y salidas, así como las condiciones y características específicas (tiempo de respuesta, sincronización, precondiciones, etc.). Durante su diseño, los especialistas determinan la mejor manera de realizar la implementación dentro del producto completo, así como las interacciones internas y externas. Durante su desarrollo, los responsables realizan la codificación de las funciones, cumpliendo las especificaciones y diseño. Finalmente se prueba y se libera para su integración en el producto completo.

La narrativa anterior describe la ruta ideal en el desarrollo, pero en la vida real se requiere garantizar que todos los elementos que integran el producto de software van a operar como fueron definidos, para esto, las metodologías de desarrollo de software guían al personal y grupos multidisciplinarios para hacerlo bien con el menor esfuerzo o retrabajo posible, siendo todos responsables de la calidad de software en cada una de sus etapas; por lo tanto, las pruebas de software son imprescindibles para generar cada elemento del producto completo con la calidad adecuada.

Pruebas de software y su importancia en el desarrollo

Muchos desarrolladores tienen la anécdota de que, al momento de entregar una función o incluso un producto de software, el usuario le indica: "Esto no es lo que necesito", es una historia de terror que le quita el sueño a los desarrolladores, casi una pesadilla.

Un error que se comete de manera muy común, es pensar más en la parte técnica y menos en lo que el usuario realmente necesita. Se toman como base los requisitos y el diseño, se interpretan las restricciones y se inicia el desarrollo hasta su entrega. Pero ¿quién verifica que se estén cumpliendo los requisitos originales?, ¿cómo se revisa que los requisitos no funcionales están bien integrados? y ¿quién valida que se cumpla con las necesidades del usuario?

Realizar la verificación y validación de los requisitos es un proceso fundamental en el ciclo de vida del desarrollo del software; a este proceso se le conoce como pruebas de software .

Las pruebas deben comenzar lo más pronto posible en el proceso de desarrollo, ¿cómo es esto posible si aún no se tiene algo funcionando?

Las pruebas se pueden clasificar como estáticas y dinámicas. Las pruebas estáticas son cuando se verifica la documentación desde el análisis de requisitos, diseño de los procesos de negocio, historias de usuario, casos de uso, documentos técnicos o el cumplimiento con alguna restricción definida (tiempo, sincronización, seguridad, etc.). Las pruebas dinámicas están relacionadas con la ejecución y pruebas funcionales del producto de software.

Dentro de las pruebas dinámicas existe una sub-clasificación que se muestra en la Figura 1, en donde se aprecia de manera visual la proporción de pruebas que se recomienda realizar, siendo la de mayor proporción las pruebas unitarias y en menor proporción las pruebas funcionales.

Figura 1. Pirámide de pruebas automatizadas.

Al ejecutar pruebas estáticas se verifica en una etapa "temprana" la posible introducción de errores en el código, ya que se podrían interpretar erróneamente los requisitos, lo cual provocará un mal diseño e impactará en los componentes y, por lo tanto, tendrá un mal funcionamiento integrado. La pregunta entonces es: ¿cuánto tiempo llevará resolver una mala interpretación que se pudo identificar al inicio del proceso?

La aplicación de pruebas tempranas es uno de los principios fundamentales de las pruebas de software, permiten conocer si los desarrolladores están comprendiendo el negocio, si se está desarrollando un producto acorde a los requisitos y, sobre todo, si se están cumpliendo las necesidades del usuario; adicionalmente, en cuestiones monetarias, se logra un ahorro considerable que será reflejado en el mantenimiento del producto.

Cuando se liberan las primeras versiones de un producto de software, las pruebas manuales suelen ser muy efectivas, ya que una persona verifica que los requisitos se cumplan, que el sistema funcione, que la interfaz gráfica se vea "bonita", que no existan problemas en el acceso al sistema, etc. Sin embargo, conforme el producto va creciendo, la probabilidad de introducir errores en el código se vuelve más alta y las pruebas se vuelven más complejas, ya que hay que verificar el incremento en las funciones y, además, hay que verificar que todo lo desarrollado previamente no ha sufrido cambios, a esto se le llama pruebas de regresión.

Con las pruebas de regresión se vuelve a probar lo que ya se había dado por bueno, con la finalidad de que, al ir incrementando el desarrollo del producto, este no se vea afectado.

Las pruebas de regresión también se pueden realizar de forma manual, pero es muy tedioso estar repitiendo una, y otra, y otra, y otra vez... las mismas pruebas, al volverse un proceso "aburrido", el personal encargado tiende a no identificar ciertos aspectos y dejan pasar muchos errores.

Afortunadamente, en muchos contextos, los procesos "repetitivos" se pueden "automatizar" y las pruebas de software no son la excepción.

Automatización de las pruebas

Las pruebas automatizadas ayudan a ejecutar adecuadamente los procesos tediosos. Básicamente funcionan como lo haría una persona, realizan aquellas acciones que se hacían de forma manual, pero en un tiempo más corto y sin incertidumbre.

Por ejemplo, en las pruebas unitarias, que consisten en probar los componentes de forma aislada, se pueden utilizar metodologías de desarrollo de software basada en pruebas, conocidas como: Test Driven Development o TDD (Desarrollo Basado en Pruebas, por sus siglas en inglés) y utilizar marcos de trabajo como: JUnit, NUnit, TestNG, QUnit, lo cual dependerá del lenguaje de programación utilizado en el desarrollo.

Para el caso de la automatización de las pruebas funcionales, pueden ser desde muy sencilla, hasta muy compleja; por ejemplo, con las herramientas Selenium IDE o Katalon, se pueden realizar grabaciones de las acciones realizadas en la navegación de un producto de software y después volver a ejecutarlas, una o muchas veces. La desventaja de este tipo de automatización es que, si algún componente del producto es modificado, se tienen que realizar nuevamente las grabaciones para poder ejecutar las pruebas.

De igual forma se pueden realizar pruebas automatizadas mucho más complejas, utilizando herramientas como: Selenium Webdriver, Testcafé, Cypress, Calabash, Appium o Capybara; en donde el encargado de las pruebas implementa código fuente en diversos lenguajes de programación como: java, javascript o ruby, para "simular" las acciones en la navegación de un producto de software. En este tipo de pruebas, si un componente del producto es modificado, únicamente se tienen que actualizar las referencias del componente en el código y volver a ejecutar las pruebas.

¿Quién debe aplicar las pruebas?

Realizar pruebas automatizadas no es un trabajo fácil, el responsable debe tener cualidades personales específicas, debe ser creativo para diseñar los casos de pruebas, analítico para identificar los diversos escenarios del negocio, curioso para preguntarse ¿qué pasa sí...? ¿por qué no hacer algo de otra forma?, desconfiando para ejecutar diversos escenarios en cada nueva versión del producto y tener muy buena comunicación para informar los "defectos" encontrados; además, debe tener conocimientos técnicos en lenguajes de programación, herramientas de automatización, herramientas de integración, sistemas de control de versiones e ingeniería de software.

Experiencia en el INEEL

Algunas de las áreas técnicas del INEEL tienen entre sus funciones más relevantes el desarrollo de productos de software de alta gama o de grado empresarial, algunos son de misión crítica para el sector energético en México, por ejemplo, para la CFE, PEMEX y CENACE, entre otros.

Hasta hace algunos años, los desarrollos requerían de una gran cantidad de tiempo por parte de los desarrolladores para verificar el correcto funcionamiento de sus productos, debido a que el proceso de pruebas se llevaba a cabo de manera manual o semi-automático.

La necesidad de adoptar metodologías modernas para el desarrollo ágil, que impulsen el desarrollo iterativo, que permitan aumentar la calidad de los productos desarrollados y disminuir el tiempo que invierten los desarrolladores para probar el software, fue un gran motivador para iniciar la implementación de pruebas automatizadas de software.

Primeramente, se elaboró un proyecto piloto, en el cual se implementaron pruebas automatizadas funcionales (pruebas desde la IHM), este proyecto piloto mostró los beneficios potenciales que se podían obtener en los diferentes desarrollos de productos de software. Posteriormente se definieron los proyectos cuyos productos de software tienen características especiales, por ejemplo, un sistema de aplicación crítica, en tiempo real y con tolerancia a fallas, en cual se implementaron pruebas automatizadas, no sólo funcionales, sino también unitarias y de integración.

En estos proyectos de desarrollo de software, los desarrolladores deben realizar las pruebas unitarias dependiendo del lenguaje que estén utilizando (Go, C#, Javascript, Typescript) y con algún marco de trabajo, propio para el lenguaje, por ejemplo, NUnit para C#. Las pruebas unitarias se enfocaron a probar de manera aislada a los módulos, clases, métodos o funciones de los componentes del software. Las pruebas de integración se realizaron con un marco de trabajo dependiente del lenguaje de programación y por un desarrollador diferente al responsable de la codificación original.

Para las pruebas funcionales, se definió a un grupo de desarrolladores que se encargan de realizar las pruebas automatizadas utilizando Selenium y dependiendo del proyecto, se utiliza C# o Java.

La implementación de pruebas automatizadas en este tipo de proyectos no es sencilla, ya que se requiere la integración de una gran cantidad de tecnología, pero una vez superados los retos tecnológicos, se obtienen mejoras sustanciales, tanto en los procesos de desarrollo, como en el producto de software, y, por lo tanto, en la satisfacción del usuario.

Factores que pueden afectar la automatización de las pruebas

Existen varios factores a tomar en cuenta al momento de implementar la automatización de pruebas, entre ellos:

  • La falta de experiencia de los desarrolladores en pruebas unitarias puede provocar que el código sea muy frágil, por lo que cualquier cambio en el código fuente del producto puede provocar que la prueba falle.
  • El código fuente de las pruebas se debe considerar en igualdad de importancia al código fuente del producto de software. Esto no es fácil de asimilar, debido a que los desarrolladores acostumbran avanzar en el desarrollo de la funcionalidad y al final realizar las pruebas.
  • Las presiones de entrega en tiempo pueden provocar que las pruebas unitarias se visualicen como una actividad que retrasa al desarrollador.

Beneficios de la automatización de las pruebas

El beneficio más tangible es contar con la capacidad de ejecutar todas las pruebas (unitarias, de integración y funcionales) en tiempos muy cortos (minutos), en lugar de las horas o días que lleva realizar las pruebas de manera manual. Esta agilidad permite verificar de manera muy rápida si alguno de los cambios o nuevas funcionalidades realizadas afecta el funcionamiento del componente o del sistema, y de ser el caso, poder realizar la corrección antes de la liberación correspondiente.

Otro beneficio menos tangible, pero muy relevante, es que, al contar con pruebas automatizadas es posible implementar un marco de trabajo para la integración continua (constantemente probar y generar las aplicaciones), esto se realiza mediante herramientas como: Jenkins, GitLab CI, TeamCity, entre otras, en conjunto con las herramientas para la automatización de las pruebas.

Finalmente, el cambio de paradigma al utilizar pruebas automatizadas, también incluye el beneficio adicional de que la estructura del código de los productos de software, mejora mediante la aplicación de patrones y técnicas de código limpio, lo que genera productos más robustos y con mayor facilidad para su mantenimiento en el tiempo.

Autores:
Raúl García Mendoza, rgarcia@ineel.mx
Alejandra Arelí Molina Gómez, molina024@gmail.com
Alfredo Espinosa Reza, aer@ineel.mx