Python下unittest框架的核心组件使用

本文详细介绍了unittest框架的核心组件、测试流程、测试用例编写方法、断言使用、异常处理等内容,并展示了如何利用TestSuite进行测试用例的收集以及数据驱动的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        前言:在接口/UI自动化中,unittest框架或多或少也听到过,流行的框架我们需要重点去学习及掌握,接下来就一起来学习下吧

 

一、unittest核心组件

1、TestCase:测试用例类,用来定义测试用例函数的

2、TestSuite:测试套件,用来收集测试用例的

3、TestRunner:测试用例运行类,用来执行测试用例的,以测试套件维度去执行

4、TestFixture:测试脚手架,前置条件,后置处理

二、测试流程--unittest你是如何做自动化测试的

1、TestCase:先定义测试用例类,在测试用例类中写测试方法

2、TestSuite:收集你要执行的测试用例类或者文件里面的测试方法,放到测试套件

3、TestRunner:将收集好的测试条件放到测试用例运行器去执行,并收集测试结果

4、TestFixture:做好前置条件和后置处理

三、如何写测试用例(TestCase)

1、导入模块:import unittest,继承TestCase类

2、定义一个测试用例类:类名称必须Test开头

3、定义测试方法:测试方法也必须是test开头,必须写在测试用例类里面

4、框架执行入口:unittest.main(),自动收集当前py文件的测试用例,然后执行

四、测试用例包含哪些东西

1、前置条件(如果没有可以不写):sql语句执行、数据库连接创建、工具类的实例化

2、测试步骤(业务逻辑):数据替换、数据驱动

3、测试结果断言:响应结果断言、数据库数据断言

4、后置处理(如果没有可以不写):数据清理、数据库连接关闭

五、前置后置(TestFixture)

自动化中什么是前置后置?

答:前置:sql语句执行、数据库连接创建、工具类的实例化
       后置:数据清理、数据库连接关闭

a) 类级别(以类级别的运行)

一、类级别(以类级别的运行)
前置:测试用例执行之前执行一次(当前测试用例类) ——   
     @classmethod
    def setUpClass(cls) -> None:(固定写法,必须加@classmethod,源码就是加了)

后置:测试用例执行之后执行一次(当前测试用例类)——
	    @classmethod
    def tearDownClass(cls) -> None: (固定写法,必须加@classmethod,源码就是加了)


解释:
类级别的前后置就是,比如你的测试用例有3条,那就每一条用例都会去执行前后置,
执行顺序:前置,第一条用例,第二条用例,后置

a) 示例:类级别

#例子:

class Test_class_setup(unittest.TestCase): #前置后置都需要类继承unittest.TestCase

    @classmethod      #类级别的前置 必须加@classmethod
    def setUpClass(cls) -> None:
        print("我是类级别的前置")

    @classmethod
    def tearDownClass(cls) -> None:  #类级别的后置 必须加@classmethod 这里后置放哪里都可以 你也可以放到最后一条用例后面去。
        print("我是类级别的后置")

    def test_01(self):
        print("用例001")

    def test_02(self):
        print("用例002")

    def test_03(self):
        print("用例003")



if __name__ == '__main__':
    unittest.main()

b) 函数级别(以函数级别的运行)

二、函数级别(以函数级别的运行)
前置:每个测试用例执行之前执行一次 ——    def setUp(self) -> None: (固定写法)
后置:每个测试用例执行之后执行一次 ——     def tearDown(self) -> None:(固定写法)

解释:
函数级别的前后置就是,比如你的测试用例有3条,那就每一条用例都会去执行前后置,
执行顺序:前置,第一条用例,后置;前置 ,第二条用例,后置

b) 示例:函数级别

例子:


class Test_setp(unittest.TestCase): #前置后置都需要类继承unittest.TestCase

    def setUp(self) -> None:#这里-> None是表示前置是没有返回值的
        print("我是函数级别的前置")

    def test_01(self): #中间可以放测试用例
        print("我是测试用例01")

    def tearDown(self) -> None:#这里-> None是表示后置是没有返回值的
        print("我是函数级别的后置")

if __name__ == '__main__':
    unittest.main()

六、前置后置(TestFixture)

1、用例执行按照Ascii码顺序:0-9<A-Z<a-z

 

#打印对应字符的ascii码
print(ord("a"))  #97

#将ascii转换为对应的字符
print(chr(102))

七、用例断言(继承TestCase类的断言方法)

断言的特点:
1、unittest以程序运行过程中是否抛出异常来判断用例是否执行成功
2、如果断言失败程序会抛出异常,框架就会把这个用例标记为失败
3、只要你的程序中执行出现了其他异常,框架也会去捕获异常并将用例标记为失败

例:self.assertEqual(1,1) 断言是否相等

unitest常见断言:

常见断言(unitest独有,pytest没有):

    1、assertEqual(a, b)
    # a == b
    '''self.assertEqual(1 + 1, 2)#实际结果、预期结果是否相等'''


    2、assertNotEqual(a, b)
    # a != b
    '''self.assertNotEqual(1, 2)#实际结果、预期结果是否不相等'''


    3、assertTrue(x)
    # bool(x) is True
    '''self.assertTrue([1,2,3])#任何为真的表达式 非0 非空 true'''


    4、assertFalse(x)
    # bool(x) is False
    '''self.assertFalse(0)#任何为假的表达式 0 空 false'''


    5、assertIs(a, b)
    # a is b
    '''self.assertIs(1,1)#is身份运算符,a 是和 b引用自同一个对象'''


    6、assertIsNot(a, b)
    # a is not b
    '''self.assertIsNot(1,2)#is not身份运算符,a 和 b不是引用自同一个对象'''


    7、assertIn(a, b)
    # a in b
    '''self.assertIn(1,[1,2,3])#in成员运算符,a是b中一员,a在b中'''


    8、assertNotIn(a, b)
    # a not in b
    '''self.assertNotIn(2,[1,3,4])#in成员运算符,a不是b中一员,a不在b中'''


    9、assertIsInstance(a, b)
    # isinstance(a, b)
    '''self.assertIsInstance(123,int)#isinstance判断一个对象是否属于某个类或类型'''


    10、assertNotIsInstance(a, b)
    # not isinstance(a, b)
    '''self.assertNotIsInstance([1,2,3],dict)#not isinstance判断一个对象不是否属于某个类或类型'''


    11、assertGreater(a, b)
    # a > b
    '''self.assertGreater(5,2)#Greater判断a是否大于b'''


    12、assertGreaterEqual(a, b)
    # a >= b
    '''self.assertGreaterEqual(5,5)#GreaterEqual判断a是否大于等于b'''


    13、assertLess(a, b)
    # a < b
    '''self.assertLess(1,4)#less判断a是否小于b'''


    14、assertLessEqual(a, b)
    # a <= b
    self.assertLessEqual(2,2)#less判断a是否小于等于b

unitest断言示例:

例子:

测试用例中:

    def test_03(self):
        print("用例003")
        self.assertEqual(1+1,3)#实际结果、预期结果是否相等,如:1+1的值  是否 等于3——这里错了后,会报错,用例执行就会不通过

八、异常捕获与异常抛出

try...except 捕获到的异常一定要抛出来给框架,否则框架就会认为用例执行成功的

异常捕获示例:

2、手动抛异常:raise AssertionError(e)


    def test_03(self):
        try:
            time.sleep(1)
            self.assertEqual(1,2)
            print("测试用例03")
        except Exception as e:
            # print("错误原因:",e)
            raise AssertionError(e)



    def test_03(self):
        try:
            self.assertEqual(1,2)
            print("用例003")
        except Exception as  e:
            raise AssertionError(e)

九、用例的收集(TestSuite)

a) 测试用例维度【了解】

添加一个测试用例
suite.addTest(TestDemo("test_04"))

添加多个测试用例
tests = [TestDemo("test_04"),TestDemo("test_02")]
suite.addTests(tests)

a) 示例:测试用例维度

添加单条用例:

from day16.unnitest_demo1 import Test_class_setup #先导入测试用例
import  unittest#导入unitest库
suite = unittest.TestSuite() #创建测试套件进行收集用例
suite.addTest(Test_class_setup("test_01")) #添加测试用例到套件内,这里是测试用例为单位
run_now = unittest.TextTestRunner() #创建执行器
run_now.run(suite) #执行器中添加测试套件后 进行运行




添加多条用例:

from day16.unnitest_demo1 import Test_class_setup #先导入测试用例
import  unittest#导入unitest库
suite = unittest.TestSuite() #创建测试套件进行收集用例

case = [Test_class_setup("test_01"),Test_class_setup("test_02")] #多条测试用例,用[]装起来也可以
suite.addTests(case) # 多条用addTests
run_now = unittest.TextTestRunner() #创建执行器
run_now.run(suite) #执行器中添加测试套件后 进行运行

b) 测试类维度【了解】

添加某个测试类(类里面所有的测试用例都会被执行)
suite.addTest(unittest.makeSuite(TestDemo))

当只要执行py文件中多个测试用例中的几个,而不是全部执行时,那么使用testsuite的addtest方法加载指定的测试用例

当执行所有的py文件中的所有的测试用例时,那么使用TestLoader

b) 示例:测试类维度

添加测试类级别的用例:

from day17.wjh_test import Test_wjh
import unittest

suite = unittest.TestSuite() #实施例套件
test_case  = unittest.TestLoader().loadTestsFromTestCase(Test_wjh) 
#用这个方法,Python3不能用unittest.makeSuite(TestDemo)
#TestLoader:可以从指定目录查找指定的py文件中的所有测试用例,自动加载到TestSuite中

suite.addTest(test_case)
run1 = unittest.TextTestRunner()
run1.run(suite)

c) 模块为维度【掌握】

