网站优化

网站优化

Products

当前位置:首页 > 网站优化 >

单元测试工具(单元测试工具unittest)

GG网络技术分享 2025-03-18 16:05 1


python单元测试之unittest

一、unittest 框架

unittest架构

unittest是python自带的测试框架,是应该掌握的python基础技能。主要包括以下几个类:

TestCase 测试用例

建立此类的子类,内部建立以test开头方法,每个方法实现一个测试。

FunctionTestCase用于将已经有的测试方法,添加入unittest框架方式运行。

IsolatedAsyncioTestCase 为python3.8新增,适应异步协程测试。

TestSuite 测试集

测试用例的管理容器,按照加入测试集合的顺序执行测试。

TextTestRunner 运行器

测试的运行器,会返回TestResult。

TestResult 测试结果

记录测试的结果。TextTestResult,为TestResult 的具体实现,保存文本格式的结果。

TestLoader 测试加载器

用于测试用例的加载。unittest.defaultTestLoader为默认的加载器。

做一个比方,把TestCase当成子弹,TestSuite则相当于弹夹,TestLoader是向弹夹装子弹的装置,TextTestRunner则是手枪,TestResult 则是射击结果。

二、运行测试文件方式

运行环境为python工具virtualenv建立的虚拟环境

(a)python zagtest2.pyzagtest2.py不只有TestCase定义,还有自定义运行器部分

按照zagtest2.py中自定义的测试顺序运行,具体说明见后文。

(b)python -m unittest zagtest2.py

用unittest默认运行器,加载运行测试模块zagtest2.py (扩展名.py可以不要)(即使zagtest2.py中有自定义运行器也不生效)。

发现输出test_1在先,与上图不一致。这是unittest的默认运行顺序,按照测试方法名字符顺序。

(c)python -m unittest

unittest自动在当前目录下查找test开头.py文件(包括子目录,文件中定义有TestCase),用默认运行器运行其中的测试用例。

python -m unittest运行输出

运行目录中有两个以test开头文件

三、测试实例讲解

基本TestCase实例(zagtest1.py)

import unittest

class TestCase1(unittest.TestCase):

@classmethod

def setUpClass(self):

#此方法第一个运行。只运行一次,

#可以在此处实现如数据库建立,数据准备等操作

print(“execute setUpClass”)

def tearDownClass(self):

#此方法最后运行,只运行一次。

#可以在此处实现如数据清理,收尾工作

print(“execute tearDownClass”)

def setUp(self):

#下面每个test开头函数运行前都执行,

#可以在此处初始化测试对象

print(“execute setUp”)

def tearDown(self):

#下面每个test开头函数运行后都执行,

#可以在此处清除测试对象

print(“execute tearDown”)

def test_2(self):

“””默认测试顺序:函数名的字符顺序”””

print(‘execute test_2’)

def test_1(self):

“””每个测试函数,完成一个独立功能测试。

命名以test开头”””

print(‘execute test_1’)

if __name__ == ‘__main__’:

unittest.main() #以unittest默认方式运行测试

#默认参数:

#unittest.main(module=”__main__”,testLoader=unittest.defaultTestLoader)

可以尝试一下,按照a、b两种方式运行,运行结果应该是相同的。

指定顺序运行TestCase

以b方式运行测试文件zagtest1.py,可以看到测试顺序是先 输出了【execute test_1】,后输出【execute test_2】。

运行顺序与方法定义顺序不一样。这就是unittest默认的运行方式,根据test开头函数的字符顺序运行。下面的代码,通过定义TestSuite,自定义测试顺序。

………(代码同上文)

if __name__==”__main__”:

suite=unittest.TestSuite() #定义TestSuite

#向TestSuite中添加2个测试,格式为:

#TestCase类名(“测试方法名字”)

suite.addTest(TestCase1(“test_2”))

suite.addTest(TestCase1(“test_1”))

runner=unittest.TextTestRunner()

runner.run(suite)

以方式(a)运行,则先输出’execute test_2,再输出execute test_1,是按照定义的顺序。

以Loader加载测试,输出测试报告到HTML文件

推荐将测试组织为3种文件:测试目标、测试用例、测试运行文件。

测试目标(myOPs.py)

class MyOPs:

def __init__(self,x,y):

self.x=x

self.y=y

def zadd(self):

return self.x+self.y

def zmult(self):

return self.x*self.y

定义测试案例(testCaseMyOPs.py)

from myOPs import MyOPs

class TestCaseMyOPs(unittest.TestCase):

def setUpClass(cls) -> None:

print(“setUpClass”)

def tearDownClass(cls) -> None:

print(“tearDownClass”)

def setUp(self) -> None:

self.ops = MyOPs(2, 3)

print(“setUp”)

def tearDown(self) -> None:

self.ops=None

print(“tearDown”)

def test_zadd(self):

print(“test_zadd”)

self.assertEqual(self.ops.zadd(),4)

def test_zmult(self):

print(“test_zmult”)

self.assertEqual(self.ops.zmult(),6)

最后,建立测试运行文件(runTestMyOPs.py)

