Python接口测试之数据驱动(二十)

在接口的自动化测试中,客户端发送请求给服务端,在客户端发送请求的时候,包含了请求地址,请求方法,以及请求参数等数据,那么在接口的自动化测试中如何来分离这些请求地址和请求参数了,最好的方式是以数据驱动的方式分离到excel中,这样在excel中直接维护,即使后期由于某些原因修改了请求参数,在excel中修改也是很快的。在下来的案例中,一个系统,请求登录成功后,服务端返回token给客户端,客户端再次请求的时候需要带着这个token。关于HTTP的请求流程,token,session这些的处理,在前面的文章中有很详细的介绍,这里就不再介绍,下面会直接引入代码实战这部分。

首先安装处理excel的库,这里使用的Python版本是3.6,所以先安装第三方库,安装的命令为(已安装的会提示已存在):

安装xlrd库好之后,创建excel文件,把请求地址和请求参数分离到excel中,见excel的数据:

现在来编写读取excel中的数据,主要思路为读取excel的数据后,把数据类型转为字典的数据类型,并且是按行的方式读取,实现的代码:

#!/usr/bin/env python 
#-*-coding:utf-8-*-

#author:wuya


import  os
import  xlrd
import  json


def readExcel(rowx, filePath='data.xlsx'):
   '''
   读取excel中数据并且返回
   :parameter filePath:xlsx文件名称
   :parameter rowx:在excel中的行数
   '''
   book = xlrd.open_workbook(filePath)
   sheet = book.sheet_by_index(0)
   return sheet.row_values(rowx)

来读取excel中的数据,并且查看它的数据类型是否是期望的字典类型,调用readExcel函数后,见执行的结果截图:

在截图中可以看到,数据类型是列表,并且返回了所有的数据,再次编写函数,返回XX行的请求地址和请求参数,在excel中,存在的共同点是不管数据是在那一行,第二列永远是请求地址,第三列是请求参数,编写获取请求地址和请求参数的函数,见源码:

#!/usr/bin/env python 
#-*-coding:utf-8-*-

#author:wuya


import  os
import  xlrd
import  json


def readExcel(rowx, filePath='data.xlsx'):
   '''
   读取excel中数据并且返回
   :parameter filePath:xlsx文件名称
   :parameter rowx:在excel中的行数
   '''
   book = xlrd.open_workbook(filePath)
   sheet = book.sheet_by_index(0)
   return sheet.row_values(rowx)

def getUrl(rowx):
   '''
   获取请求URL
   :parameter rowx:在excel中的行数
   '''
   return readExcel(rowx)[1]

def getData(rowx):
   '''
   获取请求参数
   :parameter rowx:在excel中的行数
   '''
   return json.loads(readExcel(rowx)[2])

在上面代码中,新增了获取获取请求地址和请求参数,因为请求参数数据类型是字典,所以进行了反序列化的处理。

下来编写接口用例,见数据未分离的接口用例,见实现的代码:

import  unittest
import  time as t
import  requests

class ApiTest(unittest.TestCase):
   @classmethod
   def setUpClass(cls):
      t.sleep(1)

   @classmethod
   def tearDownClass(cls):
      pass

   def getHeaders(self):
      return {
         'Parkingwang-Client-Source':'ParkingWangAPIClientWeb',
         'Content-Type':'application/json;charset=UTF-8'}

   def test_login_001(self):
      '''登录业务:登录成功'''
      r=requests.post(
         url='http://180.97.80.42:9090/v5/login',
         json={"username":"6666666666","password":"8144ed050cd8d053f24a1e179d7529e17c3a2ba9cfcfcd7d3bda9ec6a8156758"},
         headers=self.getHeaders())
      self.assertEqual(r.status_code,200)
      self.assertEqual(r.json()['status'],0)
      with open('token','w') as f:
         f.write(r.json()['data']['token'])

   def getToken(self):
      with open('token','r') as f:
         return f.read()

   def test_login_002(self):
      '''登录业务:查看用户信息'''
      r=requests.post(
         url='http://180.97.80.42:9090/v5/infoGet',
         json={"token":self.getToken()},
         headers=self.getHeaders())
      self.assertEqual(r.status_code,200)
      self.assertEqual(r.json()['status'],0)

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

