前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >理解unittest测试框架(一)从入口说起

理解unittest测试框架(一)从入口说起

原创
作者头像
点点寒彬
发布2020-03-18 15:10:26
7780
发布2020-03-18 15:10:26
举报
文章被收录于专栏:用Python做测试用Python做测试

背景

作为一名测试人员,自动化测试框架可能是我们日常工作中使用的最多的东西了,以我为例,日常工作中天天打交道的框架就是unittest,深入理解unittest测试框架的原理,再工作中能避免我们踩到某些大坑。

启动方式

unittest的启动方式有两种

  • python -m unittest xxx.xxx
  • unittest.main()

第一种方式是以命令行的方式,也是我们正常执行用例和调试的时候使用的命令。

第二种方式是代码中编排执行测试用例的时候常用的方法。

命令行方式

使用命令行方式,首先得了解,这个-m 参数的作用。

官方文档说明了这个参数是按照模块化的方式执行。

代码语言:txt
复制
-m <module-name>
Search sys.path for the named module and execute its contents as the __main__ module.
Since the argument is a module name, you must not give a file extension (.py). The module-name should be a valid Python module name, but the implementation may not always enforce this (e.g. it may allow you to use a name that includes a hyphen).
Package names are also permitted. When a package name is supplied instead of a normal module, the interpreter will execute <pkg>.__main__ as the main module. This behaviour is deliberately similar to the handling of directories and zipfiles that are passed to the interpreter as the script argument.
Note This option cannot be used with built-in modules and extension modules written in C, since they do not have Python module files. However, it can still be used for precompiled modules, even if the original source file is not available.

从这里能看到几个关键点。

  • -m执行对象是一个包,而不是一个.py文件。
  • 使用-m的方式执行之后,python会把当前路径加到sys.path中。
  • 无法这样执行内建模块

一点一点来分析。

第一点

-m执行对象是一个包,而不是一个.py文件。

准确的说,-m执行的是这个包的__main__.py 文件。

例如,新建一个文件夹叫testmodule,在文件夹中创建__init__.py, __main__.py两个文件,在__main__.py中添加如下代码.

代码语言:txt
复制
print "test"

然后在文件夹上层执行:python -m testmodule,此时输出的内容是:

代码语言:txt
复制
$ python -m testmodule
test

所以命令行执行python -m unittest的时候,实际上是执行unittest包下的__main__.py

代码语言:txt
复制
# unittest中的源代码

import sys
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的时候,拿到的是TestProgram。从main中引入的main,其赋值对象是main = TestProgram,也就是说,从命令行来运行unittest框架,最终运行的类,是TestProgram

第二点

使用-m的方式执行之后,python会把当前路径加到sys.path

这点其实非常关键,在测试过程中,经常遇到的问题就是在pycharm运行的好好的,但是用命令行执行的时候就经常报错包不存在。

例如这样的结构:

代码语言:txt
复制
.
|____testmodel
| |______init__.py
| |______main__.py
|____util
| |______init__.py
| |____sum.py
|______init__.py
|____case
| |______init__.py
| |____test.py

case中的test.py中引用了util下面的sum方法。

代码语言:txt
复制
import unittest
from util import sum

class TestDemo(unittest.TestCase):
    def test_sum(self):
        result = sum.sum(1, 2)
        self.assertEqual(result, 3)

在根目录下执行就能正常运行

代码语言:txt
复制
$ python -m unittest case.test.TestDemo.test_sum
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

但是在case目录下执行就会报错找不到包。

我们把sys.path打出来就能看到。

代码语言:txt
复制
['', '/Library/Python/2.7/site-packages/six-1.12.0-py2.7.egg', '/Library/Python/2.7/site-packages/basedeal-0.0.2-py2.7.egg', '/Library/Python/2.7/site-packages', '/Library/Python/2.7/site-packages/M2Crypto-0.35.2-py2.7-macosx-10.14-intel.egg', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages', '/Library/Python/2.7/site-packages', '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python', '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC']

其中的第一个"" 就是命令所在的目录。如果直接执行python xxx.py则会将这个文件的路径添加到sys.path中,这个细微的区别不注意,就会导致经常出现python执行的时候经常找不到包。

函数方式

函数的方式启动时,运行代码是这样:

代码语言:txt
复制
import unittest

something....balabala

unittest.main()

运行的方法是unittest中的main方法,跟踪代码可以发现,main()方法对应的依然是TestProgram。这样就找到了整个测试框架的起点。

结语

可以看到,unittest不同的启动方式,最终走到的地方是一样的,下一篇,从TestProgram开始继续往下看。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 启动方式
  • 命令行方式
    • 第一点
      • 第二点
      • 函数方式
      • 结语
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档