04 | 案例:如何把流程化的测试脚本抽象为测试框架?

你好,我是陈磊。

在上一节课中我和你强调了,用什么工具或代码解决测试问题并不重要,拥有接口测试思维才更重要。在今天的课程中,我会带你从零开始打造一个测试框架,建立你自己的技术体系。

在这里,我推荐你学习一门编程语言,以便你可以更加得心应手、个性化地改造你的测试框架或工具。在这节课中,我会以Python语言来展示我的代码示例,不过语言本身不是重点,你只需要了解这其中的逻辑与方法即可,同样的事情,你可以使用Java、Go等任何你喜欢的语言来完成。

当然,如果你想学习Python语言的话,我推荐你花一个周末的时间看看尹会生老师的“零基础学Python”课程

为什么要开发自己的测试框架?

之前,我们说到了用Postman来完成接口测试,但随着你的接口测试项目逐渐增加,你会发现越来越难以管理它的脚本,虽然测试工具导出的测试脚本也可以存放到代码仓库,但是,如果只是通过代码来查看是很难看懂的,你必须用原来的测试工具打开,才能更容易看懂原来的脚本做了什么样的操作。

同时,Postman也有其自身的局限性,最重要的一点就是它支持的接口协议有限,如果你接到了一个它无法完成的接口类型的测试任务,就不得不再去寻找另一个工具。由于接口类型的多样和变化,你会有一堆工具需要维护,这无疑会提高你的学习成本和技术投入成本。

Postman是如此,其他的工具也是如此,随着接口测试项目的增加,以及被测接口类型的增加,维护的难度会成指数级增长,所以,开发你自己的测试框架非常重要。

今天这节课,我就带你用Python 3.7来完成接口测试,并通过测试脚本的不断优化和封装,让你拥有一套完全适合你自己的接口测试框架。当然,我不会告诉你如何写出全部代码,我更想让你掌握的是,从不同的测试脚本抽象出一个测试框架的技巧和思路。

搭建测试框架,不要纠结于技术选型

在做接口测试脚本开发的技术选型上,我更建议你根据自己的技术实力和技术功底来选择,而不要以开发工程师的技术栈来选择。

这是因为,开发工程师和测试工程师关注的点,以及工作的交付目标是不同的。

  • 对于任何一个开发工程师来说,他们主要的工作就是通过写代码实现产品需求或原型设计,他们会关心高并发、低消耗、分布式、多冗余,相对来说,也更加关注代码的性能和可靠性。
  • 我们作为测试工程师,无论是使用自动化的接口测试,还是界面的手工测试,第一目标都是保障交付项目的质量,那些业务侧的表现,在大多数情况下不是我们关心的重点。

因此,开发工程师在开发技术栈上的使用频度、使用广度,都会远远高于我们,除非你本来就有对应的知识储备,否则不要强求炫技,为了提高工作效率,你只要使用自己熟悉的技术栈完成自动化接口测试就可以了。

这里我再强调一下,用什么技术栈来写代码,只是一种帮助你实现接口测试的手段,它不是你要交付的结果。所以你在搭建测试框架时,不要太纠结技术选型。

搭建前的准备工作

我相信现在你已经准备好,和我一起完成今天的内容了,但在开工之前,我要先把一些基础知识简单介绍给你。

我们今天会用到Python的一个第三方HTTP协议支持库requests,它可以让我们在和HTTP协议打交道时更轻松;requests项目的描述是“HTTP for Humans”,由此可见,这会是一个人见人爱的HTTP协议库。你可以通过下面这个命令,完成requests的安装:

pip install requests

完成安装后,你就可以使用requests完成我用Postman完成的接口测试了。主要代码段我会在文章中给出,我会尽最大努力给你一个可以直接运行的代码段,这样,即使你看不懂也不用担心,你只要把这些代码复制到一个有Python运行环境的机器上,直接使用就可以了。

第一个接口的单接口测试脚本如下,我在代码中做了详细的注释,你既可以复制出去直接运行,也可以通过注释看懂代码的作用。这样,你就完成了一个无参数的、GET访问的验证工作。

