☰
Python接口自动化测试之UnitTest详解
2026/9/25 22:05:00 网站建设 项目流程

基本概念

这个单元测试框架是受到了JUnit这种测试工具的启发。它和其他编程语言里面那些主流的单元测试框架长得很像。在风格上, 这些框架都彼此相似。这个框架支持做自动化测试工作。

它还能够帮助配置共享的东西。它也支持测试关机时的代码逻辑。另外, 它能够把很多测试样板聚集到一起变成一个测试集。最后, 它能做到让测试功能和报告功能分离开来, 互不相干。

该结构总共被拆解成了四个部分, 分别叫做test、test suite以及test, 具体详情如下:

测试的准备工作, 指的是在测试工作开始之前所需要进行的所有的准备行动, 以及后面所有的相关的处理和清理方面的操作。

测试用例是一个独立的测试单元, 它会针对特定的输入数据, 去检查系统做出的响应情况。

这个测试套件是用来做什么的呢, 它是用来把那些需要放在一起执行的测试用例全部收起来的。

测试运行器, 它是那种组件, 专门用来执行各种操作, 并且还会把所有相关的测试结果输出出来。

详解

类本身为测试用例提供了有力支持。大家可以通过继承的方式来创建一个全新的测试类, 然后在这个类里面设置具体的测试方法。在测试运行时, 每一个单独的方法都会把实际得到的响应结果和之前定好的预期结果进行对比, 以此完成单元测试这一步骤。

测试用例会包含 setUp 方法, 当然还有 ()、() 以及 ()。需要注意, 类名称必须以 Test作为前缀, 并且, 每一个测试用例的名称都得以 test开头,这样的规矩要遵守。

接下来, 咱们就用一个例子来给大家展示一下具体情况。

import unittest

class Test_unittest(unittest.TestCase):

def setUp(self) -> None:

print('setup')

def test(self):

print('test')

def tearDown(self) -> None:

print('teardown')

if __name__ == '__main__':

unittest.main()

运行结果里面可以看到打印了三条测试用例里的内容, 还有 setup 方法和相应的执行过程, 在每次执行测试用例的前后都会执行这些操作, 如果增加一条测试用例的话, setup 方法也会再额外执行一次, 如下图所示:

所以, 如果希望初始化的方法以及结束的方法各自仅仅被执行一次的话, 是可以借助对应的注解来实现的, 具体的情况是要在相关的方法的前面添加上特定的注解标识, 请大家详细参考下面所提供的具体示例内容以及最终产生的执行结果。

import unittest

class Test_unittest(unittest.TestCase):

@classmethod

def setUpClass(cls) -> None:

print('setup')

def testcase1(self):

print('testcase1')

def testcase2(self):

print('testcase2')

def tearDown(self) -> None:

print('teardown')

if __name__ == '__main__':

unittest.main()

从能够观察到,如果使用了()这个方法情况的话就仅仅只会进行一次初始化动作, 反之如果没有使用该方法的状况下每条用例执行的操作内容都将会分别再各自去实施一次。

常用方法断言

在测试用例里, 大家平时经常用到断言操作, 还会用到用skip来跳过某些测试用例的步骤。另外, 这个框架自身也带有一套专门的断言办法, 具体来看, 主要包含下面这几类情况。

这个动作就是表示直接跳过某个环节。

在实际开展的测试工作里面, 如果某些存在功能缺陷的具体功能点, 它们所关联的自动化的测试用例根本无法成功执行, 或者那些压根就不会去执行的用例场景, 大家是可以采用名称为skip的那个方法来进行处理操作的, 它这种具体的使用方式如下所示。

1.跳过这个步骤的操作不需要用户提供任何具体的理由说明, 该操作会直接且无条件地予以执行。

2.当判断条件为真值的时候, 系统去执行动作, 这个逻辑表达式写成点括号加二大于引号一引号逗号带引号理由引号括号的这种格式。