下来使用数据驱动的方式把请求地址和请求参数分离出来,见修改后的源码:

#!/usr/bin/env python 
#-*-coding:utf-8-*-

#author:wuya


import  os
import  xlrd
import  json



def readExcel(rowx, filePath='data.xlsx'):
   '''
   读取excel中数据并且返回
   :parameter filePath:xlsx文件名称
   :parameter rowx:在excel中的行数
   '''
   book = xlrd.open_workbook(filePath)
   sheet = book.sheet_by_index(0)
   return sheet.row_values(rowx)

def getUrl(rowx):
   '''
   获取请求URL
   :parameter rowx:在excel中的行数
   '''
   return readExcel(rowx)[1]

def getData(rowx):
   '''
   获取请求参数
   :parameter rowx:在excel中的行数
   '''
   return json.loads(readExcel(rowx)[2])

import  unittest
import  time as t
import  requests

class ApiTest(unittest.TestCase):
   @classmethod
   def setUpClass(cls):
      t.sleep(1)

   @classmethod
   def tearDownClass(cls):
      pass

   def getHeaders(self):
      return {
         'Parkingwang-Client-Source':'ParkingWangAPIClientWeb',
         'Content-Type':'application/json;charset=UTF-8'}

   def test_login_001(self):
      '''登录业务:登录成功'''
      r=requests.post(
         url=getUrl(1),
         json=getData(1),
         headers=self.getHeaders())
      self.assertEqual(r.status_code,200)
      self.assertEqual(r.json()['status'],0)
      with open('token','w') as f:
         f.write(r.json()['data']['token'])

   def getToken(self):
      with open('token','r') as f:
         return f.read()

   def test_login_002(self):
      '''登录业务:查看用户信息'''
      r=requests.post(
         url=getUrl(2),
         json=getData(2),
         headers=self.getHeaders())
      print(r.text)
      self.assertEqual(r.status_code,200)
      self.assertEqual(r.json()['status'],0)

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

数据分离后,维护数据统一是在excel中,第二个接口这些成功后,直接失败,见失败信息:

问题在于数据分离后,test_login_002的测试用例请求数据与登录成功后的token不一致,导致了错误,那么如何对这些动态参数进行处理了,处理的思路是:

  1. 从excel中读取数据
  2. 对如token这些动态参数再次进行赋值
  3. 返回赋值后的数据
  4. 调用赋值后的数据

依据如上的思路,对getToken方法进行修改,对token再次进行赋值,新增setToken方法,见修改后的该方法代码:

def getToken(self):
   '''读取token文件里面的内容'''
   with open('token','r') as f:
      return f.read()

def setToken(self,rowx):
   '''
   对动态参数token进行赋值
   :parameter rowx:在excel中的行数
   '''
   dict1=getData(rowx)
   #对tokek赋值
   dict1['token']=self.getToken()
   return dict1

在test_login_002的接口用例中,调用请求参数直接调用setToken方法,这样就不会出现错误了,见完整的代码:

#!/usr/bin/env python 
#-*-coding:utf-8-*-

#author:wuya


import  os
import  xlrd
import  json
import  unittest
import  time as t
import  requests


def readExcel(rowx, filePath='data.xlsx'):
   '''
   读取excel中数据并且返回
   :parameter filePath:xlsx文件名称
   :parameter rowx:在excel中的行数
   '''
   book = xlrd.open_workbook(filePath)
   sheet = book.sheet_by_index(0)
   return sheet.row_values(rowx)

def getUrl(rowx):
   '''
   获取请求URL
   :parameter rowx:在excel中的行数
   '''
   return readExcel(rowx)[1]

