Mostrando las entradas con la etiqueta testing. Mostrar todas las entradas
Mostrando las entradas con la etiqueta testing. Mostrar todas las entradas

martes, 7 de abril de 2015

Into the void.

Siguiendo con lo del post anterior, el desarrollo de “mi producto de prueba” entra oficialmente en la etapa de autobombo. Voy a tratar de no ponerme monotemático, así que el siguiente link es lo único que voy a poner explícitamente al respecto por ahora:

“Pasen y vean, qué lindas chucherías” (el que no entienda la referencia que busque la frase, vale la pena).

De alguna manera subestimé (para variar) el efecto psicológico del “lanzamiento”.

No había tenido que dar la cara hasta ahora. En mis trabajos anteriores picaba código que luego se testeaba e iba a producción donde fallaba miserablemente. Así fue siempre, igual que ahora. Pero la responsabilidad era compartida. La verdad sea dicha: las consecuencias inmediatas (llamados a media noche, apuros, gritos e insultos) solían recaer más en las áreas de soporte, testing y calidad (cuando había) que en mi escurridiza persona. No se puede hacer bugfixing con 20 monos desesperados gritándote alrededor y otros 20 por teléfono / skype / email / twitter / señales de humo avisándote de que el sitio no anda. Así que mientras yo arreglaba la cosa otros atajaban los sopapos.

Personalmente, esa división de tareas siempre me pareció (y me sigue pareciendo) bien. Pero ahora no hay con quién dividir el trabajo y, lo que es peor, nadie se desespera. Ojalá hubiese alguien tan necesitado de esta humilde herramienta (que feo suena eso) como para llegar al extremo del reclamo. Lo que sucede es algo peor: la nada misma. El vacío, fardos rodando, grillos a la luz de la luna.

Si te fuiste a dormir, tu sitio puede estar en llamas escupiendo 500 para todos lados que no te vas a enterar. ¿Los usuarios? Si te he visto no me acuerdo. Un amigo, un conocido o un familiar manda un mail con un “che, no anda” y con suerte te enterás a la mañana siguiente. Cada uno de esos desconocidos arrastrados a pulso, sangre, sudor y lágrimas (qué exagerado) ahora están viendo (si es que no se fueron ya) la aplicación retorcerse lastimosamente en medio de un infarto de javascript, con el pulgar en el Alt y el índice a punto de dar el Tab definitivo. Por lo menos en el corto plazo.

Por eso, si va a explotar (y al principio va a explotar), mejor que sea entre amigos dispuestos a dar una mano, avisar: probar de vuelta más adelate. Pero eventualmente hay que sacar la red y seguir haciendo piruetas. No es para tanto… si pinchó es que anduvo por un rato, ¿no?

martes, 23 de junio de 2009

Paradigmas.

Los desarrolladores somos –¿hipótesis?- ante todo humanos, luego usuarios, luego desarrolladores.

Como humanos –entre otras cosas-, tendemos a sobrevalorar la propia experiencia. Por ejemplo, si el sistema que desarrollamos nos es fácil de utilizar solemos atribuirle esta característica obviando el hecho de que hemos aprendido a utilizarlo “desde atrás” (es decir, desde el código, el diseño o los requerimientos) y no “desde adelante” (desde la pantalla, los manuales o la capacitación). Para cuando nos enfrentamos a la pantalla de inicio ya sabemos casi de memoria todo lo que sigue. Abstraerse de este conocimiento es –por más que me juren y recontrajuren- imposible, y es por eso que nuestras pruebas y experiencias personales son bastante objetables como medida de lo que sucederá en el mundo real. Esto se aplica, con variaciones, tanto a desarrolladores como a analistas, testers, líderes de proyecto y a cualquiera implicado en el desarrollo de software (excepto, claro está, al cliente y al usuario).

