python模块 — 单元测试框架 unittest

一、快速入门

1、unittest介绍

unittest是Python内置的单元测试框架,不需要安装可以直接调用。其中几个核心概念如下:

Test Fixture:

  • 测试脚手架,用来完成测试前置处理,后置处理。如测试前的环境准备,测试完成后环境销毁。
  • 测试函数级别:setUp,tearDown
  • 测试类级别:setUpClass,tearDownClass

Test Case:

  • 测试用例, 一个测试用例是一个独立的测试单元,新建测试用例需要继承 unittest.TestCase。

Test Suite:

  • 测试套件,用来收集测试用例或者测试套件。suite = unittest.TestSuite()

Test Loader:

  • 测试加载器,用来将测试用例加载到测试套件中。unittest.TestLoader()

Test Runner:

  • 测试运行器,用来运行测试并输出测试结果。如将测试结果输出文本格式:unittest.TextTestRunner()

2、编写测试用例

新建测试用例需要继承 unittest.TestCase,测试用例以test*开头,一个单元编写一个测试用例。

(1)编写注册功能测试用例test_register.py如下:

"""
注册功能测试用例
"""

import unittest


class TestRegister(unittest.TestCase):

    def setUp(self) -> None:
        print('setUp:打开注册页面')

    def tearDown(self) -> None:
        print('tearDown:关闭注册页面')

    def test01(self):
        print('test01:注册成功用例')

    def test02(self):
        print('test02:注册失败用例')

(2)编写登录功能测试用例test_login.py如下:

"""
登录功能测试用例
"""

import unittest