start_dir:测试文件目录
pattern='test*.py':测试用例文件名称,默认以test开头的py文件
case_dir = os.path.dirname(__file__)
suite = unittest.defaultTestLoader.discover(start_dir=case_dir)#指定某个目录下的某一类py文件进行运行,且运行所有测试用例

c) 示例:模块为维度

添加测试模块(用例文件)维度的用例————重点重点重点:


# 3、模块为维度【掌握】
# start_dir:测试文件目录
# pattern='test*.py':测试用例文件名称,默认以test开头的py文件
# case_dir = os.path.dirname(__file__)
# suite = unittest.defaultTestLoader.discover(start_dir=case_dir)

import  os
from day17.wjh_test import Test_wjh #导入测试用例
from day17.wjh_test import Test_wjh01#导入测试用例
import unittest

case_dir = os.path.dirname(__file__) #当前目录路径
suite = unittest.defaultTestLoader.discover(start_dir=case_dir,pattern='wjh_start*.py')
#start_dir是函数中的参数,指:start_dir
#pattern是函数中的参数,指的:如(pattern='test*.py':测试用例文件名称,默认以test开头的py文件)
#默认可以不加pattern的参数,如果不加。他就默认找目录中 test文件开头py文件中的测试用例执行

run1 = unittest.TextTestRunner()#TextTestRunner执行的是TestSuite
run1.run(suite)

c) TextTestRunner  和 TestRunner()  区别

TextTestRunner  和 TestRunner()  区别,因为这里很多人以为这两者都是unitest的执行器

TextTestRunner:是执行TestSuite,也就是测试套件的用例
TestRunner():执行生成测试报告

十、数据驱动:DDT

数据驱动

一、什么叫数据驱动?
1、业务流程是固定的,变化的是业务中的数据
2、使用场景:业务流程一样,只是请求数据不一样

准备工作:

安装ddt(unitest自带的ddt驱动方式)
pip install ddt

安装ddt(unittestreport第三库(木森大佬写的))
pip install unittestreport

a)unitest自带的ddt驱动方式

unitest自带的ddt驱动方式——例子:


import unittest
from ddt import ddt,data #导入ddt和data

test_cases = [{"api":"/api/login","user":"admin"},{"api":"/api/login","user":"test"}] #列表嵌套字典

@ddt #语法糖,使用ddt装饰器
class Test_login(unittest.TestCase):#同样需要继承unittest.TestCase
    @data(*test_cases)  #这里@data()表示需要添加数据进去,@data(*test_cases) 之所以加*号,是因为要解包,test_cases是列表嵌套字典
    def test_01(self,data): #这里一定主要 需要把数据驱动的变量添加进来,比如这里的data
        print("驱动")
        print(data["api"])#这里随便插一句,所有运行时,鼠标光标放在类外面去,不然会报错,这是个大坑,unitest垃圾!



if __name__ == '__main__':
    unittest.main()

b)unittestreport第三库(木森大佬写的)驱动方式

unittestreport(森哥)三方库的数据驱动

import unittest
from unittestreport import ddt,list_data #list_data是这个库的专门名字,主要就是为了省去解包的步骤,下面我们有讲解

test_cases = [{"api":"/api/login","user":"admin"},{"api":"/api/login","user":"test"}] #列表嵌套字典

@ddt #语法糖,使用ddt装饰器
class Test_login(unittest.TestCase):#同样需要继承unittest.TestCase
    @list_data(test_cases)  #@list_data()表示需要添加数据进去,这里不需要再解包上面的数据,因为@list_data有解包动作
    def test_01(self,data): #这里一定主要 需要把数据驱动的变量添加进来,比如这里的data
        print("驱动")
        print(data["api"])#这里随便插一句,所有运行时,鼠标光标放在类外面去,不然会报错,这是个大坑,unitest垃圾!



if __name__ == '__main__':
    unittest.main()

十一、unittestreport测试报告,并发送邮件

a) unitest自带测试报告——不推荐,丑,不好用

1、BeautifulReport(unitest官网自带的报告)
      pip install BeautifulReport==0.1.3

b) unittestreport :木森自研(重点掌握)

   unittestreport 使用文档unittestreport 使用文档unittestreport 使用文档:https://unittestreport.readthedocs.io/en/latest/doc8_thread/
   安装unittestreport:pip install unittestreport

b) 示例:unittestreport

实例:

import unittest
from unittestreport import TestRunner#导入测试报告模块

case_dir = os.path.dirname(__file__) #当前目录路径
suite = unittest.defaultTestLoader.discover(start_dir=case_dir)#pattern='wjh_start*.py' #收集用例

runner = TestRunner(                           #实例化测试报告模块,填写相关信息
                 suite=suite,
                 filename="my_report.html",
                 report_dir="./reports",
                 title='测试报告',
                 tester='小阿卷',
                 desc="接口自动化项目测试报告",
                 templates=3
)
runner.run()
runner.send_email(
                  host="smtp.qq.com",
                  port=465,
                  user="123456@qq.com",
                  password="123123",
                  to_addrs=["123456@qq.com"]
)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值