基于Python的接口自动化unittest测试框架和ddt数据驱动详解

引言

在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条接口测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行,还有在运行大量的接口测试用例时测试数据如何管理和加载。针对测试用例加载以及执行控制,python语言提供了unittest单元测试框架,将测试用例编写在unittest框架下,使用该框架可以单个或者批量加载互不影响的用例执行及更灵活的执行控制,对于更好的进行测试数据的管理和加载,这里我们引入数据驱动的模块:ddt,测试数据和测试脚本的分离,通过ddt数据驱动来加载测试数据到测试用例脚本中,通常在接口自动化测试中会将unittest和ddt结合起来使用,从而实现测试用例脚本和测试数据的载入来完成测试的执行。下面来看看unittest框架和ddt这两个模块具体的应用。

一、unittest测试框架

unittest单元测试框架是python语言的一套标准模块,封装提供了诸多操作测试用例和用例加载、测试前置和场景恢复以及测试结果输出等一系列类和方法。

1.unittest框架中最核心四个组件概念:

(1)TestCase:测试用例类,编写测试用例脚本时需要继承该类,从而具有该类的属性和方法,一个TestCase实例就是一个测试用例,其中测试用例方法都以test开头。

(2)TestSuite:测试集,也就是测试用例的集合,用来组织用例。

(3)testrunner:用来执行测试用例,并返回测试用例的执行结果,可以用图形或者文本将测试结果形象地展现出来,HTMLTestRunner用来生成图形化的报告,TextTestRunner用来生成简单的文本测试结果。

(4)testfixure:测试夹件,主要用于测试用例的前置初始化和执行后的销毁。

2.testcase----测试用例

  • 新建一个的.py测试用例文件必须是test开头,如test_login.py,主要后续用于识别测试用例文件编写测试用例的类,必须继承unittest.TestCase,做为测试类
  • 测试类中用例的方法名称必须以test开头,用于识别测试用例数
  • 测试类中的用例执行顺序,按照以test开头的方法后的Ascill码顺序执行(0~9,A~Z,a~z)

3.testfixure----测试夹件

  • 也叫测试夹具,主要是用例前置的初始化以及执行后的销毁
  • 测试夹件提供两种方法,一种是类级别的:setup()和teardown(),一种是方法级别的:setUpClass()和tearDownClass()
  • 类级别的测试夹件,每一条测试用例执行之前与之后都要运行一次setup()和teardown();方法级别的测试夹件,所有测试用例执行之前到执行完成只运行一次setUpClass()和tearDownClass()

下面通过简单的代码示例看看TestCase与TestFixure的使用

(1)使用setup()和teardown(),创建test_666.py文件编辑如下代码:

import unittest

class test_unittest(unittest.TestCase):
 def setUp(self):
  print("测试环境初始化,开始执行setup")

 def tearDown(self):
  print("测试执行完成,运行teardown")
  print("------------------------------")
 def test_a(self):
  print("开始执行test_a用例")

 def test_A(self):
  print("开始执行test_A用例")

 def test_1(self):
  print("开始执行test_1用例")

 def notest_1(self):
  print("不执行notest_1用例")

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

执行后,输出如下:

在代码中我们编写了4个def用例方法,只执行了3个def,因为最后一个def不是test开头。可以看到每执行一个def用例,setup()和teardown()都会执行一次,其中按照执行顺序:test_1最先执行,test_A其后,test_a最后执行

(2)使用setUpClass()和tearDownClass()

对于setUpClass()和tearDownClass()我们只需将上面代码,稍微修改即可

import unittest

class test_unittest(unittest.TestCase):
 @classmethod
 def setUpClass(cls):
  print("测试环境初始化,开始执行setup")
 @classmethod
 def tearDownClass(cls):
  print("测试执行完成,运行teardown")
  print("------------------------------")
 def test_a(self):
  print("开始执行test_a用例")

 def test_A(self):
  print("开始执行test_A用例")

 def test_1(self):
  print("开始执行test_1用例")

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

 运行效果如下:

可以看到所有用例都执行完后,setUpClass()和tearDownClass()只运行了一次。因此在编写一个测试脚本时,里面写了多个测试用例,

这时我们希望的是所有用例执行完成后再销毁环境,这时使用setUpClass()tearDownClass()就比较好了。

3.TestSuite----测试集

