| You are here: Inicio > Inmersión en Python > Programación Test-First | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Ahora que están terminadas las pruebas unitarias, es hora de empezar a escribir el código que intentan probar esos casos de prueba. Vamos a hacer esto por etapas, para que pueda ver fallar todas las pruebas, y verlas luego pasar una por una según llene los huecos de roman.py.
Este fichero está disponible en py/roman/stage1/ en el directorio de ejemplos.
Si aún no lo ha hecho, puede descargar éste ejemplo y otros usados en este libro.
"""Convert to and from Roman numerals""" #Define exceptions class RomanError(Exception): passclass OutOfRangeError(RomanError): pass
class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass
def toRoman(n): """convert integer to Roman numeral""" pass
def fromRoman(s): """convert Roman numeral to integer""" pass
| Así es como definimos nuestras excepciones propias en Python. Las excepciones son clases, y podemos crear las nuestras propias derivando las excepciones existentes. Se recomienda encarecidamente (pero no se precisa) que derive Exception, que es la clase base de la que heredan todas las excepciones que incorpora Python. Aquí defino RomanError (que hereda de Exception) para que actúe de clase base para todas las otras excepciones que seguirán. Esto es cuestión de estilo; podría igualmente haber hecho que cada excepción derivase directamente de la clase Exception. | |
| Las excepciones OutOfRangeError y NotIntegerError se usarán en toRoman para indicar varias formas de entrada inválida, como se especificó en ToRomanBadInput. | |
| La excepción InvalidRomanNumeralError se usará en fromRoman para indicar entrada inválida, como se especificó en FromRomanBadInput. | |
| En esta etapa, queremos definir la API de cada una de nuestras funciones, pero no programarlas aún, así que las dejamos vacías usando la palabra reservada de Python pass. |
Ahora el momento que todos esperan (redoble de tambor, por favor): finalmente vamos a ejecutar la prueba unitaria sobre este pequeño módulo vacío. En este momento deberían fallar todas las pruebas. De hecho, si alguna prueba pasa en la fase 1, deberíamos volver a romantest.py y evaluar por qué programamos una prueba tan inútil que pasa en funciones que no hacen nada.
Ejecute romantest1.py con la opción -v, que le dará una salida más prolija para que pueda ver exactamente qué sucede mientras se ejecuta cada caso. Con algo de suerte, su salida debería ser como ésta:
fromRoman should only accept uppercase input ... ERROR toRoman should always return uppercase ... ERROR fromRoman should fail with malformed antecedents ... FAIL fromRoman should fail with repeated pairs of numerals ... FAIL fromRoman should fail with too many repeated numerals ... FAIL fromRoman should give known result with known input ... FAIL toRoman should give known result with known input ... FAIL fromRoman(toRoman(n))==n for all n ... FAIL toRoman should fail with non-integer input ... FAIL toRoman should fail with negative input ... FAIL toRoman should fail with large input ... FAIL toRoman should fail with 0 input ... FAIL ====================================================================== ERROR: fromRoman should only accept uppercase input ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 154, in testFromRomanCase roman1.fromRoman(numeral.upper()) AttributeError: 'None' object has no attribute 'upper' ====================================================================== ERROR: toRoman should always return uppercase ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 148, in testToRomanCase self.assertEqual(numeral, numeral.upper()) AttributeError: 'None' object has no attribute 'upper' ====================================================================== FAIL: fromRoman should fail with malformed antecedents ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 133, in testMalformedAntecedent self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: InvalidRomanNumeralError ====================================================================== FAIL: fromRoman should fail with repeated pairs of numerals ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 127, in testRepeatedPairs self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: InvalidRomanNumeralError ====================================================================== FAIL: fromRoman should fail with too many repeated numerals ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 122, in testTooManyRepeatedNumerals self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: InvalidRomanNumeralError ====================================================================== FAIL: fromRoman should give known result with known input ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 99, in testFromRomanKnownValues self.assertEqual(integer, result) File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual raise self.failureException, (msg or '%s != %s' % (first, second)) AssertionError: 1 != None ====================================================================== FAIL: toRoman should give known result with known input ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 93, in testToRomanKnownValues self.assertEqual(numeral, result) File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual raise self.failureException, (msg or '%s != %s' % (first, second)) AssertionError: I != None ====================================================================== FAIL: fromRoman(toRoman(n))==n for all n ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 141, in testSanity self.assertEqual(integer, result) File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual raise self.failureException, (msg or '%s != %s' % (first, second)) AssertionError: 1 != None ====================================================================== FAIL: toRoman should fail with non-integer input ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 116, in testNonInteger self.assertRaises(roman1.NotIntegerError, roman1.toRoman, 0.5) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: NotIntegerError ====================================================================== FAIL: toRoman should fail with negative input ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 112, in testNegative self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, -1) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: OutOfRangeError ====================================================================== FAIL: toRoman should fail with large input ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 104, in testTooLarge self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 4000) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: OutOfRangeError ====================================================================== FAIL: toRoman should fail with 0 input---------------------------------------------------------------------- Traceback (most recent call last): File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 108, in testZero self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 0) File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises raise self.failureException, excName AssertionError: OutOfRangeError
---------------------------------------------------------------------- Ran 12 tests in 0.040s
FAILED (failures=10, errors=2)
[17] El nombre de esta técnica se toma de la Programación Extrema (o XP)
<< Pruebas de cordura |
| 1 | 2 | 3 | 4 | 5 | |
roman.py, fase 2 >> |