# Python代码中引入requests库,引入后才可以在你的代码中使用对应的类以及成员函数
import requests
# 建立url_index的变量,存储战场的首页
url_index='http://127.0.0.1:12356/'
# 调用requests类的get方法,也就是HTTP的GET请求方式,访问了url_index存储的首页URL,返回结果存到了response_index中
response_index = requests.get(url_index)
# 存储返回的response_index对象的text属性存储了访问主页的response信息,通过下面打印出来
print('Response内容:'+response_index.text)

接下来,是第二个被测试的接口,它是登录接口,是以POST方式访问的,它需要通过Body传递username和password这两个参数,这两个参数都是字符串类型,字符长度不可以超过10,并且不能为空。

你还记得在上节课中,我们一起用边界值法设计的测试用例吗?如果你忘记了,那么请你在本节课结束后,再回去看一下。这里你用下面的代码段,就可以完成第二个接口的单接口测试脚本了。

# python代码中引入requests库,引入后才可以在你的代码中使用对应的类以及成员函数
import requests
# 建立url_login的变量,存储战场系统的登录URL
url_login = 'http://127.0.0.1:12356/login'
# username变量存储用户名参数
username = 'criss'
# password变量存储密码参数
password = 'criss'
# 拼凑body的参数
payload = 'username=' + username + '&password=' + password
# 调用requests类的post方法,也就是HTTP的POST请求方式,
# 访问了url_login,其中通过将payload赋值给data完成body传参
response_login = requests.post(url_login, data=payload)
# 存储返回的response_index对象的text属性存储了访问主页的response信息,通过下面打印出来
print('Response内容:' + response_login.text)

无论你是不是看得懂上面的两段代码,你都能看出来,这其中有很多代码都是重叠在一起的,这两段代码的结构很相似,但又有明显的差异性。

开始打造一个测试框架

我想请你先思考这么一个问题,你在用Postman这类工具做接口测试时,除去你自己构建的访问路由和Requsts参数,其他的是不是就靠工具帮你处理完成了呢?

那么,我们接口测试的脚本,是不是也可以把一些公共的操作,抽象到一个文件中呢?这样你在写测试脚本时,通过拼凑路由、设计Request入参就可以完成接口测试了。在这样的思路之下,我们来一起改造一下刚刚的脚本。

第一步,你要建立一个叫做common.py的公共的方法类。下面我给出的这段注释详细的代码,就是类似我们使用Postman的公共方法的封装,它可以完成HTTP协议的GET请求或POST请求的验证,并且和你的业务无关。

# 定义一个common的类,它的父类是object
class Common(object):
  # common的构造函数
  def __init__(self):
    # 被测系统的根路由
    self.url_root = 'http://127.0.0.1:12356'
  # 封装你自己的get请求,uri是访问路由,params是get请求的参数,如果没有默认为空
  def get(self, uri, params=''):
    # 拼凑访问地址
    url = self.url_root + uri + params
    # 通过get请求访问对应地址
    res = requests.get(url)
    # 返回request的Response结果,类型为requests的Response类型
    return res
  # 封装你自己的post方法,uri是访问路由,params是post请求需要传递的参数,如果没有参数这里为空
  def post(self, uri, params=''):
    # 拼凑访问地址
    url = self.url_root + uri
    if len(params) > 0:
      # 如果有参数,那么通过post方式访问对应的url,并将参数赋值给requests.post默认参数data
      # 返回request的Response结果,类型为requests的Response类型
      res = requests.post(url, data=params)
    else:
      # 如果无参数,访问方式如下
      # 返回request的Response结果,类型为requests的Response类型
      res = requests.post(url)
    return res

接下来,用你自己的Common类,修改第一个接口的单接口测试脚本,就可以得到下面的代码了。

# Python代码中引入requests库,引入后才可以在你的代码中使用对应的类以及成员函数
from common import Common
# 首页的路由
uri = '/'
# 实例化自己的Common
comm = Common()
#调用你自己在Common封装的get方法 ,返回结果存到了response_index中
response_index = comm.get(uri)
# 存储返回的response_index对象的text属性存储了访问主页的response信息,通过下面打印出来
print('Response内容:' + response_index.text)

