16.7. 全部放在一起

你已经学习了足够的知识,现在来分析本章样例代码的前七行:读取一个目录并从中导入选定的模块。

例 16.16. regressionTest 函数


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))          

让我们一行行交互地看。假定当前目录是 c:\diveintopython\py,其中有包含本章脚本在内的本书众多样例。正如在 第 16.2 节 “找到路径” 中所见,脚本目录将存于 path 变量,因此让我们从这里开始以实打实的代码起步。

例 16.17. 步骤 1:获得所有文件

>>> 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']
files 是由脚本所在目录的所有文件和目录构成的列表。(如果你已经运行了其中的一些样例,可能还会看到一些 .pyc 文件。)

例 16.18. 步骤 2:找到你关注的多个文件

>>> test = re.compile("test\.py$", re.IGNORECASE)           
>>> files = filter(test.search, files)                      
>>> files                                                   
['apihelpertest.py', 'kgptest.py', 'odbchelpertest.py', 'pluraltest.py', 'romantest.py']
这个正则表达式将匹配以 test.py 结尾的任意字符串。注意,你必须转义这个点号,因为正则表达式中的点号通常意味着 “匹配任意单字符”,但是你实际上想匹配的事一个真正的点号。
被编译的正则表达式就像一个函数,因此你可以用它来过滤文件和目录构成的大列表,找寻符合正则表达式的所有元素。
剩下的是一个单元测试脚本列表,因为只有它们是形如 SOMETHINGtest.py 的文件。

例 16.19. 步骤 3:映射文件名到模块名

>>> 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']
正如你在 第 4.7 节 “使用 lambda 函数” 中所见,lambda 快餐式地创建内联单行函数。这里应用你在 例 6.17 “分割路径名” 中已经见过的,标准库的 os.path.splitext 将一个带有扩展名的文件名返回成只包含文件名称的那部分。
filenameToModuleName 是一个函数。lambda 函数并不比你以 def 语句定义的普通函数神奇。你可以如其他函数一样地调用 filenameToModuleName,它也将如你所愿:从参数中剔除扩展名。
现在你可以通过 map 把这个函数应用于单元测试文件列表中的每一个文件。
结果当然如你所愿:以指代模块的字符串构成的一个列表。

例 16.20. 步骤 4:映射模块名到模块

>>> 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'>
正如你在 第 16.6 节 “动态导入模块” 中所见,你可以通过 map__import__ 的协同工作,将模块名 (字符串) 映射到实际的模块 (像其他模块一样可以被调用和使用)。
modules 现在是一个模块列表,其中的模块和其他模块一样。
该列表的最后一个模块 romantest 模块,和通过 import romantest 导入的模块完全等价。

例 16.21. 步骤 5:将模块载入测试套件

>>> 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)) 
模块对象的存在,时时彩计划软件公式:使你不但可以像其他模块一样地使用它们;通过类的实例化和函数的调用,你还可以内省模块,从而弄清楚已经有了那些类和函数。这正是 loadTestsFromModule 方法的工作:内省每一个模块并为每个模块返回一个 unittest.TestSuite 对象。每个 TestSuite (测试套件) 对象都包含一个 TestCase 对象的列表,每个对象对应着你的模块中的一个测试方法。
最后,你将TestSuite列表封装成一个更大的测试套件。unittest 模块会很自如地遍历嵌套于测试套件中的树状结构,最后深入到独立测试方法,一个个加以运行并判断通过或是失败。

自省过程是 unittest 模块经常为我们做的一项工作。还记得我们的独立测试模块仅仅调用了看似神奇的 unittest.main() 函数就大刀阔斧地完成了全部工作吗?unittest.main() 实际上创建了一个 unittest.TestProgram 的实例,而这个实例实际上创建了一个 unittest.defaultTestLoader 的实例并以调用它的模块启动它。 (如果你不给出,如何知道调用它的模块是哪一个?通过使用同样神奇的 __import__('__main__') 命令,动态导入正在运行的模块。我可以就 unittest 模块中使用的所有技巧和技术写一本书,但那样我就没法写完这本了。)

例 16.22. 步骤 6:告知 unittest 使用你的测试套件


if __name__ == "__main__":                   
    unittest.main(defaultTest="regressionTest") 
在不使用 unittest 模块来为我们做这一切的神奇工作的情况下,你实际上已自己做到了。你已经创建了一个自己就能导入模块、调用 unittest.defaultTestLoader 并封装于一个测试套件的 regressionTest 函数。现在你所要做的不是去寻找测试并以通用的方法构建一个测试套件,而是告诉 unittest 前面那些,它将调用 regressionTest 函数,而它会返回可以直接使用的 TestSuite
合乐时时彩平台注册 老时时彩一星技巧 江西时时彩到几点 助赢软件安卓版 汇华国际时时彩平台
江西时时彩定位杀一码 彩度神针时时彩软件 第七感时时彩软件lm0 重庆时时彩如何算单双 赠彩金的时时彩平台
兰州时时彩平台 功夫时时彩 合乐时时彩平台注册 万和城娱乐平台 最权威的时时彩平台
2017信誉棋牌平台排名 重庆时时彩定胆技巧 帝豪时时彩平台 凤凰时时彩平台代理 99娱乐平台代理
江西11选五走势图 河南快3三不同遗漏 黑龙江省36选7 重庆时时彩手机版 快3技巧稳赚
重庆时时彩开奖号码查询结果 快乐10分钟开奖直播 如何能让眼睛变大 时时彩破解版 海南体彩频道
排列三试机号今天 广东福利彩票36选7 五分彩计划软件 ocketii云南11选5遗漏 河北十一选五开奖结果公告
福彩3d历史开奖号码 辽宁福彩35选7下期预测 天津时时彩开奖号码中彩网 上海快三历史开奖号码 福建22选5走势图浙江风采