3.当判断条件的结果是假的时候, 就执行括号里面的内容, 也就是把大于号的右半部分和符号一起用引号括起来的那部分当做理由, 整体来看就是“(1>2’理由’)”这一坨。

4.在执行过程中发生的错误, 不会被计算到不通过的用例数量里面。

咱们接下来看一下那个示例, 那个方法呢它是被跳过的, 原因是说这个方法里面用到了断言, 但是这个断言的结果它是对不上的, 所以呢它就蹦出了报错的信息。

import unittest

class Test_unittest(unittest.TestCase):

@classmethod

def setUpClass(cls) -> None:

print('setup')

@unittest.skip

def testcase1(self):

print('testcase1')

def testcase2(self):

a = 1

self.assertEqual(a,2,msg='error')

print('testcase2')

def tearDown(self) -> None:

print('teardown')

if __name__ == '__main__':

unittest.main()

测试套件

当一个类里面包含了多个测试用例, 并且在当前的运行状态下这些测试用例并不会被同时执行的话, 那么我们可以考虑将这些测试用例添加到一个测试套件(suite)中去进行统一管理和运行。

需要注意的是, 这里提到的在中suite中运行的方式, 并不是指直接在现有的代码文件里进行编写的操作, 而是需要我们去重新新建一个专门的源文件(py文件)来实现这一过程。

1.把那些东西一个接着一个地, 全都加入到这个名为suite的对象里面去。

第一步是导入该文件中的类。第二步是定义一个套件的名称以及对应的方法。第三步是对该套件增加测试用例。第四步是定义运行的名称。第五步是使用运行方法并添加测试套件, 这样就可以启动运行了, 不过需要注意的是这个过程得把用例一个一个地去添加。

2.先创建一个空的列表, 使用方括号将用例全部存放进去, 接着让程序执行操作:

3.通过直接读取类名的这种方式来执行操作, 它是属于最简单的一个方法, 同时也是最为方便的一个手段, 但是在这种情况之下, 不能够去使用单引号。

4.这也是一个去读取名字的操作步骤, 但是在这种情形之下, 大家容易遭遇找不到具体的类的情况, 所以需要在这个名称的前面位置强行添加上一个文件的文件名。

1.在编写完脚本之后, 重新新建一个文件, 然后在里面把对应的测试用例添加到套件当中, 这样就能实现全部执行了。

2.只要是在网络上把那个源代码给下载下来, 然后就把它复制粘贴到那个lib目录下面, 这样的操作就直接可以把东西给导入进去。

关于这种方法的主要解析。

这是那个被大家认为实现起来最为简单、使用体验也格外便捷的HTTP功能库的具体概述, 它总共包含了七个非常核心的操作方法。

打个比方来说, 如果是进行那种比较普通的接口测试的话, 那么这些接口彼此之间往往是不存在什么关联性的。鉴于这种情况的存在, 用户只需要直接地去定义相应的变量, 进而就可以顺利发起包括get请求在内的以及post请求这样的操作了。

其中, post请求常用的方式分为json格式和其他形式两种。请求参数的具体样子如截图所示。如果需要进行鉴权, 就需要导入auth包, 并且将这个包放在请求方法的后面。

方法详解

如果想了解具体的操作方法, 您可以直接按住键盘上的Ctrl键不放, 同时用鼠标左键点击“方法查看”这一选项, 这样就可以查看对应的源码信息了。

1.请求地址的url, 也就是那个用来连接服务器的网络位置。

2.data,这个数据是字典, 或者是字节序列, 又或者是文件对象, 这些都是用来作为其传入内容的具体形式。

3.json指的是那种叫做json格式的玩意儿呢, 它是用来作为一些东西的内容的。

4.需要提交一个字典, 并且要在字典里面加入 HTTP 定制头的相关信息。

5.将字典里的元素或者数组中的元素。

6.在配置当中, 会有一个名叫auth的地方, 它采用的是元祖这种形式, 主要是用来支持那种叫做HTTP认证的某种功能。