从这段代码中你可以看到,与前面对应的单接口测试脚本相比,代码的行数有明显的减少,这也能减少你很多的工作量,与此同时,如果你有任何关于HTTP协议的操作,都可以在Common类中进行修改和完善。

如果使用你自己刚刚建立的公共类(在我们内部有时候喜欢把它叫做轮子,这是源于一句俚语“不用重复造轮子”,因为Common类就是重复被各个检测代码使用的“轮子”)修改一下第二个接口的单接口测试脚本,代码就会变成下面这个样子:

#登录页路由
uri = '/login'
# username变量存储用户名参数
username = 'criss'
# password变量存储密码参数
password = 'criss'
# 拼凑body的参数
payload = 'username=' + username + '&password=' + password
comm = Common()
response_login = comm.post(uri,params=payload)
print('Response内容:' + response_login.text)

当你有一些更加复杂的脚本时,你会发现两次代码的变化会变得更明显,也更易读。

这就是那些曾经让你羡慕不已的框架诞生的过程,通过分析和观察你可以看到,原始的第一个接口的单接口测试脚本和第二个接口的单接口测试脚本,它们存在相同的部分,通过将这些相同的部分合并和抽象,就增加了代码的可读性和可维护性,也减少了脚本的开发量。通过这个方法,你就可以打造出一个属于自己的测试框架。

用你的框架完成多接口测试

上面我们仅仅进行了一小步的封装,就取得了很大的进步,在你写出越来越多的脚本后,你还会发现新的重叠部分,这时如果你能不断改进,最终就会得到完全适合你的测试框架,而且其中每一个类、每一个函数你都会非常熟悉,这样,碰到任何一个难解的问题时,你都有能力通过修改你的框架来解决它,这样,这个框架实际上就变成了一个你在接口测试方面的工具箱了。

那么,怎么用我们刚刚一起搭建的测试框架,来完成多接口测试的业务逻辑测试呢?

不知道你是不是还记得在上节课中,我们讲到的Battle使用流程的测试用例,如果你没记起来,我先告诉你:“正确登录系统后,选择武器,与敌人决斗后杀死了敌人。”其他的,在本次课程结束后,你可以自己再去温习一下。

那么。使用我们一起封装的框架来完成上面的多接口测试后,就会得到下面的代码:

# Python代码中引入requests库,引入后才可以在你的代码中使用对应的类以及成员函数
from common import Common
# 建立uri_index的变量,存储战场的首页路由
uri_index = '/'
# 实例化自己的Common
comm = Common()
#调用你自己在Common封装的get方法 ,返回结果存到了response_index中
response_index = comm.get(uri_index)
# 存储返回的response_index对象的text属性存储了访问主页的response信息,通过下面打印出来
print('Response内容:' + response_index.text)
# uri_login存储战场的登录
uri_login = '/login'
# username变量存储用户名参数
username = 'criss'
# password变量存储密码参数
password = 'criss'
# 拼凑body的参数
payload = 'username=' + username + '&password=' + password
comm = Common()
response_login = comm.post(uri_login,params=payload)
print('Response内容:' + response_login.text)
# uri_selectEq存储战场的选择武器
uri_selectEq = '/selectEq'
# 武器编号变量存储用户名参数
equipmentid = '10003'
# 拼凑body的参数
payload = 'equipmentid=' + equipmentid
comm = Common()
response_selectEq = comm.post(uri_selectEq,params=payload)
print('Response内容:' + response_selectEq.text)
# uri_kill存储战场的选择武器
uri_kill = '/kill'
# 武器编号变量存储用户名参数
enemyid = '20001'
# 拼凑body的参数
payload = 'enemyid=' + enemyid+"&equipmentid="+equipmentid
comm = Common()
response_kill = comm.post(uri_kill,params=payload)
print('Response内容:' + response_kill.text)

上面的代码有点长,但你先不要有抵触的心理,每一个代码行的注释我都写得很清楚。然而我并不是想让你知道,上面那么多类似蝌蚪文的代码都是干什么的,我是想让你看看上面的代码中,是否有可以用前面“抽象和封装重复代码的方法”进行优化的地方。

