You are here: Sommaire > Plongez au coeur de Python > Programmation fonctionnelle > Assembler les pièces | << >> | ||||
Plongez au coeur de PythonDe débutant à expert |
Vous en avez assez appris pour déconstruire les sept premières lignes du code d'exemple de ce chapitre : lire un répertoire et importer des modules sélectionnés parmi ceux qu'il contient.
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))
Regardons cela ligne par ligne. Supposons que le répertoire en cours est c:\diveintopython\py, qui contient les exemples du livre, y compris le script de ce chapitre. Comme vous l'avez vu à la Section 16.2, «Trouver le chemin», le répertoire du script est assigné à la variable path, commençons donc à cette étape.
>>> import sys, os, re, unittest >>> path = r'c:\diveintopython\py' >>> files = os.listdir(path) >>> files ['BaseHTMLProcessor.py', 'LICENSE.txt', 'apihelper.py', 'apihelpertest.py', 'argecho.py', 'autosize.py', 'builddialectexamples.py', 'dialect.py', 'fileinfo.py', 'fullpath.py', 'kgptest.py', 'makerealworddoc.py', 'odbchelper.py', 'odbchelpertest.py', 'parsephone.py', 'piglatin.py', 'plural.py', 'pluraltest.py', 'pyfontify.py', 'regression.py', 'roman.py', 'romantest.py', 'uncurly.py', 'unicode2koi8r.py', 'urllister.py', 'kgp', 'plural', 'roman', 'colorize.py']
>>> test = re.compile("test\.py$", re.IGNORECASE) >>> files = filter(test.search, files) >>> files ['apihelpertest.py', 'kgptest.py', 'odbchelpertest.py', 'pluraltest.py', 'romantest.py']
>>> filenameToModuleName = lambda f: os.path.splitext(f)[0] >>> filenameToModuleName('romantest.py') 'romantest' >>> filenameToModuleName('odchelpertest.py') 'odbchelpertest' >>> moduleNames = map(filenameToModuleName, files) >>> moduleNames ['apihelpertest', 'kgptest', 'odbchelpertest', 'pluraltest', 'romantest']
Comme vous l'avez vu à la Section 4.7, «Utiliser des fonctions lambda», lambda est une manière rapide de créer des fonctions incluses d'une ligne. Celle-ci prend un nom de fichier avec une extension et le retourne sans son extension en utilisant la fonction de la bibliothèque standard os.path.splitext que vous avez vu à l'Exemple 6.17, «Division de noms de chemins». | |
filenameToModuleName est une fonction. Il n'y a rien qui différencie les fonctions lambda des fonctions habituelles définies par l'instruction def. Nous pouvons appeler la fonction filenameToModuleName comme n'importe quelle autre et elle fait exactement ce que nous voulons qu'elle fasse : enlever l'extension du nom de fichier passé en argument. | |
Maintenant nous pouvons appliquer cette fonction à chaque nom de fichier de la liste de fichier de tests unitaires à l'aide de map. | |
Le résultat est bien ce que nous souhaitons : une liste de modules sous forme de chaînes. |
>>> modules = map(__import__, moduleNames) >>> modules [<module 'apihelpertest' from 'apihelpertest.py'>, <module 'kgptest' from 'kgptest.py'>, <module 'odbchelpertest' from 'odbchelpertest.py'>, <module 'pluraltest' from 'pluraltest.py'>, <module 'romantest' from 'romantest.py'>] >>> modules[-1] <module 'romantest' from 'romantest.py'>
Comme vous l'avez vu à la Section 16.6, «Importation dynamique de modules», nous pouvons utiliser map et __import__ pour transformer une liste de noms de modules (sous forme de chaînes) en une liste de modules (que nous pouvons appeler comme n'importe quel autre module). | |
modules est maintenant une liste de modules, totalement accessibles comme tout autre module. | |
Le dernier module de la liste est le module romantest, comme si nous avions écrit import romantest. |
>>> load = unittest.defaultTestLoader.loadTestsFromModule >>> map(load, modules) [<unittest.TestSuite tests=[ <unittest.TestSuite tests=[<apihelpertest.BadInput testMethod=testNoObject>]>, <unittest.TestSuite tests=[<apihelpertest.KnownValues testMethod=testApiHelper>]>, <unittest.TestSuite tests=[ <apihelpertest.ParamChecks testMethod=testCollapse>, <apihelpertest.ParamChecks testMethod=testSpacing>]>, ... ] ] >>> unittest.TestSuite(map(load, modules))
Ce processus d'introspection est ce que le module unittest fait d'habitude pour nous. Vous vous rappelez de cette fonction magique unittest.main() que nos modules de test appelaient pour démarrer le processus ? unittest.main() crée en fait une instance de unittest.TestProgram, qui crée à son tour une instance de unittest.defaultTestLoader et le charge avec le module appelant (comment obtient-il une référence au module appelant sans qu'on lui en donne une ? En utilisant une instruction tout aussi magique, __import__('__main__'), qui importe dynamiquement le module en cours d'exécution. Je pourrais écrire un livre sur tous les trucs et les techniques utilisé dans le module unittest, mais dans ce cas je ne finirais jamais celui-ci).
if __name__ == "__main__": unittest.main(defaultTest="regressionTest")
<< Importation dynamique de modules |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
Résumé >> |