Además de humanos –si es que damos por válida la hipótesis-, somos usuarios de sistemas de un determinado negocio: entornos de desarrollo, clientes de bases de datos, herramientas de diseño y documentación de requisitos, entre muchos otros, conforman el software de soporte al negocio del desarrollo de software. Negocio en el que estamos inmersos y que, como todos, tiene su paradigma establecido y materializado en la forma de determinados estándares: flujos de trabajo, herramientas visuales, disposición física de los objetos en una oficina… todo lo que nos rodea se deriva de éste en alguna medida.

La importancia de estos elementos –paradigma y estándares- que sobre el papel parecen un conjunto arbitrario de caprichos funcionales -¿por qué Ctrl+U y Ctrl+Shift+U? ¿Por qué un árbol y no una serie de listas encadenadas?- radica en que condicionan toda nuestra visión de la realidad (¡vaya si estamos condicionados por los paradigmas de nuestro negocio!). Los sistemas -si pretenden ser exitosos- deberán respetar –o revolucionar, pero esto es más difícil-, sobre todo en la interacción con sus usuarios, los paradigmas del negocio para el que fueron diseñados.

Como desarrolladores que somos –de eso sí estamos seguros- nos sería imposible, si estuviésemos librados a nuestro criterio, no aplicar el paradigma y los estándares propios del negocio al que pertenecemos –el desarrollo de software- a los sistemas que desarrollamos.

El problema es que, como establecimos más arriba, otros negocios o actividades tienen estándares y paradigmas diferentes. Internalizarlos es prácticamente imposible (deberíamos ser, por ejemplo, tan usuarios de distintos sistemas de gestión como lo somos de distintos entornos de desarrollo, tanto como lo es un empleado administrativo que ha transitado por diferentes empresas y puestos). Sólo podemos pretender, a lo más, conocerlos. Y para ello se requiere de una experiencia… “presencial”. Es la experiencia que trata de transmitir el analista funcional, el área comercial o quienquiera que tenga contacto directo con el cliente.

Pero un modelo mental es algo realmente difícil de describir, los estándares que se deriven de éste serán en su gran mayoría reglas y prácticas comunes y no estarán explicitadas en ningún lado. Es, en definitiva, difícil de transmitir. Por todo esto, cuantos más intermediarios haya entre aquellos que conocen a los clientes y usuarios y los desarrolladores, más probabilidades habrá de que nos apartemos del paradigma y los estándares a los que ellos están acostumbrados.

lunes, 23 de febrero de 2009

Frases: análisis de impacto o…

thumb Una pequeña modificación a las apuradas aquí y… una gran explosión allí. ¿Qué paso?

- Y… falló el análisis de impacto.

- ¿Análisis de impacto? Acá no hacemos análisis de impacto. Hacemos análisis forense.

lunes, 5 de enero de 2009

Búsqueda de errores y depuración: una historia, un poco de metodología y algunos consejos.

Último día laboral de este 2008. 7.20 de la mañana (¡sí señor!), ya despabilado y mate en mano frente a la pantalla. Mientras inicia Windows, el entorno de desarrollo y el proyecto (y un largo etc.) leo un auto-recordatorio de baja tecnología (un papel suelto sobre el teclado) que dice "ver incidente 1269". Me acuerdo del protagonista de Memento quien, como yo, tiene el Garbage Collector demasiado activo: no recuerdo de qué se trata el maldito 1269.

Resumamos esquemática y velozmente algo que en realidad es un poco más complejo, pero no viene al caso: vendo una combinación de "fichas" de diferentes valores preestablecidos, eligiendo el usuario la combinación deseada. La pantalla pide primero el importe, luego ofrece la lista con las distintas fichas disponibles donde el usuario indicará la cantidad requerida de cada una.

Hay un tipo de ficha que es el más vendido. Por lo tanto cuando el usuario ingresa el importe y lo confirma se presenta completado por defecto el cuadro correspondiente a este tipo con el importe traducido en cantidad.

Como el usuario puede cambiar los valores, al final se comprueba que la entrada (el importe) sea igual a la salida (el valor de las fichas) y si está todo ok, se graba y listo.

Ya tenemos la primera máxima:

