Gran parte de la discusión sobre aseguramiento de la calidad (QA, por sus siglas en inglés) suele involucrar grandes conceptos y temas. Mucho tecnicismo, libros blancos y charlas TED. Puede volverse bastante abstracto muy rápido. Y, seamos sinceros, a menudo no es muy relevante para los obstáculos prácticos que los equipos de QA enfrentan en su día a día.
Por eso, a veces es útil bajar las revoluciones y centrarse en algunos de los aspectos más humildes de la disciplina. En este caso, la documentación de pruebas. Aparentemente un tema sencillo, pero, como con todo en el desarrollo de software, hay monstruos escondidos bajo las tablas del suelo.
La cuestión de cómo, y cuánto, documentar las pruebas implica casi de inmediato a los equipos de QA en una especie de callejón sin salida. Si documentas demasiado poco, es difícil saber cómo se está avanzando en el esfuerzo global. Y es aún más complicado reasignar tareas de prueba a diferentes recursos según la necesidad y mantener la coherencia. Pero si documentas en exceso—oh, un momento. ¿Acaso existe el exceso de documentación de pruebas?
¿O sí existe?
He visto muchas veces a equipos de QA embarcarse, de forma concienzuda y diligente, en la heroica tarea de documentar completamente sus pruebas. Para una publicación. Y luego esa documentación suele quedar olvidada. Acumulando polvo digital en algún servidor de red. Y no porque el equipo haya dejado de creer en su importancia. Simplemente están completamente exhaustos por el esfuerzo requerido para actualizarla en la siguiente versión importante.
Porque, en su celo, el equipo de QA escribió descripciones de pruebas increíblemente detalladas, desglosando todo a un nivel maniáticamente microscópico de hiperespecificidad. Creando documentación de pruebas por separado para cada aspecto o atributo de una sola característica o interacción de usuario. Generando docenas de descripciones y tareas individuales para lo que en realidad es una sola prueba. Es como esa persona frente a ti en la fila del supermercado que insiste en pagar $80 en monedas sueltas.
El resultado de este celo atomizador es la generación de cientos, a veces miles, de descripciones de pruebas para la versión correspondiente. Sin quererlo, QA ha terminado escribiendo una novela de Dickens. Una historia de diez mil ciudades. ¿Alguna vez has leído una de esas? Yo tampoco.
La consecuencia es que nadie tiene el tiempo ni la paciencia para actualizar esos miles de descripciones de pruebas individuales. Porque siempre tendrá más prioridad probar la siguiente iteración del software, ya que eso es lo que finalmente genera ingresos, mientras que actualizar la documentación de pruebas no.
Pero también porque las aplicaciones de documentación de pruebas no facilitan en absoluto realizar actualizaciones masivas de registros de documentación. Hacer cambios globales a clases de pruebas puede ser arduo y poco intuitivo en la mayoría de las aplicaciones (esto también ocurre con muchas aplicaciones de seguimiento de errores, incluso hoy en día). Aumentando el coste en tiempo y salud mental de hacerlo.
Como resultado, toda esa meticulosa documentación de pruebas termina abandonada. Y todo el tiempo invertido en crearla, al final, se desperdicia. Porque no es reutilizable. Es un éxito de un solo golpe. Es el "I Melt With You" de las pruebas de software. Y, sin embargo, la documentación de pruebas es absolutamente necesaria para que el esfuerzo de pruebas sea repetible y sistemático. De ahí el callejón sin salida.
Existe una salida a este dilema. Y, por mucho que me duela admitirlo, debemos mirar a la ingeniería para encontrar la solución. O al menos su inspiración. Los ingenieros enfrentaron un problema similar en los primeros años del desarrollo de software comercial. Debido a las limitaciones de los lenguajes de programación de entonces, para cada función, tenían que reescribir el código de los mismos atributos básicos, acciones y salvaguardas. Una y otra vez. La gestión de memoria y la recolección de basura eran un buen (y peligroso) ejemplo de este problema.
Como resultado, los ingenieros generaban enormes cantidades de código redundante y perdían muchísimo tiempo (no es que a los ingenieros necesariamente les moleste esto. Ebay sigue existiendo por una razón). Luego, alguien ingenioso inventó la programación orientada a objetos, donde se podían crear objetos de código que heredaban atributos predeterminados por su propia naturaleza. Ya no era necesario volver a escribir (o copiar y pegar) el mismo código cada vez. Lo que significaba que la calidad ya no dependía de la memoria o destreza mecanográfica de un ingeniero concreto. Por eso QA está eternamente agradecida.
Esta es una visión muy útil para QA cuando se enfrenta al callejón sin salida de la documentación de pruebas. El concepto de orientación a objetos como existe en la ingeniería no puede aplicarse directamente a este problema, pero como metáfora ofrece mucho. La inteligencia, por definición, se adapta fácilmente a nuevas situaciones.
En mi carrera me he encontrado muchas veces con el problema de cómo crear documentación de pruebas que sea completa pero concisa, útil en el momento pero también fácilmente reutilizable en futuras versiones. Y la solución a la que finalmente llegué fue aplicar la idea de un "objeto" a la documentación de pruebas en sí.
Aquí hablo de mucho más que una plantilla de documentación de pruebas. Estas son muy útiles como una herramienta de estandarización, por supuesto, pero son irrelevantes para el problema real. Desarrollé la idea de que las pruebas podían documentarse de manera que incluyera, en una sola documentación, todos sus diferentes modos, puntos de inflexión, flujos de trabajo y condiciones especiales. Cuando tuve esta revelación en mi cabeza, la respuesta de repente pareció muy sencilla. Y muy alcanzable.
Vamos a profundizar en eso.
Tomando la pastilla roja
La respuesta es ver cada prueba individual, y por lo tanto también su documento asociado, no como la afirmación o descripción de una prueba sobre un único punto de datos o condición aislada, sino como la descripción de toda la matriz (¿ves lo que hice?) de condiciones en las que la funcionalidad o capacidad necesita ser validada.
Esto implica un enfoque holístico para la definición individual de pruebas. Una tarea de prueba coherente y única no puede fragmentarse útilmente en docenas de "pruebas" independientes sin, paradójicamente, eliminar la especificidad en la evaluación del funcionamiento de la característica como un todo. Es un caso de ver el bosque por los árboles.
Aquí es útil repasar el concepto de contexto de prueba. Porque, para implementar efectivamente la idea de un objeto de prueba, primero se debe ser capaz de separar el núcleo inalterable de una funcionalidad de sus contextos secundarios de aplicación y operación. Esta es una cuestión que el estilo atómico de documentación de pruebas evita, y por eso los probadores nunca aprenden a realizar este análisis de manera sistemática y consciente. Otro inconveniente más del enfoque atómico.
En pocas palabras, los contextos de prueba para una funcionalidad o sistema son el conjunto de condiciones, entornos, flujos de trabajo o estados que pueden variar independientemente dentro de los límites de la funcionalidad misma. Los sistemas operativos y sus versiones son un claro ejemplo de esto. Los idiomas extranjeros son otro. Los estados del sistema son otro más (por ejemplo, para un servidor web, si la memoria caché está activada o no). Una vez entiendes esta distinción, puedes pensar fácilmente en muchos otros relevantes para los tipos de productos que estás probando.
Una vez que hayas realizado este análisis (que debería ser la base de toda planificación profesional de pruebas en todo caso), tendrás la capacidad de crear formas compactas de documentación de prueba que internalicen esta distinción. En el sistema que describo, un solo artefacto de documentación de pruebas consistirá en:
- Una descripción de la funcionalidad principal o capacidad bajo prueba.
- Una lista de todos los contextos en los que debe validarse la funcionalidad principal.
- Cualquier otro elemento que normalmente incluirías (precondiciones para que la prueba sea válida, recursos y privilegios del sistema necesarios para ejecutar la prueba, un enlace a los requisitos del producto relevantes, etc.). Nada de esto se elimina con lo que propongo.
En este punto puede que estés pensando: "¡Oye, eso podrían ser muchos contextos!". Bueno, claro. Pero míralo de esta manera. Hacerlo así no te genera más trabajo. De hecho, lo reduce. Redactar planes de pruebas completos se vuelve más fácil con nuestra lista curada de herramientas para documentación de pruebas de software. Porque este método *reducirá enormemente* la cantidad de pruebas individuales que necesitas crear y que tendrás que mantener (o negarte a hacerlo) en el futuro. Mientras que en el sistema atómico, tendrías que crear un artefacto de documentación de prueba para cada uno de ellos. Lo que lleva al callejón sin salida descrito al principio de este artículo.
Este método de documentación de pruebas sí tiene ciertas consecuencias a nivel de proceso que al principio pueden parecer incómodas. O incluso inquietantes. Y no solo para QA, sino también para otros implicados en el proyecto. Sin embargo, si todos los involucrados se toman el tiempo para entenderlas, verán que en realidad son mejoras. Para todos.
La principal de ellas es que, al agrupar la matriz de contextos de la funcionalidad en la propia prueba principal, esto significa, lógicamente, que si esa única prueba falla en cualquiera de esos contextos, entonces toda la prueba se considera fallida. Incluso si es solo en uno. Puedo imaginar que esto cause pánico entre los ingenieros. Porque puede parecer que se les está poniendo una traba imposible de superar para que una prueba cuente como "aprobada". Pero ese temor es fácil de disipar. Basta con señalarles dos cosas, y una tercera para uno mismo:
- Este método en realidad reduce la cantidad de errores generados contra su trabajo durante las pruebas. Ya que con el método atómico, el fallo en cualquiera de esos contextos produciría su propio error independiente. Así aumentaría el número total de errores registrados contra esa funcionalidad en particular. Eso debería sacar una sonrisa a los ingenieros. Y a los gestores de proyectos.
- En segundo lugar, probar usando esta metodología proporciona automáticamente contexto sobre el alcance real del fallo funcional. Porque, ¿cuál es la primera pregunta que el ingeniero asignado para solucionar el error siempre va a hacerte? "Eh, ¿pasa en todas partes? ¿O solo en el contexto X?" Y, en vez de tener que darte prisa de vuelta a tu escritorio y repetir la prueba en el contexto X (¿quizás olvidaste hacerlo en tus pruebas originales?) ya tendrás esa respuesta, y el ingeniero no podrá excusarse para posponer el arreglo (lo que QA da en menos errores, lo quita luego).
- En tercer lugar, el análisis de contextos para la documentación de pruebas garantiza que realmente pensaste en todos los contextos relevantes al documentar la prueba. Lo que significa que es menos probable que sufras esos momentos de pánico —tres días antes o, peor, después de la publicación— cuando te das cuenta de que olvidaste probar en algunos muy importantes. Un esfuerzo de QA basado en el pánico no es nada efectivo. Ni psicológicamente satisfactoria.
En la máquina
Este método de documentación de pruebas inspirado en objetos reducirá drásticamente la cantidad de artefactos de documentación que tienes que producir, y por tanto hará mucho más probable que realmente puedas —y quieras— mantenerlos y actualizarlos para lanzamientos futuros.
El único inconveniente es que pocas aplicaciones de documentación de pruebas están preparadas para documentar pruebas de esta manera de forma nativa. Tienden a asumir el modelo atómico de documentación, ya que lamentablemente es la norma, y por tanto no cuentan con la funcionalidad nativa necesaria para acomodar fácilmente el modelo de objeto que he descrito aquí.
Por eso muchas veces he recurrido a soluciones de aplicación mucho menos elaboradas — como Excel — que en realidad, para este propósito, son mucho más flexibles y fáciles de personalizar, porque son de propósito general. La desventaja de esa estrategia es que integrarlas con Jira y otros se vuelve engorroso. Pero quizás la integración está sobrevalorada.
En cualquier caso, sigue siendo cierto que muchas aplicaciones para documentar pruebas y defectos hacen diabólicamente difícil realizar actualizaciones en lote de registros individuales. Independientemente de los protocolos que elijas para crearlas. Pero eso es verdad sin importar cómo decidas escribir la documentación de tus pruebas. Un problema a la vez, gente.
Perdón de antemano (o en tu caso, a posteriori) por no darte una plantilla de objeto de prueba. Según mi experiencia, proporcionar plantillas suele ser una mala idea porque la gente simplemente empieza a usar tu plantilla. La disponibilidad de plantillas genéricas ya hechas tiende a interrumpir y dejar de lado la creatividad del equipo a la hora de idear una plantilla que se adapte realmente a sus necesidades, procesos y herramientas reales. Así que, sin resentimientos.
Siempre estoy abierto a tus preguntas y sugerencias. Solo publícalas o mándamelas por mensaje en LinkedIn.
Y, como siempre, te deseo lo mejor.