实验中使用了HTMLReport第三方模块(https://github.com/Rain0193/HTMLReport),输出测试结果到html文件。以python runTestMyOPs.py 方式运行。

import HTMLReport

from testCaseMyOPs import TestCaseMyOPs

if __name__==”__main__”: #注意:使用HTMLReport,必须加此判断

suite=unittest.TestSuite()

loader=unittest.TestLoader()

#从TestCase类中,加载定义的测试(2个)

suite.addTests(loader.loadTestsFromTestCase(TestCaseMyOPs))

result_file=”TestMyOPs_report.html”

runner=HTMLReport.TestRunner(result_file,title=”测试报告”,description=”加法与乘法测试”,

lang=”cn”)

runner.run(suite)

测试文件默认输出到report目录下,可以点击【失败】【通过】,查看报告细节。

四、pycharm中快速建立测试文件

class Car:

def __init__(self,type=”BMX”):

self.type=type

self.speed=0

def speed_up(self,new_speed):

self.speed = new_speed

def stop(self):

self.speed = 0

def show_msg(self):

return self.type+”:”+str(self.speed)

有一个待测试类Car,定义有3个可测试方法。在Car类名上,点击鼠标右键,如下图选择。

自动命名测试用例文件为test_Car.py,测试用例类为TestCar。

可以选择要测试的3个函数,生成Car类的测试用例文件。

pycharm默认的测试框架为unittest,也可选择其他测试框架。参考下图更改。

五、注意事项及默认规则

命名规则

以unittest命令行方式运行测试文件,默认把test*.py认为是TestCase文件;

TestCase定义文件中,默认把 test* 方法,当做测试函数(没有load_tests方法时);

[晕]千万别把文件名命名为unittest.py

测试标记

测试结果显示中会见到:

s 表示跳过一个测试

. 测试通过

F 测试未通过

E 表示测试中发生错误(比如除0,对象不存在等)

FunctionTestCase用于将未使用测试框架写的测试,纳入到unittest统一方式

“””随便写的测试代码”””

def sayHello():

return “hello”

def testSayHello():

assert sayHello()==”hello”

suite.addTest(FunctionTestCase(testSayHello))

#此测试可以添加到testsuite中测试独立方法

def showMsg(msg):

return “%s”%(msg)

def do_divide(a,b):

return a/b

def showTrue(flag):

return flag

class TestSomFunc(unittest.TestCase):

def testrun(self):

print(“testrun”)

self.assertEqual(“OK”,showMsg(“OK”))

self.assertNotEqual(“OK”,showMsg(“NO”))

self.assertTrue(do_divide(1,2))

self.assertIs(showTrue(False),False)

self.assertIs(int(do_divide(1,2)),1)

suite.addTest(TestSomFunc(“testrun”))

suite.addTest(FunctionTestCase(testSayHello)) #将FunctionTestCase加入

runner.run(suite)TestLoader自动查找测试的规则

在目录中运行python -m unittest,实现原理也就是内部运行loader.discover()查找TestCase。

def discover(self, start_dir, pattern=’test*.py’, top_level_dir=None)

start_dir:为搜索起始目录

pattern:认为什么样的文件中存储有TestCase

top_level_dir:默认为None,此时start_dir,即为当前项目的顶级位置(不是子目录)。

如start_dir为子目录,则此处需自行指定到项目的顶级位置。

discover会在当前目录(包括子目录),查找满足pattern的文件。

python中将一个文件称为一个module(模块)。将一个有__init__.py的目录称为一个package(包)。

如果模块或包中__init__.py文件,有load_tests方法,则由此方法返回测试TestSuite。否则,则查找模块中test开头的方法。

下面模块test_module.py中的load_tests方法实例,用TestLoader.loadTestsFromModule也是同理。

class TestCaseA(unittest.TestCase):

pass

class TestCaseB(unittest.TestCase):

def test_m(self):

class TestCaseC(unittest.TestCase):

def test_k(self):

def test_x(self):

test_cases=(TestCaseA,TestCaseB,TestCaseC)

def load_tests(loader,tests,pattern):

for test_class in test_cases:

tests=loader.loadTestFromTestCase(test_class)

suite.addTests(tests)

return suite

下面将介绍包__init__.py中的load_tests定义:

import os

def load_tests(loader,standard_tests,pattern):

“””

standard_tests: 代表顶层的TestSuite

this_dir=os.path.dirname(__file__)

package_tests=loader.discover(start_dir=this_dir,pattern=pattern) #查找当前包中的tests

standard_tests.addTests(package_tests) #添加到顶层的TestSuite

return standard_tests条件测试

unittest中,可以根据条件状况有选择的进行测试。下面代码名为 testCondition.py

import sys

__version__=1

class TestCaseSkips(unittest.TestCase):

@unittest.skip(“无条件跳过”)

def test_nothing(self):

print(“test_nothing”)

@unittest.skipUnless(sys.platform.startswith(“win”),”只支持windows”)

def test_win(self):

print(“test_win”)

@unittest.skipIf(__version__<3,\"版本太低\")

def test_version(self):

print(“test_version”)

python -m unittest testCondition.py

在win10下运行

一个s表示跳过一个测试 .表示测试通过(只test_win运行)。

TestCase类也可以添加跳过标记,如下例。

@unittest.skipUnless(sys.platform.startswith(“win”),”只支持windows”)

class MySkippedTestCase(unittest.TestCase):

def test_not_run(self):

python unittest的官方文档地址:

https://docs.python.org/3/library/unittest.html

本文如果对你有所帮助,希望能点赞支持。今后,会持续推出技术积累、实验笔记,感兴趣的话,可以关注!

标签:

提交需求或反馈

Demand feedback