Ver el cuadro completo antes de bajar a los detalles: luego de una leída rápida al reporte del incidente hay que abocarse en obtener "the big picture": la mirada del cliente (humano o no), determinar el papel de esta funcionalidad dentro del sistema y, sobre todo: saber cómo debería funcionar.

Una nota: el caso en particular puede variar, pero en general un reporte de error o incidente sólo describe una situación, que no debería aceptarse como un error sin más análisis. Por ello el siguiente paso es reproducir la situación y clasificarla (por ejemplo: "error del sistema", o "error del entorno de ejecución", "nueva funcionalidad", o "error en el reporte de error" -valga la redundancia- o etiquetas similares).

Un poco de manoseo con la pantalla en cuestión no dejó lugar a dudas: si yo ingresaba un importe imposible de vender en fichas (digamos $10,31 y yo tengo fichas de $1 cada una) el sistema redondeaba la cantidad ofrecida por defecto (en mi ejemplo ofrecería vender 10 u 11 fichas). Al confirmar la transacción se leía un bonito mensaje "la transacción no suma 0" (una excepción de negocio medio genérica que se aplica a un sinfín de situaciones). Hasta ahí iba bastante bien aunque pensé que podría mejorar el mensaje. Pero cuando retrocedí y corregí el importe y volví a avanzar... ¡crash bum pang! Un error no controlado rompía la mitad de la pantalla. Ok. Hay un error, no cabe duda.

Esto da para un poco de teoría: el primer mensaje fue una excepción (controlada), el segundo un error. Escribí un poco más sobre eso hace poco: Errores y excepciones parte I, parte II y parte III. Pero citemos así seguimos adelante:

[...] Entiendo que una excepción es una situación inusual en la ejecución del sistema, pero contemplada al momento de diseñar el sistema o de escribir el código. [...] Un error, a diferencia de la excepción, es una respuesta o estado no contemplado en el sistema. [...]

Es decir, que el dinero ingresado no coincidiera con el valor de las fichas que salían era algo contemplado, se estaba chequeando (aunque me molestara el mensaje). Pero el posterior aterrizaje poco sutil de la aplicación, digamos, fue resultado de algo no contemplado por nadie (espero).

Así que me puse a leer ese feo mensaje de error. Completo, con stack trace y todo. Aunque ud. no lo crea, esto es algo que poca gente hace. Y así es como nos llenan de reportes de error del tipo "La conexión a la base de datos se ha caído." o "Disk Full". Es decir, situaciones que están claramente descritas en ese mensaje... que nadie lee.

Pero no son sólo los usuarios. Cierta ansiedad profesional nos lleva a enchufar el depurador, reproducir la situación, concentrarnos en la línea que tira el error y empezar desde ahí (tratando desesperadamente de no ir a ningún otro lado, como si todos los errores estuviesen en la última línea que se ejecutó del código). Mucha de esa información está ahí, delante nuestro.

Un dato importante obtenido al leer el mensaje que explotó la aplicación fue, justamente, "El tipo de ficha ya se encuentra incluido en la transacción". Es decir, era un mensaje codificado por nosotros, no un error descontrolado. En algún lado del código la situación fue tratada como una excepción (es decir contemplada), pero la aplicación explotó igual.

El siguiente punto de análisis es ¿qué debería haber pasado? Para corregir un error primero tenemos que saber cómo nos hubiese gustado que termine la historia. Como todo en sistemas, se empieza por la salida. ¿A dónde quiero llegar?