def getData(rowx):
   '''
   获取请求参数
   :parameter rowx:在excel中的行数
   '''
   return json.loads(readExcel(rowx)[2])


class ApiTest(unittest.TestCase):
   @classmethod
   def setUpClass(cls):
      t.sleep(1)

   @classmethod
   def tearDownClass(cls):
      pass

   def getHeaders(self):
      return {
         'Parkingwang-Client-Source':'ParkingWangAPIClientWeb',
         'Content-Type':'application/json;charset=UTF-8'}

   def test_login_001(self):
      '''登录业务:登录成功'''
      r=requests.post(
         url=getUrl(1),
         json=getData(1),
         headers=self.getHeaders())
      self.assertEqual(r.status_code,200)
      self.assertEqual(r.json()['status'],0)
      with open('token','w') as f:
         f.write(r.json()['data']['token'])

   def getToken(self):
      '''读取token文件里面的内容'''
      with open('token','r') as f:
         return f.read()

   def setToken(self,rowx):
      '''
      对动态参数token进行赋值
      :parameter rowx:在excel中的行数
      '''
      dict1=getData(rowx)
      #对tokek赋值
      dict1['token']=self.getToken()
      return dict1

   def test_login_002(self):
      '''登录业务:查看用户信息'''
      r=requests.post(
         url=getUrl(2),json=self.setToken(2),headers=self.getHeaders())
      self.assertEqual(r.status_code,200)
      self.assertEqual(r.json()['status'],0)

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

原文发布于微信公众号 - Python自动化测试(wuya-python)

原文发表时间:2018-06-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

AggregateCacheDependency、CacheDependency、SqlCacheDependency Asp.net 2.0和Sql Server的缓存管理和使用ObjectBuil

       这两天 PetShop is Evil?等对PetShop 的讨论很多,我在这里也发一篇凑凑热闹。我下面主要是对Asp.net 2.0新增的缓存管...

21680
来自专栏逸鹏说道

01.SQLServer性能优化之---水平分库扩展

汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 第一次引入文件组的概念:http://www.c...

35470
来自专栏散尽浮华

Mysql主从同步(1)-主从/主主环境部署梳理

Mysql复制概念说明 Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一...

39850
来自专栏idba

如何确保应用程序运行的唯一性

一 简介 相信大家在开发脚本或者写程序的时候 ,大多会遇到如何判断已经有程序在运行的情况。比如设计备份binlog ,由于某个实例产生的binlog 数量大...

9620
来自专栏程序员的SOD蜜

(PDF.NET框架实例讲解)将存储过程映射为实体类

PDF.NET数据开发框架可以将表,视图,表值函数,自定义的查询语句和存储过程映射为实体类,在上一篇《(PDF.NET框架实例讲解)将任意复杂的SQL查询映射成...

251100
来自专栏小狼的世界

重新认识wget

Wget是平时经常会用到的一个工具,这个工具其实有着非常丰富的参数和配置,能够实现很强大的功能。比较常用的一个就是抓站或者为网站做镜像。

12010
来自专栏python学习之旅

Python笔记(十二):操作数据库

(一)      前言     本文说明如何连接Oracle、MySQL、sqlserver,以及执行sql、获取查询结果等。 (二)      DB-API ...

39990
来自专栏芋道源码1024

Java中高级面试题(5)

线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资源...

9700
来自专栏腾讯技术工程官方号的专栏

鹅厂 TDSQL XA 事务隔离级别的奥秘

TDSQL XA 全局事务(global transaction)是指用户客户端连接到 TDSQL XA 分布式数据库系统后发起和执行的事务,也就是 TDSQL...

52020
来自专栏喵了个咪的博客空间

基于PhalApi2的Redis拓展

基于PhalApi2的Redis拓展 ? 前言 Redis在PHP开发中运用场景已经无处不在,小到简单缓存大到数据库或消息队列都可以使用Redis来进行实现,基...

31950

扫码关注云+社区

领取腾讯云代金券