框架结构如下:

Test_Api_Project
|
|---base.py
|---base_api
|   |---register_api.py

|   |---send_sms_code_api.py
|---settings.py
|---test_case
|   |---test_register_api.py

|---utilities

|  |---conn_db.py

|  |---user.py

一、先说settings配置文件,与WEB端自动化类似,settings文件中存放整个项目的配置,如:被测项目域名、数据库地址、redis地址、APP版本号、请求头等。

# env config
ENV = 'test' APP_VERSION = '2.3.7' HEADERS = {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'} # test url test config
API_TEST_BASE_URL = "http://api.abc.com" # redis config
REDIS_HOST = ''
REDIS_PORT = '' # mysql config
DB_HOST = ''
DB_PORT = ''
DB_USER = ''
DB_PASSWORD = ''

二、base.py

该文件中主要是对测试url的处理、对常用的请求类型重新封装(如:GET、POST等)

# -*- coding:utf-8 -*-
import json,requests
import settings class BaseApi(object):
url = ""
base_url= settings.API_TEST_BASE_URL def __init__(self,url_params=None):
if not url_params:
url_params = []
self.url_params = url_params
self.response = None
self.base_url = self.base_url # 拼接url
def api_url(self):
if not self.url:
raise RuntimeError("no url been set")
return self._get_url() def _get_url(self):
format_url = self.url.format(self.url_params)
return "{0}{1}".format(self.base_url, format_url) # 封装POST请求类型
def post(self, data=None):
if not data:
data = {}
base_param = self.build_base_param()
custom_param = self.build_custom_param(data)
data.update(base_param)
data.update(custom_param)
self.response = requests.post(url=self.api_url(), data=data, headers=settings.HEADERS)
return self.response # 封装GET请求类型
def get(self,data=None):
if not data:
data={}
base_param = self.build_base_param()
custom_param = self.build_custom_param(data)
data.update(base_param)
data.update(custom_param)
response = requests.get(url=self.api_url(),params=data)
return self.response # 获取回参中状态码
def get_code(self):
if self.response:
return json.loads(self.response.text)['code'] # 获取HTTP状态码
def get_status_code(self):
if self.response:
return self.response.status_code # 获取回参中message
def get_response_message(self):
if self.response:
return json.loads(self.response.text)['msg'] # 所有接口共有的入参,比如:app_version、token等
def build_base_param(self):
return {
"app_version": SETTINGS.APP_VERSION,
"token":""
} # 被测接口除公共参数外所需的其余参数
def build_custom_param(self, data):
return {}

三、conn_db.py 连接数据库

import pymysql.cursors,settings

def execute(sql, params=None, db='', is_fetchone=True):
# Connect to the database
connection = pymysql.connect(host=settings.DB_HOST,
port=settings.DB_PORT,
user=settings.DB_USER,
password=settings.DB_PASSWORD,
db=db,
autocommit=True,
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
try:
with connection.cursor() as cursor:
cursor.execute(sql, params)
if is_fetchone:
return cursor.fetchone()
else:
return cursor.fetchall()
finally:
connection.close()

user.py文件主要是对数据库中用户相关的一些操作

# -*- coding:utf-8 -*-
import db def get_sms_captcha(mobile):
# 获取短信验证码
sms_captcha = db.execute('select code from send_sms_code where mobile=%s order by id desc',params=(mobile))
return sms_captcha['code'] def delete_user(mobile):
# 删除用户
db.execute('delete from user where mobile=%s',params=(mobile))

四、下面以注册接口为例子

因注册时需要获取短信验证码,所以除了调用注册接口之外,还需要调用获取短信验证码皆苦,在base_api下新建register_api.py、send_sms_code_api.py,内容如下:

register_api.py

# -*- coding:utf-8 -*-
from base_api.base_api import BaseApi
import settings class RegisterApi(BaseApi):
url = '/home/register' #对BaseApi类中build_custom_param方法重写
def build_custom_param(self, data):
return {'login_name':data['login_name'],'password':data['password'],'code':data['code'],'nickname':data['nickname']}

send_sms_code_api.py

# -*- coding:utf-8 -*-
from base_api.base_api import BaseApi
import settings class SendSmsCaptcha(BaseApi):
url = '/user/sendsms' def build_custom_param(self, data):
return {'type': data['type'], 'phone': data['phone']}

对两个接口的url地址和所需要的入参都已经封装好了,接下来开始写case。

在test_case下新建test_register_api.py

下面是一个注册成功的例子

# -*- coding:utf-8 -*-
from unittest import TestCase
from base_api.register_api import RegisterApi
from base_api.send_sms_code_api import SendSmsCaptcha
from utilities import user
import settings,json class TestRegisterApi(TestCase):
new_mobile = ''
password = '123abc'
nick_name = 'XiangXi' def test_register_success(self):
# 调用发送短信验证码接口
send_sms_code_api = SendSmsCaptcha()
send_sms_code_api.post({'type':'register','phone':self.new_mobile}) # 校验发送短信验证码接口HTTP状态码为200
self.assertEqual(send_sms_code_api.get_status_code(),200) # 校验发送短信验证码接口反参中code为0,代表成功(不同项目该字段值不一定为0)
self.assertEqual(send_sms_code_api.get_code(),0) # 通过数据库获取短信验证码
sms_code = user.get_sms_captcha(self.new_mobile) # 调用注册接口
register_api = RegisterApi()
response = register_api.post({'login_name':self.new_mobile,'password':self.password,'code':sms_code,'nickname':self.nick_name}) # 校验注册接口HTTP状态码为200
self.assertEqual(send_sms_code_api.get_status_code(),200) # 校验注册接口反参中code为0
self.assertEqual(register_api.get_code(),0) # 校验反参中手机号、登录名与用户昵称是否与入参值一样
identity_obj = json.loads(response.content)['result']['identity_obj']
self.assertEqual(identity_obj['nickname'],self.nick_name)
self.assertEqual(identity_obj['login_name'],self.new_mobile)
self.assertEqual(identity_obj['mobilephone'],self.new_mobile) def tearDown(self):
user.delete_user(self.new_mobile)

最后和WEB端类似,通过teardown()方法将新注册的用户在数据库中删除,防止该手机号下次执行case时候报手机号已被注册。

为了更好了验证通过接口注册的用户信息,也可以调用登录接口测试一下注册接口反参中的用户名是否可以正常登陆返回token。

五、如果调用接口的前提需要用户登录,那么就需要BaseApi类中build_base_param方法中的token有一个有效的值,否则调用接口时可能会提示token错误或者用户未登录等,这种情况下可以新建一个LoginBaseApi类,继承BaseApi,代码如下:

假设对登录接口已经进行了封装,入参为login_name和password

# -*- coding:utf-8 -*-
from base_api.base_api import BaseApi
from base_api.login_api import LoginApi class LoginBaseApi(BaseApi):
def __init__(self, login_name,password, *args, **kwargs):
super(LoginBaseApi, self).__init__(*args, **kwargs)
self.login_name = login_name
self.password = password def build_base_param(self):
base_param = super(LoginBaseApi, self).build_base_param()
response = LoginApi().post(self.login_name, self.password)
base_param['token'] = token
return base_param

这时,底层类就有两个,一个是BaseApi() 一个是LoginBaseApi(),需要登录的接口在封装入参时继承LoginBaseApi,不需要登录的接口继承BaseApi

不同项目接口的入参格式,反参格式可能会不同,仅供参考

Python做接口自动化测试框架的更多相关文章

  1. python 做接口自动化测试框架设计

    1,明确什么叫自动化测试,什么叫接口自动化测试,如何设计接口测试用例,已登录为例 自动化测试:解放人力来自动完成规定的测试. 自动化测试分层模型:UI层,不论WEB端还是移动端,都是基于页面元素的识别 ...

  2. python+requests接口自动化测试框架实例详解

    python+requests接口自动化测试框架实例详解   转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实 ...

  3. python版接口自动化测试框架源码完整版(requests + unittest)

    python版接口自动化测试框架:https://gitee.com/UncleYong/my_rf [框架目录结构介绍] bin: 可执行文件,程序入口 conf: 配置文件 core: 核心文件 ...

  4. python之接口自动化测试框架

    梳理python+unittest接口自动化测试框架的思路: 1.确定目录: cases:存放测试用例的py文件:config:存放一些数据库,环境地址等固定不变的信息: core:核心的文件, ca ...

  5. 【接口自动化】Python+Requests接口自动化测试框架搭建【一】

    公司项目启用新框架,前后端分离,所以接口测试成为测试工作中不可缺失的一个环节,现在将从0开始搭建接口自动化测试框架的路程,一步步记录下来. 开发语言我们采用Python+第三方库Requests,测试 ...

  6. Python Api接口自动化测试框架 excel篇

    工作原理: 测试用例在excel上编辑,使用第三方库xlrd,读取表格sheet和内容,sheetName对应模块名,Jenkins集成服务发现服务moduleName查找对应表单,运用第三方库req ...

  7. python+requests接口自动化测试框架实例详解教程

    1.首先,我们先来理一下思路. 正常的接口测试流程是什么? 脑海里的反应是不是这样的: 确定测试接口的工具 —> 配置需要的接口参数 —> 进行测试 —> 检查测试结果(有的需要数据 ...

  8. 【接口自动化】Python+Requests接口自动化测试框架搭建【三】

    经过上两篇文章的讲解,我们已经完成接口自动化的基础框架,现在开始根据实际项目丰满起来. 在PyCharm中新建项目,项目工程结构如下: config:配置文件夹,可以将一些全局变量放于配置文件中,方便 ...

  9. 基于Python的接口自动化测试框架

    项目背景 公司内部的软件采用B/S架构,目的是进行实验室的数据存储.分析.管理. 大部分是数据的增删改查,但是由于还在开发阶段,所以UI的变化非常快,难以针对UI进行自动化测试,那样会消耗大量的精力与 ...

随机推荐

  1. jQuery的parseHTML方法

    // data html字符串    // context 如果指定了context,则碎片将在此范围内被创建,默认是document    // keepScripts 如果是true,则将有scr ...

  2. 题目1016:火星A+B(进制新问题)

    题目链接:http://ac.jobdu.com/problem.php?pid=1016 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...

  3. LeetCode 36 Valid Sudoku(合法的数独)

    题目链接: https://leetcode.com/problems/valid-sudoku/?tab=Description   给出一个二维数组,数组大小为数独的大小,即9*9  其中,未填入 ...

  4. sencha touch 在安卓中横屏、竖屏切换 应用崩溃问题

    答案来至于 Sencha Touch 交流 @周旭 这是由于横竖屏转换导致activity重跑onCreate方法导致的,有两种解决方案:1.横竖屏转换的时候不要重新跑onCreate方法,这个可以在 ...

  5. Artech的MVC4框架学习——第四章Model元数据的解析

    总结: 第一Model元数据是针对 数据类型的一种表述信息. 第二Model元数据作用:控制数据类型本身及其成员,通过相应的特性,在view中 为绑定的数据(Model)实现模版化的html呈现. 第 ...

  6. thinkphp结合layui上传图片

    简单示例: <script type="text/javascript"> layui.use(['form', 'layedit','element', 'layda ...

  7. SSH客户端提示 用户密钥未在远程主机上注册

    今天在一台使用已久的内网服务器上面帮一位新同事添加账户,添加完成之后就把账号交付于他,过了10分钟他告诉我说无法登陆,觉得很诧异 这么轻车熟路的 这么会 登陆不上去了,自己也用Xshell 登陆了一下 ...

  8. codeforces#518 Div2 ABCDE

    A---Birthday http://codeforces.com/contest/1068/problem/A 题意: 有n种硬币,m个人.m个人要给Ivan送硬币,每个人送的硬币都要互不相同但数 ...

  9. CVPR2018资源汇总

    CVPR 2018大会将于2018年6月18~22日于美国犹他州的盐湖城(Salt Lake City)举办. CVPR2018论文集下载:http://openaccess.thecvf.com/m ...

  10. Python的一个命名空间冲突,关于from-import机制

    from os import * #import os def foo(): a = listdir("trainingDigits") b = open("traini ...