Pensé un poco en la situación, ordenando los problemas cronológicamente:

  • En principio, me debería haber informado de que no se podía vender por ese importe cuando lo confirmé y no dejarme seguir hasta el final de la operación. Los errores de entrada se informan lo antes posible.

  • Después, al confirmar toda la operación, el mensaje podría haber sido algo así como "No puede conformar el importe indicado con las fichas disponibles" en vez de eso tan extraño de "La transacción no suma 0".

  • Para seguir, al ir hacia atrás y volver a intentar se ve que el sistema intentó ingresar a la operación el mismo tipo de ficha dos veces, o aún más probable, que no haya borrado lo que estaba antes de reintentar.

    Eso se deduce del segundo mensaje, "El tipo de ficha ya se encuentra incluido en la transacción". No puedo decir que vendo 5 fichas de $1 por un lado y otras 5 de $1 por el otro en la misma operación, tiene que detallarse una y sólo una vez cada tipo de ficha: son 10 fichas de $1.

    Una nota importante: mal por el front-end, que primero se olvidó de borrar y después no contempló la posibilidad de una excepción. Bien por el negocio que controló la situación salvando las papas del fuego al cancelar la operación y arrojar una excepción con un mensaje decente. Es como si hubiese gritado dramáticamente "¡no puedo hacer eso, soy demasiado bueno, prefiero morir!"). ¿O hubiesen preferido quedar mejor con el cliente, que no pase nada, ni reportes, ni llamadas desesperadas, ni nada y encontrarse a fin de mes con 10.000 ventas que no cierran?.

  • Pero ese último mensaje debería haberse mostrado prolijamente como el primero, sin embargo en la pantalla apareció como un error no controlado.

    Otra nota: si luego de este bodoque siguen con ganas de leer los artículos citados, verán que esta situación indica que una excepción lanzada en la capa de negocio hizo "explotar" a la capa de presentación porque debido a un error ella no se lo esperaba. El problema no es el mensaje, sino que la capa de presentación no lo esperara y mostrara correctamente.

Me gustaría que los líderes de proyecto que lean esto lo tengan en mente cuando en su próximo ataque de ansiedad (ya sé que uds. ponen la cara) pretendan que arreglemos "esa bobada de los centavos" en 10 o 15 minutos o renieguen de que "el sistema explotó por una boludez tontería (pero nosotros tenemos que aguantarlos, y no tenemos a nadie más para descargar tensiones... lo que me recuerda "Reacciones ante los errores en un sistema informático").

Como podemos ver, que el sistema explote por una bobada es de por sí un error grave que trasciende esa bobada.

Ante este tipo de situaciones tenemos dos alternativas: resolver la bobada, y luego la otra y la otra y la otra (porque bobadas hay muchas) o resolver el problema de fondo logrando que el sistema resista las bobadas dejándonos más tranquilos y con más tiempo para trabajar en lo que nos gusta.

Para ser más explícito y utilizar el ejemplo: hay una larga cadena de errores, pero el último es el peor. Si ese mensaje se hubiese mostrado correctamente en vez de hacer explotar la pantalla,

  • el usuario se habría dado cuenta de que con reiniciar la operación bastaba para seguir trabajando,
  • lo hubiese percibido como una desprolijidad menor y no como un error de la aplicación,
  • y así la prioridad de todo el asunto baja bastante, ¿no?

Por supuesto, es más fácil arreglar el problema puntual de los centavos que solucionar todo eso.

Pero por suerte no le explotó al cliente en producción sino a nuestro equipo de pruebas (bien por ellos) con lo cual en vez de nervioso me sentía contento y aliviado. La misma sensación que debe tener un acróbata cuando tras fallar una pirueta aterriza suavemente en su red de seguridad.

No lo aclaré antes porque le resta dramatismo a todo.

Para finalizar:

  • ¿Programador principiante? Mira la línea en la que saltó el error y no entiende nada. Va hacia atrás y donde puede poner un "if" para evitar la situación lo enchufa, probablemente rompiendo otra cosa.
  • ¿Programador desganado? Arregla lo de los centavos (el primer problema) y todo lo demás desaparece... por un rato.
  • ¿Programador apurado? Arregla el último problema (el del mensaje) y manda el arreglo. Deja los demás registrados detalladamente con una solución propuesta para después.
  • ¿Yo en el último día de trabajo del año? En apenas 9 horitas lo tengo todo resuelto, cuando alguien me pida explicaciones le paso un link a este post, aunque seguramente no llegue al final.

