python 接口数据驱动_基于Python Requests的数据驱动的HTTP接口测试

3) requests的返回值

这里让我们来讨论下requests的返回值。见表1。

表1:requests的返回值

14982672_201708301056113hWu5.jpg

请求网址的内容信息

在这里介绍一下请求页面的状态(状态码),这个在基于HTTP协议的接口测试中经常作为一个验证点。

1XX:表示消息

这个比较少用

2XX:表示成功

经常使用的是:

200:正确

#3XX 表示重定向.

经常使用的是:

304: 没有改变

4XX 表示客户端错误

经常使用的是:

404: 网址不存在

5XX,6XX表示服务器错误.

经常使用的是:

500:服务器内部错误

4)有了上面这些知识,我们来看一下通过request如何来实现接口测试,我们这里以前面介绍的登录模块作为测试对象来设置测试用例。测试用例见表2。

表2:登录模块测试用例

14982672_201708301056114DmQX.jpg

进入登录后页面,出现“查看购物车”

假设我们的正确用户名为 jerry,正确密码为000000,这样我们设计测试代码

testLogin.py

import requests

#正确的用户名,错误的密码

url=“http://127.0.0.1:8000/login_action/

payload={{"username":"jerry","password":“000000"}}

data = requests.post(url,data=payload)

if (str(data.status_code)==‘200’) and (“用户名或者密码错误” in str(data.text))

print(“pass”)

else:

print(“Fail”)

#错误的用户名,正确的密码

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“tom","password":“123456"}}

data = requests.post(url,data=payload)

if (str(data.status_code)==‘200’) and (“用户名或者密码错误” in str(data.text))

print(“pass”)

else:

print(“Fail”)

#错误的用户名,错误的密码

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“tom","password":“000000"}}

data = requests.post(url,data=payload)

if (str(data.status_code)==‘200’) and (“用户名或者密码错误” in str(data.text))

print(“pass”)

else:

print(“Fail”)

#正确的用户名,正确的密码

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“jerry","password":“123456"}}

data = requests.post(url,data=payload)

if (str(data.status_code)==‘200’) and (“查看购物车” in str(data.text))

print(“pass”)

else:

print(“Fail”)

这样的代码虽然可以测试,但是没有测试框架进行限制,代码不利于维护,更不利于批量地执行,我们用刚才介绍的unittest框架进行改造。

testLogin.py

import unittest,requests

class mylogin(unittest.TestCase):

def setUp(self):

print("--------测试开始--------")

def test_login_1:

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“tom","password":“000000"}}

data = requests.post(url,data=payload)

self.assertEqual(‘200’,str(data.status_code))

self.assertIn((“用户名或者密码错误”,str(data.text))

def test_login_2:

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“jerry","password":“123456"}}

data = requests.post(url,data=payload)

self.assertEqual(‘200’,str(data.status_code))

self.assertIn((“用户名或者密码错误”,str(data.text))

def test_login_3:

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“tom","password":“000000"}}

data = requests.post(url,data=payload)

self.assertEqual(‘200’,str(data.status_code))