7.这个 files, 它是一个叫做字典类型的数据结构, 专门用来进行文件的传输操作。

8.把超时的时长给设定好, 用的单位是秒。

9.这是一种字典类型, 用来设定访问代理服务器, 可以增加登录认证。

10.这是一个关于布尔类型的是非判断, 默认情况下其值为真, 用于控制重定向功能的开启与关闭。

11.判断选项是选择真还是选择假, 默认值是选择真, 这一项的功能是用来控制是否在获取到内容之后立刻进行下载的操作开关状态。

12.默认情况是True, 意思是这个选项会被激活。这个是关于证书开启的开关, 它的作用是启用认证功能中的SSL证书。

13.cert: 本地ssl证书路径

返回方法详解

1.也就是我们通常所说的那个, 从服务器方面返回过来的, 关于http协议响应的状态编码, 这个内容。

2.. #返回的是bytes型也就是二进制的数据

3.返回来的那个http请求头。

4..json() # 返回响应中的Json数据

5..url # 返回url

6.. # 返回响应的编码格式

7.我们来看看如何从返回的响应里面, 找到那个你要的东西。

8.这里是文本的部分, 返回的内容是类型的数据。

详解

当遇到那些前后存在接口依赖关系的情况, 就比如需要从前面的请求里面获取token, 并且把这个token作为参数用在后面的那个接口请求里进行提交的时候, 使用上述的那种方法进行试验的话, 显然并不合适。

如果按照上述的方法来操作的话, 就必须去定义非常多的变量, 然后还得根据依赖关系把它添加到对应的请求参数之中。

这种方法是通过会话的形式来进行, 并且在整个过程中都保持贯通的状态。因为只需要添加一次, 所以在之后的所有请求里面都可以直接使用到相关的内容。

解释:

1.这个系统属于缺陷管理系统, 在进行登录操作的过程里面, 必须把响应内容里的特定字段提取出来, 并且将其作为后续其他请求的必要参数携带过去, 如果省略了这一步骤, 就会导致登录流程无法成功执行。

2.因此在整体架构的设计层面, 是完全可以将登录这一具体操作环节放置到setup函数内部的, 这种做法与UI自动化测试中的思路是保持高度一致的, 也就是说, 它类似于把登录步骤统一放在初始化阶段去执行。

3.我们在配置的过程中, 把从服务器那里接收到的响应内容的值, 全部都添加到了这个请求里面去, 同时在操作之中, 还特意添加了浏览器的UA标识信息。

4.参数是可以进行复用的, 从头开始到结束这个过程中所请求的那些变量全部都是rsp, 而在body里面所涉及到的那些参数它们全都是dict类型的, 这样做起来编写起来简单又方便。

定义一个变量, 让这个名字叫做s的变量去承接那个会话的情况, 然后后续的所有的环节当中, 都要使用这个由s所代表的会话状态来发起相关的网络请求操作。

定义一个变量, 让该变量的值等于s去发起请求之后所得到的结果, 也就是让rsp等于s。

需要在会话请求的头文件中添加这个内容, 如果不这样做就无法成功登录, 需要提醒的是, 这个id是存在于响应信息里的。

由于响应信息是以json这种字典格式来呈现的, 因此当需要将该内容添加到请求头里面的时候, 就必须得去严格按照截图里所展示的那种格式来进行操作才行。

如果在需要往字典中去新增字段或者添加一些具体的内容方面的话, 那么应该遵循那个截图所示出来的那种特定的格式来进行操作。

‘xxx’

当把这个等于“xxx”的键值对进行设置的时候, 如果在那个字典里面存在这个键和值的配对的话, 那么这个现有的值就会直接被刷新成为新的内容;相反地, 假如那个字典里完全没有这一组键和对应的值搭配的话, 那么系统就会执行追加的操作, 把这一组全新的键和值作为新的条目添加进那个字典的里面去。