class TestLogin(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        print('setUpClass:打开登录页面')

    @classmethod
    def tearDownClass(cls) -> None:
        print('tearDownClass:关闭登录页面')

    def test03(self):
        print('test03:登录成功用例')

    def test04(self):
        print('test04:登录失败用例')

(3)项目目录结构如下:

3、运行测试用例

项目根目录中,新建程序主入口run.py文件,运行测试用例并生成测试报告。这一步可以拆分成如下步骤:

(1)实例化一个测试套件

(2)加载测试用例到测试套件

(3)运行测试套件

(4)生成测试报告

"""
程序主入口

"""
import unittest


# 封装测试套件方法
def suite():
    # 实例化测试套件
    testsuite = unittest.TestSuite()

    # TestLoader测试加载器
    loader = unittest.TestLoader()
    tests = loader.discover(start_dir='testcases', pattern='test*.py')

    # 加载测试用例到测试套件
    testsuite.addTests(tests)

    return testsuite


# 运行测试套件
if __name__ == '__main__':
    suite = suite()
    # 测试运行器,生成文本格式测试报告
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

控制台打印日志详细程度参数 :verbosity

  • verbosity=0 (静默模式)::你只能获得总的测试用例数和总的结果。比如 总共100个 失败20 成功80
  • verbosity=1 (默认模式): 非常类似静默模式 只是在每个成功的用例前面有个“.” 每个失败的用例前面有个 “E”
  • verbosity=2 (详细模式):测试结果会显示每个测试用例的所有相关的信息

关于测试套件,测试加载器,测试运行器会在下文API中详细说明,为了快速入门,这里只要会初步使用就行。

项目目录结构如下:

运行main方法,注册功能的测试用例test_register.py,登录功能的测试用例test_login.py中的所有子用例都执行了。

4、使用测试套件加载测试用例

测试套件TestSuite对象的方法有addTest逐条加载测试用例(测试套件),addTests加载多条测试用例(测试套件)。也可以结合测试加载器TestLoader对象的方法一起用来加载多条测试用例。

项目根目录中,新建run_suite.py文件如下,其中列举了7种加载测试用例的方法。

"""
测试套件加载测试用例的方法

"""
import unittest
from testcases import test_register, test_login


# addTest(test) 添加一个TestCase或者TestSuite到测试套件中,test必须是已经实例化的对象。
# 加载单个测试用例
def suite1():
    testsuite = unittest.TestSuite()
    test = test_register.TestRegister('test01')
    testsuite.addTest(test)
    return testsuite


# 逐个加载测试用例
def suite11():
    testsuite = unittest.TestSuite()
    test1 = test_register.TestRegister('test01')
    test2 = test_register.TestRegister('test02')
    testsuite.addTest(test1)
    testsuite.addTest(test2)
    return testsuite


# 加载单个测试套件
def suite12():
    testsuite = unittest.TestSuite()
    test2 = test_register.TestRegister('test02')
    testsuite.addTest(suite1())
    testsuite.addTest(test2)
    return testsuite


# addTests(tests) 添加多个TestCase或者TestSuite到测试套件中,tests必须是已经实例化,并且可迭代的对象.
# 加载多个测试用例
def suite2():
    testsuite = unittest.TestSuite()
    tests = [test_login.TestLogin('test03'), test_login.TestLogin('test04')]
    testsuite.addTests(tests)
    return testsuite


# 加载多个测试套件
def suite21():
    testsuite = unittest.TestSuite()
    tests = [suite1(), suite2()]
    testsuite.addTests(tests)
    return testsuite


# TestLoader() 测试加载器
# loadTestsFromTestCase(testCaseClass) 加载某个测试类中的所有测试用例
def suite3():
    testsuite = unittest.TestSuite()
    loader = unittest.TestLoader()
    tests = loader.loadTestsFromTestCase(test_register.TestRegister)
    testsuite.addTests(tests)
    return testsuite


# loadTestsFromModule(module) 加载某个模块中的所有测试用例
def suite4():
    testsuite = unittest.TestSuite()
    loader = unittest.TestLoader()
    tests = loader.loadTestsFromModule(test_register)
    testsuite.addTests(tests)
    return testsuite


# loadTestsFromName(name) 根据给定的字符串来获取测试用例套件,字符串可以是模块名,测试类名,测试类中的测试方法名
def suite5():
    testsuite = unittest.TestSuite()
    loader = unittest.TestLoader()
    tests = loader.loadTestsFromName('testcases.test_register')
    testsuite.addTests(tests)
    return testsuite


# loadTestsFromNames(names) 与name功能相同,只不过接受的是字符串列表
def suite6():
    testsuite = unittest.TestSuite()
    loader = unittest.TestLoader()
    tests = loader.loadTestsFromNames(['testcases.test_register', 'testcases.test_login'])
    testsuite.addTests(tests)
    return testsuite


# discover(start_dir, pattern='test*.py') 根据指定的目录和匹配规则,递归所有子目录模糊查询加载测试用例
def suite7():
    testsuite = unittest.TestSuite()
    loader = unittest.TestLoader()
    tests = loader.discover(start_dir='./testcases', pattern='test*.py')
    testsuite.addTests(tests)
    return testsuite


# 运行测试套件
if __name__ == '__main__':
    suite = suite1()
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

5、生成HTML格式的测试报告

测试运行器TextTestRunner以文本的格式输出测试结果,不方便展示我们测试成果,下面介绍2种方法生成HTML格式的测试报告。

(1)HTMLTestRunner

第三方插件,可将测试结果保存成html文件,从PyPI官网下载的原文件不能直接使用,原文件是基于Python2的版本,需要修改成兼容Python3才行,建议直接百度一份别人修改好后可以使用的文件。

(2)BeautifulReport

第三方插件,可将测试结果保存成html文件,从PyPI官网下载后可以直接使用,推荐使用。

项目根目录下新建run_report.py文件如下:

"""
生成测试报告的几种方式

"""
import unittest
# import HTMLTestRunner
from BeautifulReport import BeautifulReport


def suite():
    testsuite = unittest.TestSuite()
    loader = unittest.TestLoader()
    tests = loader.discover(start_dir='./testcases', pattern='test*.py')
    testsuite.addTests(tests)
    return testsuite


# TextTestRunner
# if __name__ == '__main__':
#     suite = suite()
#     with open(file='./report/report.txt', mode='a') as file:
#         runner = unittest.TextTestRunner(verbosity=2, stream=file)
#         runner.run(suite)

# HTMLTestRunner
# if __name__ == '__main__':
#     suite = suite()
#     with open(file='HTMLReport.html', mode='w') as file:
#         runner = HTMLTestRunner.HTMLTestRunner(stream=file, verbosity=2)
#         runner.run(suite)

# BeautifulReport
if __name__ == '__main__':
    suite = suite()
    result = BeautifulReport(suite)
    result.report(report_dir='./report', filename='breport.html', description='注册和登录功能测试报告')

运行run_report.py文件,生成测试报告如下:

 使用chrome浏览器打开测试报告如下:

6、命令行模式运行

上文说的都是通过main方法来运行测试用例,unittest也可以通过命令行模式运行测试用例。

几种常见的命令如下:

  • python -m unittest:探索性测试,默认搜索当前目录及其子目录中,所有test*.py模式的测试文件。
  • python -m unittest test_module1
  • python -m unittest test_module1 test_module2
  • python -m unittest test_module.TestClass
  • python -m unittest test_module.TestClass.test_method
  • python -m unittest tests/test_something.py

以上文的注册功能测试用例test_register.py,登录功测试用例test_login.py为例,打开Terminal终端,进入路径testcases中,输入命令:python -m unittest

7、跳过测试(测试函数/测试类)

@unittest.skip(reason),跳过被此装饰器装饰的测试。 reason 为测试被跳过的原因。

@unittest.skipIf(condition, reason),当 condition 为真时,跳过被装饰的测试。

@unittest.skipUnless(condition, reason),跳过被装饰的测试,除非 condition 为真。

TestCase.skipTest(),直接跳过测试,抛出SkipTest异常。

@unittest.expectedFailure,标记测试用例预期失败。

8、注意事项

测试用例执行顺序:根据ASCII码的顺序加载,数字与字母的顺序为:0-9,A-Z,a-z。

若 setUp() 方法引发异常,测试框架会认为测试发生了错误,因此测试方法不会被运行。

若 setUp() 成功运行,无论测试方法是否成功,都会运行 tearDown() 。

被跳过的测试的 setUp() 和 tearDown() 不会被运行。

被跳过的类的 setUpClass() 和 tearDownClass() 不会被运行。

被跳过的模组的 setUpModule() 和 tearDownModule() 不会被运行。

二、API

1、TestCase 测试用例

setUp:前置处理,函数级别,此方法会在调用每个测试函数之前被调用。除了 AssertionError 或 SkipTest,此方法所引发的任何异常都将被视为错误而非测试失败。默认不做任何处理。

tearDown:后置处理,函数级别,此方法会在调用每个测试函数之后被调用。无论测试是否成功,只要setup执行成功,都会执行该方法。除了 AssertionError 或 SkipTest,此方法所引发的任何异常都将被视为错误而非测试失败。默认不做任何处理。

setUpClass:前置处理,测试类级别,在一个单独类中的测试运行之前被调用的类方法。使用@classmethod装饰器。

tearDownClass:后置处理,测试类级别,在一个单独类的测试完成运行之后被调用的类方法。使用@classmethod装饰器。

run:运行测试,并将测试结果保存到TestResult对象中。

skipTest:在测试方法或 setUp() 执行期间调用此方法将跳过当前测试。

fail:使用给定消息立即失败。

id:返回测试方法的完整名称,包括模块名和类名。

subTest:上下文管理器

断言:assertEqua,assertNotEqual,assertTrue,assertFalse,……

异常:assertRaises,assertWarns,assertLogs,……

2、TestSuite 测试套件

addTest(test):添加一个TestCase或者TestSuite到测试套件中,test必须是已经实例化的对象。

addTests(tests):添加多个TestCase或者TestSuite到测试套件中,tests必须是已经实例化,并且可迭代的对象。

run(result):运行测试,并将测试结果保存到TestResult对象中。

3、TestLoader 测试加载器

loadTestsFromTestCase(testCaseClass):加载某个测试类中的所有测试用例。

loadTestsFromModule(module) :加载某个模块中的所有测试用例。

loadTestsFromName(name) :根据给定的字符串来获取测试用例套件,字符串可以是模块名,测试类名,测试类中的测试方法名。

loadTestsFromNames(names) :与name功能相同,只不过接受的是字符串列表

discover(start_dir, pattern='test*.py'):根据指定的目录和匹配规则,递归所有子目录模糊查询加载测试用例。

4、TestResult 测试结果

用来存储TestCase.run(), TestSuite.run() 的测试结果到result中,可以通过扩展这个基类的方式自定义测试报告。

如:HTMLTestRunner

5、TextTestRunner 测试运行器

 run(test):存储测试结果,并以文本的形式输出,test可以是test case 或者 test suite


reference:

unittest — Unit testing framework — Python 3.8.13 documentation

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值