你可以看到,上面的代码大量重复了你自己写的通用类的调用,这个其实是可以合成一个的;同时,你再观察一下我们一起写的Common类,你会发现有一个self.url_root = ‘http://127.0.0.1:12356’,如果这里这样写,你的Common就只能用来测试我们这个小系统了,除非你每次都去修改框架。

但是,任何一个框架的维护者,都不希望框架和具体逻辑强相关,因此这也是一个优化点,那么将上面的内容都修改后,代码就会变成下面这个样子:

# Python代码中引入requests库,引入后才可以在你的代码中使用对应的类以及成员函数
from common import Common
# 建立uri_index的变量,存储战场的首页路由
uri_index = '/'
# 实例化自己的Common
comm = Common('http://127.0.0.1:12356')
#调用你自己在Common封装的get方法 ,返回结果存到了response_index中
response_index = comm.get(uri_index)
# 存储返回的response_index对象的text属性存储了访问主页的response信息,通过下面打印出来
print('Response内容:' + response_index.text)
# uri_login存储战场的登录
uri_login = '/login'
# username变量存储用户名参数
username = 'criss'
# password变量存储密码参数
password = 'criss'
# 拼凑body的参数
payload = 'username=' + username + '&password=' + password
response_login = comm.post(uri_login,params=payload)
print('Response内容:' + response_login.text)
# uri_selectEq存储战场的选择武器
uri_selectEq = '/selectEq'
# 武器编号变量存储用户名参数
equipmentid = '10003'
# 拼凑body的参数
payload = 'equipmentid=' + equipmentid
response_selectEq = comm.post(uri_selectEq,params=payload)
print('Response内容:' + response_selectEq.text)
# uri_kill存储战场的选择武器
uri_kill = '/kill'
# 武器编号变量存储用户名参数
enemyid = '20001'
# 拼凑body的参数
payload = 'enemyid=' + enemyid+"&equipmentid="+equipmentid
response_kill = comm.post(uri_kill,params=payload)
print('Response内容:' + response_kill.text)
是不是比上一个节省了很多代码,同时也看的更加的易读了,那么我们封住好的Common就变成了如下的样子:

# 定义一个common的类,它的父类是object

class Common(object):

# common的构造函数

 def __init__(self,url_root):

# 被测系统的跟路由

self.url_root = url_root


 
# 封装你自己的get请求,uri是访问路由,params是get请求的参数,如果没有默认为空

def get(self, uri, params=''):

 # 拼凑访问地址

 url = self.url_root + uri + params

 # 通过get请求访问对应地址

 res = requests.get(url)

 # 返回request的Response结果,类型为requests的Response类型

 

return res

 # 封装你自己的post方法,uri是访问路由,params是post请求需要传递的参数,如果没有参数这里为空

def post(self, uri, params=''):

 # 拼凑访问地址

 url = self.url_root + uri

 if len(params) > 0:

 # 如果有参数,那么通过post方式访问对应的url,并将参数赋值给requests.post默认参数data

 # 返回request的Response结果,类型为requests的Response类型

 res = requests.post(url, data=params)

 else:

# 如果无参数,访问方式如下

# 返回request的Response结果,类型为requests的Response类型

 res = req

你可以看到,在上面这段代码中,我主要是让我们Common类的构造函数接受了一个变量,这个变量就是被测系统的根路由。这样是不是就比上一个代码段节省了很多代码,同时也更加易读了?那么我们封装好的Common就变成了下面这个样子:

# 定义一个common的类,它的父类是object
class Common(object):
  # common的构造函数
  def __init__(self,url_root):
    # 被测系统的跟路由
    self.url_root = url_root
  # 封装你自己的get请求,uri是访问路由,params是get请求的参数,如果没有默认为空
  def get(self, uri, params=''):
    # 拼凑访问地址
    url = self.url_root + uri + params
    # 通过get请求访问对应地址
    res = requests.get(url)
    # 返回request的Response结果,类型为requests的Response类型
    return res
  # 封装你自己的post方法,uri是访问路由,params是post请求需要传递的参数,如果没有参数这里为空
  def post(self, uri, params=''):    
    # 拼凑访问地址    
    url = self.url_root + uri    
    if len(params) > 0:    
      # 如果有参数,那么通过post方式访问对应的url,并将参数赋值给requests.post默认参数data   
      # 返回request的Response结果,类型为requests的Response类型   
      res = requests.post(url, data=params)    
    else:
      # 如果无参数,访问方式如下
      # 返回request的Response结果,类型为requests的Response类型
      res = requests.post(url) 
      return res

通过改造Common类的构造函数,这个类已经变成一个通用类了,无论是哪一个项目的接口测试,都可以使用它来完成HTTP协议的接口验证了。

我相信现在你已经掌握了测试框架的形成过程,就如下图所示,测试框架的形成是在撰写大量测试脚本的过程中不断抽象封装出来的,然后,再用这个不断完善的框架,改写原有的测试脚本。循环往复这个过程,你就会慢慢获得一个独一无二的、又完全适合你工作的接口测试框架。

其实到这里,我们上面说的只能算是一个调试代码,还不能算是一个测试框架。上面这些代码所有的返回值都打印到控制台后,为了完成接口测试,你需要时时刻刻看着控制台,这还不能算是自动化,只能说是一个辅助小工具。

在这里,你应该让全部测试结果都存储到测试报告里面,同时通过一个测试驱动框架来完成各个模块的驱动,这也是为什么你在学习任何一种框架的时候,总会遇见类似Java的JUnit、Python的Unittest的原因,因此,上面的Common类还需要和Python的unittest一起使用,才算是一个完美的测试框架。

至于你自己的Common类怎么和测试驱动框架相结合,这部分内容就留给你在未来的接口测试工作中,自己去学习并完成了。

总结

今天,我们一起学习了一个测试框架的诞生过程。测试框架就是在你测试脚本中不断抽象和封装得来的。今天我们课程的内容充斥着各种代码,如果你的代码基础稍微比较薄弱,并没有完全记住上面的内容,那么我希望你记住从测试脚本到测试框架的转化过程:

  1. 不断撰写测试脚本,所有的抽象和封装都是站在已有的测试脚本基础之上的;
  2. 多观察已经写好的测试脚本,找出其中的重叠部分,最后完成封装;
  3. 以上两步是一个不断循环又循序渐进的过程,你要在你的工作中始终保持思考和警惕,发现重复马上进行框架封装。

最后我想和你强调的是,测试框架的封装和抽象过程并不是一蹴而就的,它是靠一点一点的积累得来的,因此,你要通过自己的实践,慢慢积累和完善你的测试框架,而不要妄想一次就能有一个完善的测试框架。我相信,当你通过写脚本完成整个项目的接口测试后,你一定会得到一个完美的测试框架。

思考题

在我讲的最后一个多接口测试脚本,其实也并不是最完美的修改,你能提出更好的修改意见吗?如果它可以抽取到你的框架中,那么是完成一个什么样任务的类或者函数呢?

我是陈磊,欢迎你在留言区留言分享你的观点,如果这篇文章让你有新的启发,也欢迎你把文章分享给你的朋友,我们一起探讨和学习。

