【Python测试】unittest源码解析二----Test Discovery

python -m unittest discover /home/kortide "Atest.py"

上面是执行我放在桌面的Atest.py测试模块。

 

这里的-m什么意思呢?python -h说明如下:

 

-m mod : run library module as a script (terminates option list)

把库模块作为一个脚本来运行,当把unittest作为一个脚本来运行的时候,就会运行该文件夹下的__init__和__main__。

 

 

 

import sys
print sys.argv[0]
if sys.argv[0].endswith("__main__.py"):
    sys.argv[0] = "python -m unittest"

__unittest = True

from .main import main, TestProgram, USAGE_AS_MAIN
TestProgram.USAGE = USAGE_AS_MAIN

main(module=None)

 

运行到__main__.py时,打印sys.argv[0],/usr/lib/python2.7/unittest/__main__.py,正好是当前执行文件__main__.py的所在路径。(和C、C++一样)

最后同样会去调用main,并设置这时候的module=None。

 

 

    def parseArgs(self, argv):
        if len(argv) > 1 and argv[1].lower() == 'discover':
            self._do_discovery(argv[2:])
            return
    def _do_discovery(self, argv, Loader=None):
        if Loader is None:
            Loader = lambda: self.testLoader

        # handle command line args for test discovery
        self.progName = '%s discover' % self.progName
        import optparse
        parser = optparse.OptionParser()
        parser.prog = self.progName
        parser.add_option('-v', '--verbose', dest='verbose', default=False,
                          help='Verbose output', action='store_true')
        if self.failfast != False:
            parser.add_option('-f', '--failfast', dest='failfast', default=False,
                              help='Stop on first fail or error',
                              action='store_true')
        if self.catchbreak != False:
            parser.add_option('-c', '--catch', dest='catchbreak', default=False,
                              help='Catch ctrl-C and display results so far',
                              action='store_true')
        if self.buffer != False:
            parser.add_option('-b', '--buffer', dest='buffer', default=False,
                              help='Buffer stdout and stderr during tests',
                              action='store_true')
        parser.add_option('-s', '--start-directory', dest='start', default='.',
                          help="Directory to start discovery ('.' default)")
        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
                          help="Pattern to match tests ('test*.py' default)")
        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
                          help='Top level directory of project (defaults to start directory)')

        options, args = parser.parse_args(argv)
        if len(args) > 3:
            self.usageExit()

        for name, value in zip(('start', 'pattern', 'top'), args):
            setattr(options, name, value)

        # only set options from the parsing here
        # if they weren't set explicitly in the constructor
        if self.failfast is None:
            self.failfast = options.failfast
        if self.catchbreak is None:
            self.catchbreak = options.catchbreak
        if self.buffer is None:
            self.buffer = options.buffer

        if options.verbose:
            self.verbosity = 2

        start_dir = options.start
        pattern = options.pattern
        top_level_dir = options.top

        loader = Loader()
        self.test = loader.discover(start_dir, pattern, top_level_dir)

在_do_discovery中会导入optparse模块,在其中添加有效的参数。然后根据设定的有效参数去分析传入的参数,options, args = parser.parse_args(argv)。

然后再在for循环中设置分析出来的属性值:

 

        for name, value in zip(('start', 'pattern', 'top'), args):
            setattr(options, name, value)

 

最后再通过Loader根据设置好的属性去获取TestSuite类的一个对象。

 

loader.py -- def discover(self, start_dir, pattern='test*.py', top_level_dir=None)

 

        set_implicit_top = False
        if top_level_dir is None and self._top_level_dir is not None:
            # make top_level_dir optional if called from load_tests in a package
            top_level_dir = self._top_level_dir
        elif top_level_dir is None:
            set_implicit_top = True
            top_level_dir = start_dir

        top_level_dir = os.path.abspath(top_level_dir)


获取将要提取的TestSuite所在的顶层目录。然后把顶层目录加到sys.path中。

 

 

        is_not_importable = False
        if os.path.isdir(os.path.abspath(start_dir)):
            start_dir = os.path.abspath(start_dir)
            if start_dir != top_level_dir:
                is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))


判断传入的参数是否是一个目录文件,如果是,就获取start_dir的绝对路径和top_level_dir进行比较,如果不是top_level_dir,那么就判断该目录是否作为一个包,

 

判断依据就是是否存在__init__.py文件。举个例子说明下,在当前目录current下,存在One目录, One中存在很多*test.py,Two中存在subTwo目录,

根据上面的说明,如果你的top_level_dir = current,start_dir = One,那么One中就需要存在__init__.py,也就是把One做成一个包。否则后面会一起一个异常:

 

        if is_not_importable:
            raise ImportError('Start directory is not importable: %r' % start_dir)


最后在正确的start_dir下,搜索需要的测试用例列表,转换成TestSuite类型后返回。

 

 

        tests = list(self._find_tests(start_dir, pattern))
        return self.suiteClass(tests)

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值