¿Y cómo se corrige eso? Del último al primero:

  • que el mensaje de excepción no explote la pantalla (y lo pruebo),
  • que borre la basura de la operación incompleta evitando que tire ese mensaje (y lo pruebo),
  • cambiando el mensaje al final de la transacción para que diga claramente que no puede vender ese importe en fichas porque no hay forma (y lo pruebo),
  • y por último agregando un control para que controle esto apenas ingresado el importe (y lo pruebo).

Y así, mi catedral no sólo es más bonita, también es más resistente.

Un tip: vean que de esta manera voy probando todos los arreglos a medida que los voy implementando con el mismo caso de prueba. Si empiezan por el final, luego probar todo es un problema.

Espero que hayan llegado hasta aquí leyendo todo, despiertos y con ganas de vivir...

Ah, por cierto, cuando volvía para casa a las 18.00 me dí cuenta de un pequeño detalle que introduje en el último arreglo: si quiero vender $10.50 y tengo fichas de $1 y de $0.50 (operación 100% válida) pero tengo como predeterminada la ficha de $1 el sistema va a tratar de proponer $10.50 en fichas de $1, no va a poder y por obra y gracia de mis controles prematuros va a trabar toda la operación sin darle posibilidad al usuario de modificar las cantidades.

En resumen: corregí un buen par de problemas graves, pero por un pequeño error lo dejé, a ojos del mundo, peor que como estaba. ¡Ah! Y para eso tardé todo el día.

¿Me acordaré de corregirlo cuando vuelva? Seguro que sí, porque ese día es hoy y alguien me va a avisar. Magias de la programación de posts.

jueves, 4 de septiembre de 2008

Testing es veneno para la mente.

Yo siempre lo pensé y por eso tengo reservado a los testers mi más profundo cariño.

Porque hay que tener ganas, realmente... pantalla por pantalla, botón por botón, probando desde las combinaciones más simples hasta las más delirantes, tratando de ganar en maldad y superar en estupidez al usuario (toda una utopía).

Y porque aunque en menor medida, ellos también sufren, junto a los desarrolladores, la suerte que el destino reserva a aquellos que han cometido graves faltas en vidas anteriores (o en ésta): no importa qué tan bien hagan su trabajo, siempre fracasarán. Si descubrieron 1000 bugs en el sistema éstos serán reparados y olvidados rápidamente, y serán denostados por "ése tan obvio" que se les pasó.

Lo que sufren ocasionalmente (gracias a ellos) los usuarios estos pobres mártires lo sufren día a día, hora tras hora, y se levantan y van por más.

Arriesgaría que los sistemas administrativos son peores. Hay tantas posibilidades, idas y vueltas, cancelaciones, aprobaciones parciales, cierres y contracierres, documentos que vencen y situaciones ambigüas que asustan. Éstos sistemas usualmente funcionan aparentemente bien, lo cual es peor, porque bajo esa apariencia de solidez pueden ocultarse graves errores conceptuales, de negocio.

¡Pero qué divertido probar un juego! Pensamos a veces... no nos engañemos. Probar no es jugar y tratar de repetir y definir aquella acción que nos transportó desde un mundo virtual a un loop infinito no puede ser sino el peor de los calvarios.

Como desarrollador a veces me fastidio, sobre todo cuando me vienen con bolu nimiedades, pero cada vez que se descubre un "pequeño agujero negro" en el sistema pienso qué hubiese tenido que soportar si se les hubiese pasado... porque a mí ya se me había pasado.

Cuando faltan, sentimos que estamos trabajando a 30 metros de altura sin red, cuando no reportan nos ponemos nerviosos... nunca está bien, si no hay errores es simplemente que no los están encontrando.

Entonces, digo, ¡defendamos a los testers! Cuidemos de aquellos pocos a los que les encanta su trabajo, sobre todo de declaraciones ignorantes y difamantes. Hago público mi voto de censura hacia Elvira Lindo, que probablemente escriba muy lindo, pero que de sistemas seguro no entiende nada. Y cito:

"Usar la inteligencia solo para buscar los errores de los demás acaba envenenando, y acaba no siendo inteligencia."

- Elvira (que no merece otro link), vía Microsiervos, quienes deberían disculparse, sí, sí, sí.