Capítulo 13. Pruebas unitarias (Unit Testing)

13.1. Introducción a los números romanos

En capítulos interiores, se “sumergió” dando un vistazo rápido al código e intentándo comprenderlo lo más rápidamente posible. Ahora que tiene bastante Python a sus espaldas, vamos a retroceder y ver los pasos que se dan antes de escribir el código.

En los próximos capítulos vamos a escribir, depurar y optimizar una serie de funciones de utilidad para convertir números romanos a decimales, y viceversa. Vimos el mecanismo de construir y validar los números romanos en Sección 7.3, “Caso de estudio: números romanos”, pero ahora retrocederemos y consideraremos lo que tomaría expandirlo en una utilidad de doble sentido.

Las reglas de los números romanos llevan a varias observaciones interesantes:

  1. Sólo hay una manera correcta de representar un número en particular en romanos.
  2. A la inversa también es cierto: si una cadena de caracteres es un número romano válido, representa un número único (es decir sólo se puede leer de una manera).
  3. Hay una cantidad limitada de números expresables en romanos, específicamente desde 1 a 3999. (Los romanos tenían varias maneras de expresar números más grandes, por ejemplo poniendo una barra sobre un número representando que su valor normal debería multiplicarse por 1000, pero no vamos a tratar con eso. Para el propósito de este capítulo, estipularemos que los números romanos van de 1 a 3999).
  4. No hay manera de representar 0 en números romanos. (Sorprendentemente, los antiguos romanos no tenían concepto de 0 como número. Los números eran para contar cosas que tenías; ¿cómo ibas a contar lo que no tenías?)
  5. No hay manera de representar números negativos en romanos.
  6. No hay manera de representar fracciones o números no enteros en romanos.

Dado todo esto, ¿qué podríamos esperar de un conjunto de funciones para convertir de y a números romanos?

Requisitos de roman.py

  1. toRoman debería devolver la representación en romanos de todos los enteros del 1 al 3999.
  2. toRoman debería fallar cuando se le dé un entero fuera del rango 1 al 3999.
  3. toRoman debería fallar cuando se le dé un número no entero.
  4. fromRoman debería tomar un número romano válido y devolver el número que representa.
  5. fromRoman debería fallar cuando se le dé un número romano no válido.
  6. Si tomamos un número, lo convertimos a romanos, y luego de vuelta a un número, deberíamos acabar con el mismo número con que empezamos. Así que fromRoman(toRoman(n)) == n para todo n en 1..3999.
  7. toRoman debería devolver siempre un número romano usando letras mayúsculas.
  8. fromRoman sólo debería aceptar números romanos en mayúsculas (es decir debería fallar si se le da una entrada en minúsculas).

Lecturas complementarias

  • Este sitio cuenta más cosas sobre los números romanos, incluyendo una fascinante historia sobre la manera en que los romanos y otras civilizaciones los usaban (versión corta: descuidada e inconsistentemente).