unittest-30-框架整体运行过程分析-2

1、main() 重要参数说明

本人视频参考:DAA02_unittest_全面精讲_0401_main方法_defaultTest参数_哔哩哔哩_bilibili

各参数简要说明:
  • module:(str, 默认值:'__main__'):要运行测试的Python模块,默认值为“__main__”,代表当前模块,用于通过模块方式加载测试
  • defaultTest: (str, 默认值:None):如果指定了这个参数,unittest将只运行与这个参数匹配的测试集合。可以是一个类名或者方法名或者其列表,支持点号.连接来指定嵌套关系。
  • argv: (list, 默认值:None):命令行参数列表,用于解析和处理命令行选项
  • verbosity:(int,默认值:1):输出时是否显示详细信息。0表示仅显示失败信息;1是正常输出;大于1的数字会增加输出详细度。
  • testRunner: (unittest.runner.TestRunner, 默认值:None):负责运行测试的 TestRunner 类实例,用于运行测试并报告结果。默认使用unittest内置的TestRunner。
  • testLoader: (unittest.loader.TestLoader, 默认值:loader.defaultTestLoader):负责发现并加载测试的 TestLoader 类实例。默认情况下,使用unittest模块提供的标准测试加载器,它可以找到并组织模块中的测试类和测试方法。
  • exit: (bool, 默认值:True):当测试运行完成后是否退出程序。如果设置为True,则会在测试结束后调用sys.exit()函数,根据测试结果返回相应的退出代码。
  • failfast:(bool, 默认值:None):是否启用快速失败模式。如果设为True,那么当遇到第一个失败的测试时,测试程序将立即停止运行剩余的测试。
  • catchbreak: (bool, 默认值:None):是否捕获中断信号(如Ctrl+C)。如果设为True,在接收到中断信号时,会先显示已执行的测试结果再退出。
  • buffer: (bool, 默认值:None):控制是否缓冲stdout和stderr输出。如果设为True,在测试过程中对标准输出进行缓存,在每个测试结束后才显示。
  • warnings: (None 或 bool, 默认值:None):控制警告的处理方式。如果设为True,则将捕获并显示所有警告。未设置时,unittest可能会忽略某些警告。
  • tb_locals: (bool, 关键字参数,默认值:False):如果设为True,在输出的堆栈信息中将包含局部变量。这对于调试测试失败时查看错误发生时的上下文变量状态非常有用。

1.1、参数:verbosity

  • 默认值 = 1:运行结果不显示详细信息
  • 传入值 > 1:运行结果显示详细信息

1.2、参数:module

  • 需要运行测试的模块
  • 默认 “__mian__” 为当前模块
  • 可以传入:① 字符串类型模块名称;② 已经导入成功的模块对象
# 源码:D:\A0_Program\Python311\Lib\unittest\main.py - class TestProgram() - def __init__():

if isinstance(module, str):
    # 如果传入的是字符串,unittest 会先进行导入处理
    self.module = __import__(module)
    for part in module.split('.')[1:]:
        self.module = getattr(self.module, part)
else:
    # 如果传入的是已经导入好的模块对象,就直接使用
    self.module = module
试验:
# D:\A0_Project\Python\Temp\ex_10\test01.py
import unittest
class TestA(unittest.TestCase):
    def test_01(self):
        self.assertEqual(1, 1)

    def test_02(self):
        self.assertEqual(1, 1)

if __name__ == '__main__':
    # 如果运行当前模块,可以写成 module="__main__"
    # unittest.main(verbosity=2, module="test01")
    unittest.main(verbosity=2, module=__import__("__main__"))
运行结果:

1.3、参数:defaultTest

  • 指明默认要运行的测试
  • 从源码可见,其允许是 None、str、list 的类型
  • 注意:defaultTest 参数和 module 参数二者必须要匹配,即 defaultTest 传入的测试必须在 module 的模块内被定义。
# 源码:D:\A0_Program\Python311\Lib\unittest\main.py - class TestProgram() - def parseArgs():

elif self.defaultTest is None:
    # createTests will load tests from self.module
    self.testNames = None
elif isinstance(self.defaultTest, str):
    self.testNames = (self.defaultTest,)
else:
    self.testNames = list(self.defaultTest)

1.3.1、试验演示

分别进行演示试验:
import unittest

class TestA(unittest.TestCase):
    def test_01(self):
        self.assertEqual(1,1)

    def test_02(self):
        self.assertEqual(1,1)

def suite():
    suite = unittest.TestSuite()
    suite.addTest(TestA("test_01"))
    suite.addTest(TestA("test_02"))
    return suite

试验1 - 测试套件:

试验2 - 测试类:

试验3 - 测试方法:

试验4 - 使用一个列表:

1.3.2、易出现不匹配的小问题

如下执行 main() 方法时报错:
  • module 参数传入了 “test01.py” 模块文件
  • defaultTest 参数传入的却是 “test02.py” 模块下的测试方法
  • 以上二者没有匹配
  • 所以:应该是传入 module 参数指定的模块中的 “测试用例、测试方法、测试套件”

修改参数,重新匹配后再次执行成功

1.4、参数:argv

1.4.1、参数说明

参数说明:
  • 该参数是一个列表类型,主要用于存储命令行中传入的各类选项(如-v,-k等)
  • 该列表中的第一个参数,是框架自动添加的一个“程序名称”
先看下源码:

# 源码:D:\A0_Program\Python311\Lib\unittest\__main__.py
"""Main entry point"""
import sys
if sys.argv[0].endswith("__main__.py"):
    import os.path
    # We change sys.argv[0] to make help message more useful

    executable = os.path.basename(sys.executable)
    # 在这里框架自动为该参数的第一项增加了一个“程序的名称”
    sys.argv[0] = executable + " -m unittest"
    del os


# 源码:D:\A0_Program\Python311\Lib\unittest\main.py - class TestProgram():
def __init__()
    if argv is None:
        argv = sys.argv
    self.progName = os.path.basename(argv[0])

1.4.2、从命令行观察

调整原代码,增加打印语句,以便查看运行的中间结果:

通过命令行运行测试:
  • unittest 中使用的每个 “选项”、“选项值”、“tests参数值” 均被依次传入到 sys.argv 列表中
  • 列表中的第一项为框架自动添加的 “程序名称”

基于以上情况,在使用 main() 方法的时候,可以自己构造命令行参数的使用
# D:\A0_Project\Python\Temp\ex_10\test01.py

import unittest

class TestA(unittest.TestCase):
    def test_01(self):
        self.assertEqual(1, 1)

    def test_02(self):
        self.assertEqual(1, 1)


if __name__ == '__main__':
    # 此处用 argv 参数模拟了命令行的运行方式
    # 其中第一项随意起了一个名称
    unittest.main(argv=["my test name", "-v", "-k", "*02*", "TestA.test_01"])
    
执行结果:

1.4.3、还有不匹配的问题

以下试验出现了报错
  • argv 参数中模拟命令行的 tests 参数为 “test01”(即 test01.py 模块名称)
    • 以前提到过,命令行中的 tests 参数可以是 “模块名、测试类、测试方法、测试套”
  • 报错:当前模块中缺少属性 “test01”
    • 原因:还是二者没有匹配上,module 参数默认传入了 “__mian__”
    • 解决:手动将 module 参数置为空
调整代码:
  • 添加 module = None,使该参数置空
  • 重新运行:成功了

1.4.4、短路 defaultTest 参数

一个有趣的现象,如果同时使用了 defaultTest 和 argv 参数,则 defaultTest 中指定的测试将被 “短路” 掉而不执行

2、各参数的处理流程图

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值