Le module unittest de Python signale-t-il toujours les erreurs en stricte correspondance avec l'ordre d'exécution des lignes dans le code testé? Les erreurs créent-elles la possibilité de changements inattendus dans les variables du code? J'ai été déconcerté par une KeyError rapportée par unittest. La ligne elle-même semble correcte. Sur la dernière ligne avant l'arrêt de l'exécution, débogage des impressions de la clé demandée et le dictionnaire a montré que la clé était dans le dictionnaire. La clé référencée dans KeyError était une clé différente, mais cela semblait aussi être dans le dictionnaire. J'ai inséré une variable compteur dans la boucle externe pour imprimer le nombre d'itérations externes juste avant la ligne d'erreur (à l'intérieur d'une boucle interne), et celles-ci ne sont pas sorties dans la séquence attendue. Ils sortent quelque chose comme 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 2, 2, 2 - quand je m'attendrais à quelque chose comme 0, 0, 0, 1, 1, 1, 2, 2, 2. Et les impressions de débogage des données internes montrent des changements inattendus d'une boucle à l'autre.Est-ce que Python unittest signale des erreurs immédiatement?
code (avec de nombreuses lignes de débogage):
def onSave(screen_data):
counter = 0
for table, flds_dct in self.target_tables.items():
print 'TABLE %s' % table
print 'FIELDS: %s' % flds_dct['fields']
tbl_screen_data = {}
for fld in flds_dct['fields']:
print 'LOOP TOP'
print 'FIELD: %' % fld
print 'SCREEN DATA: %s' % screen_data
print 'COUNTER: %s' % counter
print 'SCREEN DATA OUTPUT: %s' % screen_data[fld]
tbl_screen_data[fld] = screen_data[fld]
print 'LOOP BOTTOM'
self.tables[table].addEntry(tbl_screen_data)
counter =+ 1
print 'OUTER LOOP BOTTOM'
Juste avant l'erreur, cette sortie:
TABLE: questions
FIELDS: ['whatIsYourQuest', 'whatIsYourName', 'whatIsTheAirSpeedOfSwallow']
LOOP TOP
FIELD: whatIsYourQuest
SCREEN DATA:
{'whatIsYourQuest': 'grail',
'whatIsYourName': 'arthur',
'whatIsYourFavouriteColour': 'blue',
'whatIsTheAirSpeedOfSwallow': 'african or european?',
'whatIsCapitalOfAssyria': 'Nineveh'}
COUNTER: 1
SCREEN DATA OUTPUT: grail
LOOP BOTTOM
OUTER LOOP BOTTOM
Mais l'exécution arrête et je reçois ce message d'erreur:
line 100, in writeData
print 'SCREEN DATA OUTPUT: %s screen_data[fld]
KeyError: 'whatIsCapitalOfAssyria'
Mais l'erreur est attribuée à une ligne qui a déjà imprimé sa sortie et arrête l'exécution après t La sortie de plusieurs lignes après la ligne avec l'erreur.
Comme je l'ai mentionné ci-dessus, un débogage supplémentaire montre que le contenu de screen_data est modifié au cours des itérations de la boucle. Fondamentalement, le dictionnaire transmis n'a pas de clé 'whatIsCapitalOfAssyria'.
L'absence de cette clé était la cause de l'erreur. À un certain point, le code a demandé au dictionnaire screen_data 'whatIsCapitalOfAssyria', auquel il n'a pas pu répondre, et donc, bien sûr, il a été jeté du Pont de la Mort, err, échoué. MAIS il était difficile de voir que lorsque l'objet screen_data produit dans les lignes de débogage a a la clé; et la condition d'erreur signalée n'est pas levée avant l'exécution de beaucoup plus de lignes, ce qui rend confus l'inspection des valeurs locales à l'erreur.
Alors comment unittest gère-t-il les erreurs de code? Qu'est-ce que je fais mal ici? Comment dois-je l'utiliser pour éviter ce genre de chose?
EDIT: Il peut être utile si j'ai ajouté que la méthode testée déclenche des appels sur un certain nombre d'autres méthodes, ce qui déclenche les appels eux-mêmes. Je pense que tout cela est raisonnablement bien testé, mais peut-être que le nombre d'appels interconnectés est important.
Si vous ne l'avez pas déjà fait, supprimez tous les fichiers .pyc et .pyo dans les répertoires à partir desquels vous exécutez ce code, puis réessayez. Parfois, lorsque je reçois des résultats inexplicables comme celui-ci, un fichier bytecode qui n'est pas synchronisé avec la source est la cause (il est vrai que c'est plutôt rare). –