Au Chapitre 13, Tests unitaires, vous avez appris la philosophie des
tests unitaires. Au Chapitre 14, Ecriture des tests en premier, vous avez suivi pas à
pas l'implémentation de tests unitaires en
Python. Au Chapitre 15, Refactorisation, vous
avez vu comment les tests unitaires facilitent la refactorisation à
grand échelle. Ce chapitre va poursuivre le développement de ces
programmes, mais cette fois en mettant l'accent sur des techniques
avancées de Python plutôt que sur les test
unitaires proprement dit.
Voici un programme Python complet qui
remplit le rôle de framework pour les
tests de régression. Il prend les tests unitaires que vous avez
écrits pour chaque modules, les assemble en une seule suite de tests et
les exécute en une seule fois. J'utilise ce script pendant la procédure
de construction de ce livre, j'ai des tests unitaires pour plusieurs
programmes d'exemple (pas seulement le module
roman.py du Chapitre 13, Tests unitaires) et la
première chose que mon script de construction automatique fait est
d'exécuter ce programme pour être sûr que tous mes exemples fonctionnent
encore. Si ce test de régression échoue, la construction s'arrête
immédiatement. Je n'ai pas plus envie de publier un exemple qui ne
marche pas que vous de le télécharger et de vous gratter la tête face à
l'écran en vous demandant ce qui ne va pas.
Exemple 16.1. regression.py
Si vous ne l’avez pas déjà fait, vous pouvez télécharger cet exemple ainsi que les autres exemples du livre.
"""Regression testing framework
This module will search for scripts in the same directory named
XYZtest.py. Each such script should be a test suite that tests a
module through PyUnit. (As of Python 2.1, PyUnit is included in
the standard library as "unittest".) This script will aggregate all
found test suites into one big test suite and run them all at once.
"""
import sys, os, re, unittest
def regressionTest():
path = os.path.abspath(os.path.dirname(sys.argv[0]))
files = os.listdir(path)
test = re.compile("test\.py$", re.IGNORECASE)
files = filter(test.search, files)
filenameToModuleName = lambda f: os.path.splitext(f)[0]
moduleNames = map(filenameToModuleName, files)
modules = map(__import__, moduleNames)
load = unittest.defaultTestLoader.loadTestsFromModule
return unittest.TestSuite(map(load, modules))
if __name__ == "__main__":
unittest.main(defaultTest="regressionTest")
À l'exécution de ce script dans le même répertoire que le reste
des scripts d'exemple de ce livre, l'ensemble des tests unitaires,
nommés moduletest.py,
sont trouvés, exécutés comme un seul test, réussissant ou échouant
ensemble.
Exemple 16.2. Exemple de sortie de regression.py
[you@localhost py]$ python regression.py -v
help should fail with no object ... ok
help should return known result for apihelper ... ok
help should honor collapse argument ... ok
help should honor spacing argument ... ok
buildConnectionString should fail with list input ... ok
buildConnectionString should fail with string input ... ok
buildConnectionString should fail with tuple input ... ok
buildConnectionString handles empty dictionary ... ok
buildConnectionString returns known result with known input ... ok
fromRoman should only accept uppercase input ... ok
toRoman should always return uppercase ... ok
fromRoman should fail with blank string ... ok
fromRoman should fail with malformed antecedents ... ok
fromRoman should fail with repeated pairs of numerals ... ok
fromRoman should fail with too many repeated numerals ... ok
fromRoman should give known result with known input ... ok
toRoman should give known result with known input ... ok
fromRoman(toRoman(n))==n for all n ... ok
toRoman should fail with non-integer input ... ok
toRoman should fail with negative input ... ok
toRoman should fail with large input ... ok
toRoman should fail with 0 input ... ok
kgp a ref test ... ok
kgp b ref test ... ok
kgp c ref test ... ok
kgp d ref test ... ok
kgp e ref test ... ok
kgp f ref test ... ok
kgp g ref test ... ok
----------------------------------------------------------------------
Ran 29 tests in 2.799s
OK