unittest框架下提供了unittest.TestSuite()和unittest.TestLoader()类,这两个类下封装了加载用例的方法,用于加载测试用例到测试集中

(1)unittest.TestSuite()提供单个用例加载方法

addTest():单个用例加载,当然也可以将多个用例的方法名放入列表中添加到addTest()中,加载多条测试用例

(2)unittest.TestLoader()提供批量加载或发现用例的方法

loadTestsFromTestCase(测试类名):添加一个测试类
loadTestsFromModule(模块名):添加一个模块
discover(测试用例的所在目录):指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例

4.testrunner----测试运行

testrunner就是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式。
​html格式的就是HTMLTestRunner了,HTMLTestRunner是Python标准库的unittest框架的一个扩展,它可以生成一个直观清晰的HTML测试报告。使用的前提就是要下载HTMLTestRunner.py,下载完后放在python的安装目录下的scripts目录下即可。

通过代码示例看看testsuite和testrunner这两个组件的使用,上面的test_666.py用例文件我们已经写好了3条用例了,现在我们来加载这些用例

新建run_case.py文件,该文件和test_666.py文件放置在同一个包文件:test下,run_case.py文件编辑如下代码运行:

import unittest
from test.test_666 import test_unittest

# 单个用例加载
suite = unittest.TestSuite()
case1 = test_unittest('test_1')
case2 = test_unittest('test_a')
suite.addTest(case1)
suite.addTest(case2)
print(suite)
print("------------------")
# 批量用例加载
case_path = r"E:\api_test\test"
# 按文件路径加载,注意该文件为包文件即文件下有__init__.py
all_case = unittest.defaultTestLoader.discover(case_path,pattern="test_666*.py",top_level_dir=None)
all_case1 = unittest.defaultTestLoader.loadTestsFromTestCase(test_unittest) # 按类名称加载
print(all_case)
print("------------------")
print(all_case1)

 输出结果如下:

E:\api_test\Scripts\python.exe E:/api_test/test_bak/run_case.py
<unittest.suite.TestSuite tests=[<test.test_666.test_unittest testMethod=test_1>, <test.test_666.test_unittest testMethod=test_a>]>
------------------
<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<unittest.suite.TestSuite tests=[<test_666.test_unittest testMethod=test_1>, <test_666.test_unittest testMethod=test_A>, <test_666.test_unittest testMethod=test_a>]>]>]>
------------------
<unittest.suite.TestSuite tests=[<test.test_666.test_unittest testMethod=test_1>, <test.test_666.test_unittest testMethod=test_A>, <test.test_666.test_unittest testMethod=test_a>]>
 
Process finished with exit code 0

 通过unittest框架下提供的加载用例的诸多方法,我们就可以单个或者批量加载用例,后续可以将加载的用例集引入到HTMLTestRunner.py模块生成可视化的测试报告

5.assert----测试断言

无论是什么样的测试用例,最后都需要有用例执行后的验证,在接口自动化测试中我们执行完接口用例也需要验证断言用例执行是否满足我们的预期。unittest提供了丰富的断言方法,常见的断言如下表:

二、ddt数据驱动

  • @ddt:类的装饰器,继承的是TestCase类
  • @data():@data装饰符可以把参数当成测试数据,参数可以是单个值、列表、元祖、字典这些类型,用于输入测试数据
  • @unpack:分解数据标志,主要是把元祖和列表解析成多个参数
  • @file_data():输入文件,如json或者yaml类型文件

(1)输入简单的参数:单个值、列表、元祖、字典

import unittest
from ddt import data,unpack,ddt

@ddt
class myddt(unittest.TestCase):

 @data("123")    # 单个值
 def test1(self,testdata1):
  print(testdata1)
  print("------------------")

 @data([1,2,3],[4,5,6]) # 列表
 def test2(self,testdata2):
  print(testdata2)
  print("------------------")
"""
 @data((1, 2, 3))   # 元组
 def test2(self, testdata3):
  print(testdata3)
  print("------------------")

 @data({'zhangshan':1,'wangwu':2,'lisi':3}) # 字典
 def test2(self, testdata4):
  print(testdata4)
  print("------------------")
"""
if __name__ == '__main__':
  unittest.main()

 (2)使用@unpack对复杂数据结构,如元组、列表数据进行分解

代码示例:

import unittest
from ddt import data,unpack,ddt