self.assertIn((“用户名或者密码错误”,str(data.text))

def test_login_4:

url=“http://127.0.0.1:8000/login_action/

payload={{"username":“jerry","password":“000000"}}

data = requests.post(url,data=payload)

self.assertEqual(‘200’,str(data.status_code))

self.assertIn((“查看购物车”,str(data.text))

def tearDown(self):

print("--------测试结束--------")

if __name__=='__main__':

#构造测试集

suite=unittest.TestSuite()

suite.addTest(mylogin(" test_login_1 "))

suite.addTest(mylogin(" test_login_2 "))

suite.addTest(mylogin(" test_login_3 "))

suite.addTest(mylogin(" test_login_4 "))

#运行测试集合

runner=unittest.TextTestRunner()

runner.run(suite)

程序通过self.assertEqual(‘200’,str(data.status_code)),来判断返回码是不是与预期的相同;通过self.assertIn((“用户名或者密码错误”,str(data.text))来判断返回的文本中是不是包括指定的字符串。测试用例test_login_1、test_login_2和test_login_3为错误情况的测试用来,将在返回页面中出现“用户名或者密码错误”的提示,test_login_4为正确的测试用例,登录满足需求,页面跳入到登录商品列表后页面,并且显示“查看购物车”的连接,所以我们以返回页面中是否存在“查看购物车”来判断测试是否成功。

4、数据驱动的自动化接口测试

数据驱动的自动化测试是HP在其著名的产品QTP中进行提出,并且成为了业内自动化测试的一个标准,所谓数据驱动可以理解为测试数据参数化。由于Python读取XML的技术相当成熟,我们可以把测试数据放在XML里来进行设计数据驱动的自动化接口测试。首先来看一下我是如何设计XML文件的。

loginConfig.xml

testcase001

用户登录

post

正确用户名,错误密码

http://127.0.0.1:8000/login_action/

{"username":"jerry","password":"12345"}

200

用户名或者密码错误

testcase002

用户登录

post

错误用户名,正确密码

http://127.0.0.1:8000/login_action/

{"username":"smith","password":"knyzh158"}

200

用户名或者密码错误

testcase003

用户登录

post

错误用户名,错误密码

http://127.0.0.1:8000/login_action/

{"username":"smith","password":"12345"}

200

用户名或者密码错误

testcase004

用户登录

post

正确用户名,正确密码

http://127.0.0.1:8000/login_action/

{"username":"jerry","password":"knyzh158"}

200

查看购物车

在这里是根标识,…表示一个测试用例,这里面有四个…对,分别上述表示四个测试用例。在…对中,有些数据是为了我们读起来比较方便,有些数据是程序中要是用的,下面来进行分别的介绍。

… :测试用例描述

:测试的URL地址(程序用到)

… :请求参数,用{}括起来,为符合Python字典格式的值参对(程序用到)

… :返回码(程序用到)

… :验证字符串(程序用到)

在py文件中我们通过调用from xml.dom import minidom来引入minidom类;dom = minidom.parse('loginConfig.xml')来获取所需要读取的xml文件; root = dom.documentElement来开始获取文件中节点的内容,然后通过语句aaa = root.getElementsByTagName('AAA')来获得文件中的所有叶子节点…对中的数据,因为文件中有多个…对,所以返回参数aaa为一个对象列表对,然后通过

for keyin aaa:

aaaValue = key.firstChild.data

print(aaaValue)

来获取每一个…对中的参数。但是由于XML文件中的标签往往不止一个,且对出现,真像我们文件所以loginConfig.xml中的…、…

、… …,所以我们可以这样来获得。

aaa = root.getElementsByTagName('AAA')

bbb = root.getElementsByTagName('BBB')

ccc = root.getElementsByTagName('CCC')

i = 0

for keyin AAA:

aaaValue = aaa[i].firstChild.data

bbbValue = bbb[i].firstChild.data

cccValue = ccc[i].firstChild.data

print(aaaValue)

print(bbbValue)

print(cccValue)

i =i+1

我们来看一下测试代码。

loginConfig.xml

#!/usr/bin/env python

#coding:utf-8

import unittest,requests

from xml.dom import minidom

class mylogin(unittest.TestCase):

def setUp(self):

print("--------测试结束--------")

#从XML中读取数据

dom = minidom.parse('loginConfig.xml')

root = dom.documentElement

TestIds = root.getElementsByTagName('TestId')

Titles = root.getElementsByTagName('Title')

Methods = root.getElementsByTagName('Method')

Descs = root.getElementsByTagName('Desc')

Urls = root.getElementsByTagName('Url')

InptArgs = root.getElementsByTagName('InptArg')

Results = root.getElementsByTagName('Result')

CheckWords =root.getElementsByTagName('CheckWord')

i = 0

mylists=[]

for TestId in TestIds:

mydicts={}

#获取每一个数据,形成字典

mydicts["TestId"] = TestIds[i].firstChild.data

mydicts["Title"] = Titles[i].firstChild.data

mydicts["Method"] = Methods[i].firstChild.data

mydicts["Desc"] = Descs[i].firstChild.data

mydicts["Url"] = Urls[i].firstChild.data

mydicts["InptArg"] = InptArgs[i].firstChild.data

mydicts["Result"] = Results[i].firstChild.data

mydicts["CheckWord"] =CheckWords[i].firstChild.data

mylists.append(mydicts)

i = i+1

self.mylists = mylists

def test_login(self):

for mylist in self.mylists:

payload = eval(mylist["InptArg"])

url=mylist["Url"]

#发送请求

try:

if mylist["Method"] == "post":

data = requests.post(url,data=payload)

elif mylist["Method"] == "get":

data = requests.get(url,params=payload)

else:

print ("Method 参数获取错误")

except Exception as e:

self.assertEqual(mylist["Result"],"404")

else:

self.assertEqual(mylist["Result"],str(data.status_code))

self.assertIn(mylist["CheckWord"],str(data.text))

def tearDown(self):

print("--------测试结束--------")

if __name__=='__main__':

#构造测试集

suite=unittest.TestSuite()

suite.addTest(mylogin("test_login"))

#运行测试集合

runner=unittest.TextTestRunner()

runner.run(suite)

setUp(self)主要把XML里的所有叶子节点数据获取到,放在一个名为mylists的列表变量中,并且返回给self.mylists变量,列表中每一项为一个字典类型的数据,key为XML里的所有叶子节点标签,key所对应的值为XML标签的内容。最后self. mylists传给每个测试函数中使用。

现在我们来看一下函数test_login(self)。

for mylistin self.mylists:把刚才在初始化里面定义的self.mylists每一项分别取出。

payload =eval(mylist["InptArg"]):为获取标签为InptArg中的数据,由于在XML格式定义的时候,这一项用{}括起来,里面是个值参对,由于mylist["InptArg"]返回的是一个{}括起来的具有字典格式的字符串,所以我们必须通过函数eval()进行转移成字典变量赋给payload。

url=mylist["Url"]为发送HTTP的地址。

然后通过判断mylist["Method"]是等于”post”还是等于”get”,选择使用data = requests.post(url,data=payload)或者data =requests.get(url,params=payload)来发送信息,接受信息放在变量data中。

最后通过self.assertEqual(mylist["Result"],str(data.status_code))来判断返回代码是否符合期望结果,以及self.assertIn(mylist["CheckWord"],str(data.text))期望代码mylist["CheckWord"]是否在返回内容str(data.text)中来判断测试是否成功。在这里特别指出在程序中except Exception as e中通过self.assertEqual(mylist["Result"],"404")来判断是否期望结果不存在。在这个项目中我们也加上类似的runtest.py来运行所有的测试用例。格式与前面相同,再次不在重复介绍。图3是加上注册接口测试代码的测试报告。

14982672_201708301056115GDD1.jpg

图3基于Python Requests的HTTP接口测试报告

5、进一步优化

细心的同学可能会发现,上面程序中setUp函数我们可以进行一些封装优化,我们建立一个单独的py文件getXML.py,内容如下:

getXML.py

#!/usr/bin/env python

#coding:utf-8

from xml.dom import minidom

class GetXML():

def getxmldata(xmlfile):

#从XML中读取数据

dom = minidom.parse(xmlfile)

root = dom.documentElement

TestIds = root.getElementsByTagName('TestId')

Titles = root.getElementsByTagName('Title')

Methods = root.getElementsByTagName('Method')

Descs = root.getElementsByTagName('Desc')

Urls = root.getElementsByTagName('Url')

InptArgs = root.getElementsByTagName('InptArg')

Results = root.getElementsByTagName('Result')

CheckWords =root.getElementsByTagName('CheckWord')

i = 0

mylists=[]

for TestId in TestIds:

mydicts={}

#获取每一个数据,形成字典

mydicts["TestId"] = TestIds[i].firstChild.data

mydicts["Title"] = Titles[i].firstChild.data

mydicts["Method"] = Methods[i].firstChild.data

mydicts["Desc"] = Descs[i].firstChild.data

mydicts["Url"] = Urls[i].firstChild.data

mydicts["InptArg"] = InptArgs[i].firstChild.data

mydicts["Result"] = Results[i].firstChild.data

mydicts["CheckWord"] =CheckWords[i].firstChild.data

mylists.append(mydicts)

i = i+1

return mylists

这样在loginTest.py改为setUp函数只需要改为:

loginConfig.xml

from getXML import GetXML #引入刚才建立的类

class mylogin(unittest.TestCase):

def setUp(self):

print("--------测试开始--------")

self.mylists = GetXML.getxmldata("loginConfig.xml")#调用类中的函数

…版权声明:51Testing软件测试网原创出品,转载时请务必以超链接形式标明文章原始出处、作者信息和本声明,否则将追究法律责任。

22/2<12

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值