进行接口的实际测试操作时, 需要把那个token添加到那些文件的标题部分里面去。

在我们公司做实际项目的时候, 去调接口之前, 得先弄到一个token。你得先去请求那个用来获取token的东西, 等拿到了token这个数字或者字符串之后, 把它放到头文件里面, 这样在后面调接口的用的时候就能用了。

self的后面接上小括号, 小括号里面是双大括号括起来的字符串内容, 字符串内容是token冒号rsp的点方法调用json。

‘data’

‘token’

})

您可以向左侧或者右侧拖动, 以此来查看完整的全部代码部分。

通过在setup初始化方法中去调用获取token这个操作, 然后就能把拿到的token值拿到手, 接着把这个得到的数据整体添加到头信息里面去, 这样的话在后续的其他请求过程中也都不需要再进行额外的头部添加操作了。

使用ddt做参数化

关于DDT数据驱动测试这一事宜, 首要的任务在于执行pip list ddt这一些操作以便于安装那个被称为第三方的库, 接着我们需要确保在代码文本的最顶端位置处, 导入在该库内部所存在的名为data的部分。

从ddt导入ddt、data以及相关的函数和类, 在测试类的前面声明使用ddt, 通过@ddt注解来实现。

1、在编写测试用例之前, 需要先进行声明动作, 具体的方式就是使用关键字“data”。

@data('test1','test2')

def test_ddt1(self,value):

print(value)`在这里插入代码片`

(左右滑动查看完整代码)

在运行的结果里面, 这个用例被执行了两次。第一次输出的内容是test1, 第二次输出的内容是test2。

2、在数据的应用方法里面, 进行文件的读取操作。

这个办法是需要执行解包操作的, 因此务必要借助于某个特定的方法, 而要在测试用例开始之前进行声明, 操作的时候需要在前面加上一个@符号。

def readline(self):

date = []

file = open('D:\\base64\\keyid.txt','r',encoding='utf-8')

for line in file:

date.append(line.split())

return date

@data(*readline(""))

@unpack

def test_ddt2(self,vars):

print(vars)

我们对运行的结果进行解释, 首先定义一个用于读取文件的方法, 然后定义一个列表数组, 接下来使用文件的开放方法去读取那个名为“txt1”的文件, 读取的模式设定为读的形式, 编码的格式被确定成utf-8, 通过运用for循环这种方式来不停地、持续地读取文件里的每一行内容, 在此过程里, 以换行符即\n作为每一行的结尾标志, 并以逗号用来分隔开里面的每一个参数, 在最终完成这些步骤后, 返回data这个值, 目的是为了让下面的部分可以直接拿去调用。

在上面写了读取方法之后 <, > 在测试用例前 <, > 直接使用该方法即可 <, > @data(*())这种形式接着使用@解包的方法即可。

生成测试报告

按照上述的方法, 先把测试用例编写好了, 然后再结合那个能够生成报告的框架来去生成接口测试报告。

你可以到网上去找那个库里边的文件, 然后下载下来, 接着把它放到你已经安装好的目录之中, 具体来说就是放到lib这个文件夹里面去, 这样做完之后你以后就可以直接来使用它了。

最后, 作为一名已经经历过这些的人, 真心希望大家能少踩一些坑, 不要走太多弯路。如果你实在不想再重新体验那种在学习过程里找不到靠谱资料, 结果坚持没几天干脆就半途而废的糟糕感觉, 那么我在这里把自己手里的一些关于软件测试的学习资源拿出来分享给你。

这些东西, 对于那些想要学习【软件测试】的朋友来说, 基本上应该算是比较全面、也比较完整的备战素材库了, 希望能在你前行的路上稍微帮你一把。如果你觉得这些东西你能用得上, 可以直接拿去使用就行:

这些资料, 对于软件测试的朋友来说应该是最全面最完整的备战仓库。这个仓库也陪伴上万个测试工程师们走过最艰难的路程。希望也能帮助到你!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询