@ddt
class myddt(unittest.TestCase):

 @data([1,2],[3,4]) # 列表
 @unpack
 def test2(self, testdata1,testdata2):
  print("拆解的第一个参数:",testdata1)
  print("拆解的第二个参数:", testdata2)
  print("------------------")

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

 运行后输出如下:

(3)使用@file_data()输入文件格式测试数据

编辑一个data.json的文件,代码示例:

import unittest
from ddt import file_data,ddt

@ddt
class myddt(unittest.TestCase):

 @file_data(r"E:\api_test\test\data.json")
 def test1(self, *value):
  print(value)

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

 通过ddt和unittest框架的结合就可以实现测试用例脚本编写、测试执行控制以及测试数据的批量加载,从而完成不同接口测试用例的批量执行和覆盖测试不同测试场景。

到此这篇关于基于Python的接口自动化unittest测试框架和ddt数据驱动详解的文章就介绍到这了,更多相关Python的接口自动化ddt数据驱动内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-01-25

python ddt数据驱动最简实例代码

在接口自动化测试中,往往一个接口的用例需要考虑 正确的.错误的.异常的.边界值等诸多情况,然后你需要写很多个同样代码,参数不同的用例.如果测试接口很多,不但需要写大量的代码,测试数据和代码柔合在一起,可维护性也会变的很差.数据驱动可以完美的将代码和测试数据分开,将代码进行分装,提高复用性,测试数据维护在本地文件或数据库. 使用python做接口自动化,首要任务是搭建一个自动化测试框架,其中unittest+ddt是一个不错的选择,下文主要介绍ddt在unittest下的使用. ddt包含两个方法

Python3+Requests+Excel完整接口自动化测试框架的实现

框架整体使用Python3+Requests+Excel:包含对实时token的获取 1.------base -------runmethond.py runmethond:对不同的请求方式进行封装 import json import requests requests.packages.urllib3.disable_warnings() class RunMethod: def post_main(self, url, data, header=None): res = None if

python接口自动化测试之接口数据依赖的实现方法

在做自动化测试时,经常会对一整套业务流程进行一组接口上的测试,这时候接口之间经常会有数据依赖,那么具体要怎么实现这个依赖呢. 思路如下: 抽取之前接口的返回值存储到全局变量字典中. 初始化接口请求时,解析请求头部.请求参数等信息中的全局变量并进行替换. 发出请求. 核心代码实现: 抽取接口的返回值存储到全局变量字典中 # 抽取接口的返回值存储到全局变量字典中 if set_global_vars and isinstance(set_global_vars, list): for set_glo

python自动化测试之DDT数据驱动的实现代码

时隔已久,再次冒烟,自动化测试工作仍在继续,自动化测试中的数据驱动技术尤为重要,不然咋去实现数据分离呢,对吧,这里就简单介绍下与传统unittest自动化测试框架匹配的DDT数据驱动技术. 话不多说,先撸一波源码,其实整体代码并不多 # -*- coding: utf-8 -*- # This file is a part of DDT (https://github.com/txels/ddt) # Copyright 2012-2015 Carles Barrobés and DDT con

Python+unittest+DDT实现数据驱动测试

前言 数据驱动测试: 避免编写重复代码 数据与测试脚本分离 通过使用数据驱动测试,来验证多组数据测试场景 通常来说,多用于单元测试和接口测试 ddt介绍 Data-Driven Tests(DDT)即数据驱动测试,可以实现不同数据运行同一个测试用例.ddt本质其实就是装饰器,一组数据一个场景. ddt模块包含了一个类的装饰器ddt和三个个方法的装饰器: data:包含多个你想要传给测试用例的参数,可以为列表.元组.字典等: file_data:会从json或yaml中加载数据: unpack:分

python ddt实现数据驱动

ddt 是第三方模块,需安装, pip install ddt DDT包含类的装饰器ddt和两个方法装饰器data(直接输入测试数据) 通常情况下,data中的数据按照一个参数传递给测试用例,如果data中含有多个数据,以元组,列表,字典等数据,需要自行在脚本中对数据进行分解或者使用unpack分解数据. @data(a,b) 那么a和b各运行一次用例 @data([a,d],[c,d]) 如果没有@unpack,那么[a,b]当成一个参数传入用例运行 如果有@unpack,那么[a,b]被分解

Python Selenium 之数据驱动测试的实现