精选留言

  • 捷后愚生

    2020-11-28 10:57:38

    接口测试框架的形成过程
    流水账式的接口测试脚本
    在编写不少流水账式的接口测试脚本后,发现其中存在大量重复的代码
    思考:能不能把公共的操作单独抽离出来,抽象到一个common文件中,在其他文件继承或导入文件进行使用

    如何区分哪些是公共的部分?
    一般哪些是公共部分?
    公共部分与非公共部分的边界是什么?
    提供common文件的通用性
    如不写死测试系统,通过传入参数指定测试系统

    加入测试报告
    加入测试报告模块,把测试结果储存在测试报告当中,而是都使用print打印

    加入测试驱动框架
    加入unittest或pytest测试驱动框架来驱动各个模块,更好地组织测试脚本

    加入日志
    为了更好地定位和分析问题,加入日志模块

    加入断言
    针对复杂断言,引入jsonpath断言、Xml断言、Xpath断言、hamcrest断⾔、Json schema校验

    引入POM
    为了更好地区分业务操作,方便脚本维护,引入POM

    引入参数化
    为了应对大数据量测试,引入参数化

    ......

    不要把测试框架看得太高大上了,不是只有像selenium、appium、httprunner才叫测试框架,你可以从一个简单地测试框架开始做起。

    测试框架是在编写大量测试脚本地过程中不断抽象封装出来地,然后不断完善,是一个循环往复地过程。
    作者回复

    看你的总结 我都想修改我的课程总结了。太棒了

    2020-12-14 08:46:00

  • 2020-02-26 09:44:20

    😁确实比较基础,不过思路是完全没问题,任何东西基本都是无中生有,然后发展壮大,然后又归于无。
    测试的诉求就是想快,其实各行各业都一样都想快,怎么才能快起来呢?更强壮、更灵活、更聪明的人明显会快许多,不过精力再好也有疲惫的时候,所以,人肉这条路天花板太低啦!那还能怎样?用机器呀!他不仅擅长简单重复的事情,而且不知疲倦,只要有电用到报废都无所谓。OK,问题来了怎么用机器?机器擅长简单重复的事情,那好就找简单重复的事情给他做,找的过程就是抽象封装的过程,告诉机器怎么做就是编程的过程。然后就是再想法子搞一个定时任务,让他自己动起来,这些都不难,下面其实就没有了,不过测试这么干,其他使用机器的思路基本如此,剩下就是不断优化,提高用户体验,说通俗点就是让傻瓜也能操作是最理想的。
    做到这些确实可以提高测试效率,不过路还很长,就我自己的感受而言,我们的业务比较复杂,变化快,细节多,许多好几年的老测试甚至研发本身对于业务都不能完全搞清楚,代码像像小说一样,入参、出参、调用都是容易搞定的事情,难点在于你不知道走了什么逻辑,你不知道结果对不对。当然,这是一个难题,破解之道别无他法熟悉业务知识积累业务知识,不过之所以,这么难就是分布式系统本身的特性,高并发高可用高性能易扩展的代价就复杂度的提升。
  • happychap

    2020-02-08 10:57:16

    有个观点与老师不同,就是在编程语言的选择上,针对新手而言,选择与研发团队相同的编程语言(java,python,js,go)个人觉得会更好一些,一方面有研发团队作为依靠,另一方面在接入ci时,可以复用研发团队的ci接入技术栈。再有就是能复用面向测试的底层开源库就先复用它们,把更多的精力放在测试领域功能封装上,如:入参的处理,出参的传递,接口请求结果的抽取等方面。
    如果对编程语言还是一知半解,老师本讲所讲的内容就要多去理解、实践了,它是很好的入门窗口。
    作者回复

    您好,看了您的留言,你的观点也有道理,我不推荐按照rd的技术栈选择是因为rd的技术栈入门门槛高,ci,cd流水线也不依赖rd技术栈,因此我建议在基础薄弱的小伙伴选择上以简单的开始。

    2020-02-08 14:52:43

  • 技术修行者

    2020-02-23 09:04:52

    看完这篇文章,可以更清晰的感觉到这个专栏的受众应该是初级测试人员,不太适合开发人员。

    在部落中也零星看到一些关于这个专栏的讨论和批评,我觉得可能是因为大家对专栏的期望太高了,结果在这里没有看到化腐朽为神奇的东西。

    一步一步来吧,总归是开卷有益,拓展思路,查漏补缺也挺好的。
    作者回复

    谢谢您的支持,每个人都有自己的评价,我虚心学习

    2020-02-23 14:17:43

  • 牺牲

    2020-05-08 23:38:52

    我真的没看出common接收变量后,代码量有什么节省。就是不用动框架了,每次传参就可以了。
    作者回复

    也不差啊

    2020-05-13 09:42:30

  • 丁丁历险记

    2020-05-02 23:10:02

    推荐一本书,martin flower 的重构。
    作者回复

    好书

    2020-05-03 09:41:14

  • 深瞳

    2020-04-01 19:08:09

    上了这个课程以后才知道自己会的接口测试知识太太少了,要学的太多了,自己的基础太薄弱了
    作者回复

    发现了不足就是最大的收获,也是对我最大的鼓励,谢谢您的支持

    2020-04-01 21:56:49

  • 陈优雅

    2020-02-09 01:53:45

    单一接口测试代码可以用postman直接生成
    作者回复

    谢谢,后续课程也就有相关讲解

    2020-02-09 08:58:02

  • Geek_a57228

    2020-02-07 16:28:45

    老师,看你的脚步,写公共方法的那一段是否需要加上import requests呢?不然后面调用requests包时,会有问题吧,刚学Python代码,所以问题比较初级
    作者回复

    嗯,是的谢谢指出。

    2020-02-07 23:01:19

  • 懒猫

    2021-07-22 16:59:46

    对我个人而言,看完了前面几篇收获比较少,但毕竟只是入门课程不能强求,不过老师的大部分观点和思想都比较赞同,只想知道老师后续是否有进阶课程?
  • 小老鼠

    2020-04-19 21:31:33

    对于非HTTP协议用什么类?比如DNS、Webservices、DHCP?
  • Geek_a859b9

    2020-03-28 21:55:49

    测试框架的形成是在撰写大量测试脚本的过程中不断抽象封装出来的,然后,再用这个不断完善的框架,改写原有的测试脚本。循环往复这个过程,你就会慢慢获得一个独一无二的、又完全适合你工作的接口测试框架。
  • 7F

    2020-02-09 11:20:33

    有一个Python业界很获得接口测试框架,HTTPrunner,老师你怎么看这个框架。
    作者回复

    每个框架都有它的优势和劣势,HTTPRunner我还没听说,有时间我去学习一下。

    2020-02-09 12:23:38

  • 杨亚玲

    2020-02-08 13:18:39

    有下面这样的错误:
    print('Response内容:' + response_login.text)
    AttributeError: 'NoneType' object has no attribute 'text'
    作者回复

    您好,我在我的电脑上没有发现有类似保存,您方便把全部代码贴出来看一下吗。

    2020-02-09 09:26:57

  • 168园长

    2025-03-14 15:47:28

    # 实例化自己的Com = Common('http://127.0.0.1:12356'这里可以这样写吗?为啥我运行起来,提示我便利comm是none,无法调用get函数
    Traceback (most recent call last):
    File "/Users/liwenyuan/PycharmProjects/PythonProject1/决斗流程测试.py", line 9, in <module>
    responses_index=com.get(uri_index)
    AttributeError: 'NoneType' object has no attribute 'get'
  • On

    2023-08-04 17:09:43

    最近几份工作的招聘都是需要接口测试,现在才发现接口测试的知识和技能都太欠缺了。感谢遇到老师这门课!
  • 韩培仁

    2023-04-13 09:11:32

    使用可以高并发分布式的Python爬虫框架,比如scrapy,应该除了实现接口测试之外,还可以实现性能测试,负载和压测都可以用爬虫框架模拟大批量用户访问服务端接口,
    然后再使用监控组件,数据可视化组件,就可以做出来远比Jmeter好用还好看得多的工具或者平台
  • tester_tu

    2022-09-14 15:10:40

    类里面的init函数没有默认执行,弄得他报AttributeError: 'Common' object has no attribute 'url_root'错误。要怎么弄咧?
  • 伶花

    2022-08-30 15:42:33

    if len(params) > 0: # 如果有参数,那么通过post方式访问对应的url,并将参数赋值给requests.post默认参数data # 返回request的Response结果,类型为requests的Response类型 res = requests.post(url, data=params) else: # 如果无参数,访问方式如下 # 返回request的Response结果,类型为requests的Response类型 res = requests.post(url) return res

    老师,测别的系统时,运行会提示 '>' not supported between instances of 'str' and 'int'
  • Duxuebing

    2022-06-22 17:18:27

    看起来不难,等我自己封装get请求,想添加header 和 params却折腾了好久还没成功,老师,基础知识太弱怎么办