数据驱动模式的测试好处相比普通模式的测试就显而易见了吧!使用数据驱动的模式,可以根据业务分解测试数据,只需定义变量,使用外部或者自定义的数据使其参数化,从而避免了使用之前测试脚本中固定的数据.可以将测试脚本与测试数据分离,使得测试脚本在不同数据集合下高度复用.不仅可以增加复杂条件场景的测试覆盖,还可以极大减少测试脚本的编写与维护工作. 下面将使用Python下的数据驱动模式(ddt)库,结合unittest库以数据驱动模式创建百度搜索的测试. ddt库包含一组类和方法用于实现数据驱动测试.可以将

Python自动化之数据驱动让你的脚本简洁10倍【推荐】

前言 数据驱动是一种思想,让数据和代码进行分离,比如爬虫时,我们需要分页爬取数据时,我们往往把页数 page 参数化,放在 for 循环 range 中,假如没有 range 这个自带可以生产数字序列的方法可以用,我们是不是得手动逐个添加? 现实场景中就存在大量这样的例子,比如我之前写的爬取上海各地区房租情况的时候,对地区进行遍历的时候,为了偷懒,我直接把这些地区的拼音全称放在了列表里,组合成各地区房源的链接.最后文章写完了,有读者反馈,少了徐汇区的统计数据.这种小数量的数据都出现了纰漏,可想而

利用Python如何实现数据驱动的接口自动化测试

前言 大家在接口测试的过程中,很多时候会用到对CSV的读取操作,本文主要说明Python3对CSV的写入和读取.下面话不多说了,来一起看看详细的介绍吧. 1.需求 某API,GET方法,token,mobile,email三个参数 token为必填项 mobile,email 必填其中1项 mobile为手机号,email为email格式 2.方案 针对上面的API,在做接口测试时,需要的测试用例动辄会多达10+, 这个时候采用数据驱动的方式将共性的内容写入配置文件或许会更合适. 这里考虑把AP

python使用ddt过程中遇到的问题及解决方案【推荐】

前言: 在使用DDT数据驱动+HTMLTestRunner输出测试报告时遇到过2个问题: 1.生成的测试报告中,用例名称后有dict() -> new empty dictionary 2.使用ddt生成的用例名称无法更改 1.用例名称后有dict() -> new empty dictionary 报告中用例名称后有dict() -> new empty dictionary,如图所示: 解决方案:这是ddt高版本1.2.0的bug 1.cmd先通过pip uninstall ddt

Python 中如何实现参数化测试的方法示例

之前,我曾转过一个单元测试框架系列的文章,里面介绍了 unittest.nose/nose2 与 pytest 这三个最受人欢迎的 Python 测试框架. 本文想针对测试中一种很常见的测试场景,即参数化测试,继续聊聊关于测试的话题,并尝试将这几个测试框架串联起来,做一个横向的比对,加深理解. 1.什么是参数化测试? 对于普通测试来说,一个测试方法只需要运行一遍,而参数化测试对于一个测试方法,可能需要传入一系列参数,然后进行多次测试. 比如,我们要测试某个系统的登录功能,就可能要分别传入不同的用

python selenium自动化测试框架搭建的方法步骤

设计思路 本文整理归纳以往的工作中用到的东西,现汇总成基础测试框架提供分享. 框架采用python3 + selenium3 + PO + yaml + ddt + unittest等技术编写成基础测试框架,能适应日常测试工作需要. 1.使用Page Object模式将页面定位和业务操作分开,分离测试对象(元素对象)和测试脚本(用例脚本),一个页面建一个对象类,提高用例的可维护性: 2.使用yaml管理页面控件元素数据和测试用例数据.例如元素ID等发生变化时,不需要去修改测试代码,只需要在对应的

Python自动化之UnitTest框架实战记录

1 UnitTest 基本用法 UnitTest 框架是 Python 自带的一个作为单元测试的测试框,相当于 Java中的 JUnit,随着自动化技术的成熟,UnitTest 成为了测试框架第一选择,可以完整的结合 Selenium.Requests 来实现 Ul 和接口的自动化,由 UnitTest 再衍生出 PyTest,PyTest 可以完美结合 UnitTest 来实现自动化. 基本应用: 1.环境搭建,Python 中已经直接加载了 UnitTest 框架,无须额外安装 2.四大组件