!/usr/bin/env python

coding=utf-8

Todo:接口自动化测试

Author:归根落叶

Blog:http://this.ispenn.com

import json

import http.client,mimetypes

from urllib.parse import urlencode

import random

import time

import re

import logging

import os,sys

try:

import xlrd

except:

os.system('pip install -U xlrd')

import xlrd

try:

from pyDes import *

except ImportError as e:

os.system('pip install -U pyDes --allow-external pyDes --allow-unverified pyDes')

from pyDes import *

import hashlib

import base64

import smtplib

from email.mime.text import MIMEText

log_file = os.path.join(os.getcwd(),'log/liveappapi.log')

log_format = '[%(asctime)s] [%(levelname)s] %(message)s'

logging.basicConfig(format=log_format,filename=log_file,filemode='w',level=logging.DEBUG)

console = logging.StreamHandler()

console.setLevel(logging.DEBUG)

formatter = logging.Formatter(log_format)

console.setFormatter(formatter)

logging.getLogger('').addHandler(console)

获取并执行测试用例

def runTest(testCaseFile):

testCaseFile = os.path.join(os.getcwd(),testCaseFile)

if not os.path.exists(testCaseFile):

logging.error('测试用例文件不存在!!!')

sys.exit()

testCase = xlrd.open_workbook(testCaseFile)

table = testCase.sheet_by_index(0)

errorCase = []

correlationDict = {}

correlationDict['${hashPassword}'] = hash1Encode('123456')

correlationDict['${session}'] = None

for i in range(1,table.nrows):

correlationDict['${randomEmail}'] = ''.join(random.sample('abcdefghijklmnopqrstuvwxyz',6)) + '@automation.test'

correlationDict['${randomTel}'] = '186' + str(random.randint(10000000,99999999))

correlationDict['${timestamp}'] = int(time.time())

if table.cell(i,10).value.replace('\n','').replace('\r','') != 'Yes':

continue

num = str(int(table.cell(i,0).value)).replace('\n','').replace('\r','')

api_purpose = table.cell(i,1).value.replace('\n','').replace('\r','')

api_host = table.cell(i,2).value.replace('\n','').replace('\r','')

request_url = table.cell(i,3).value.replace('\n','').replace('\r','')

request_method = table.cell(i,4).value.replace('\n','').replace('\r','')

request_data_type = table.cell(i,5).value.replace('\n','').replace('\r','')

request_data = table.cell(i,6).value.replace('\n','').replace('\r','')

encryption = table.cell(i,7).value.replace('\n','').replace('\r','')

check_point = table.cell(i,8).value

correlation = table.cell(i,9).value.replace('\n','').replace('\r','').split(';')

for key in correlationDict:

if request_url.find(key) > 0:

request_url = request_url.replace(key,str(correlationDict[key]))

if request_data_type == 'Form':

dataFile = request_data

if os.path.exists(dataFile):

fopen = open(dataFile,encoding='utf-8')

request_data = fopen.readline()

fopen.close()

for keyword in correlationDict:

if request_data.find(keyword) > 0:

request_data = request_data.replace(keyword,str(correlationDict[keyword]))

try:

if encryption == 'MD5':

request_data = json.loads(request_data)

status,md5 = getMD5(api_host,urlencode(request_data).replace("%27","%22"))

if status != 200:

logging.error(num + ' ' + api_purpose + "[ " + str(status) + " ], 获取md5验证码失败!!!")

continue

request_data = dict(request_data,**{"sign":md5.decode("utf-8")})

request_data = urlencode(request_data).replace("%27","%22")

elif encryption == 'DES':

request_data = json.loads(request_data)

request_data = urlencode({'param':encodePostStr(request_data)})

else:

request_data = urlencode(json.loads(request_data))

except Exception as e:

logging.error(num + ' ' + api_purpose + ' 请求的数据有误,请检查[Request Data]字段是否是标准的json格式字符串!')

continue

elif request_data_type == 'Data':

dataFile = request_data

if os.path.exists(dataFile):

fopen = open(dataFile,encoding='utf-8')

request_data = fopen.readline()

fopen.close()

for keyword in correlationDict:

if request_data.find(keyword) > 0:

request_data = request_data.replace(keyword,str(correlationDict[keyword]))

request_data = request_data.encode('utf-8')

elif request_data_type == 'File':

dataFile = request_data

if not os.path.exists(dataFile):

logging.error(num + ' ' + api_purpose + ' 文件路径配置无效,请检查[Request Data]字段配置的文件路径是否存在!!!')

continue

fopen = open(dataFile,'rb')

data = fopen.read()

fopen.close()

request_data = '''

------WebKitFormBoundaryDf9uRfwb8uzv1eNe

Content-Disposition:form-data;name="file";filename="%s"

Content-Type:

Content-Transfer-Encoding:binary

%s

------WebKitFormBoundaryDf9uRfwb8uzv1eNe--

''' % (os.path.basename(dataFile),data)

status,resp = interfaceTest(num,api_purpose,api_host,request_url,request_data,check_point,request_method,request_data_type,correlationDict['${session}'])

if status != 200:

errorCase.append((num + ' ' + api_purpose,str(status),'http://'+api_host+request_url,resp))

continue

for j in range(len(correlation)):

param = correlation[j].split('=')

if len(param) == 2:

if param[1] == '' or not re.search(r'^[',param[1]) or not re.search(r']$',param[1]):

logging.error(num + ' ' + api_purpose + ' 关联参数设置有误,请检查[Correlation]字段参数格式是否正确!!!')

continue

value = resp

for key in param[1][1:-1].split(']['):

try:

temp = value[int(key)]

except:

try:

temp = value[key]

except:

break

value = temp

correlationDict[param[0]] = value

return errorCase

接口测试

def interfaceTest(num,api_purpose,api_host,request_url,request_data,check_point,request_method,request_data_type,session):

headers = {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',

'X-Requested-With':'XMLHttpRequest',

'Connection':'keep-alive',

'Referer':'http://' + api_host,

'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36'}

if session is not None:

headers['Cookie'] = 'session=' + session

if request_data_type == 'File':

headers['Content-Type'] = 'multipart/form-data;boundary=----WebKitFormBoundaryDf9uRfwb8uzv1eNe;charset=UTF-8'

elif request_data_type == 'Data':

headers['Content-Type'] = 'text/plain; charset=UTF-8'

conn = http.client.HTTPConnection(api_host)
if request_method == 'POST':
conn.request('POST',request_url,request_data,headers=headers)
elif request_method == 'GET':
conn.request('GET',request_url+'?'+request_data,headers=headers)
else:
logging.error(num + ' ' + api_purpose + ' HTTP请求方法错误,请确认[Request Method]字段是否正确!!!')
return 400,request_method
response = conn.getresponse()
status = response.status
resp = response.read()
if status == 200:
resp = resp.decode('utf-8')
if re.search(check_point,str(resp)):
logging.info(num + ' ' + api_purpose + ' 成功, ' + str(status) + ', ' + str(resp))
return status,json.loads(resp)
else:
logging.error(num + ' ' + api_purpose + ' 失败!!!, [ ' + str(status) + ' ], ' + str(resp))
return 2001,resp
else:
logging.error(num + ' ' + api_purpose + ' 失败!!!, [ ' + str(status) + ' ], ' + str(resp))
return status,resp.decode('utf-8')

获取md5验证码

def getMD5(url,postData):

headers = {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',

'X-Requested-With':'XMLHttpRequest'}

conn = http.client.HTTPConnection('this.ismyhost.com')

conn.request('POST','/get_isignature',postData,headers=headers)

response = conn.getresponse()

return response.status,response.read()

hash1加密

def hash1Encode(codeStr):

hashobj = hashlib.sha1()

hashobj.update(codeStr.encode('utf-8'))

return hashobj.hexdigest()

DES加密

def desEncode(desStr):

k = des('secretKEY', padmode=PAD_PKCS5)

encodeStr = base64.b64encode(k.encrypt(json.dumps(desStr)))

return encodeStr

字典排序

def encodePostStr(postData):

keyDict = {'key':'secretKEY'}

mergeDict = dict(postData, **keyDict)

mergeDict = sorted(mergeDict.items())

postStr = ''

for i in mergeDict:

postStr = postStr + i[0] + '=' + i[1] + '&'

postStr = postStr[:-1]

hashobj = hashlib.sha1()

hashobj.update(postStr.encode('utf-8'))

token = hashobj.hexdigest()

postData['token'] = token

return desEncode(postData)

发送通知邮件

def sendMail(text):

sender = 'no-reply@myhost.cn'

receiver = ['penn@myhost.cn']

mailToCc = ['penn@myhost.cn']

subject = '[AutomantionTest]接口自动化测试报告通知'

smtpserver = 'smtp.exmail.qq.com'

username = 'no-reply@myhost.cn'

password = 'password'

msg = MIMEText(text,'html','utf-8')
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = ';'.join(receiver)
msg['Cc'] = ';'.join(mailToCc)
smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.login(username, password)
smtp.sendmail(sender, receiver + mailToCc, msg.as_string())
smtp.quit()

def main():

errorTest = runTest('TestCase/TestCasePre.xlsx')

if len(errorTest) > 0:

html = '接口自动化定期扫描,共有 ' + str(len(errorTest)) + ' 个异常接口,列表如下:' + '

'

for test in errorTest:

html = html + '

'

html = html + '

接口 状态 接口地址 接口返回值
' + test[0] + ' ' + test[1] + ' ' + test[2] + ' ' + test[3] + '

'

#sendMail(html)

if name == 'main':

main()

接口自动化python的更多相关文章

  1. 接口自动化-python unittest+requests+HTMLrunner

    从2015年毕业入行软件测试,快满4年了,之前技术分享都在百度贴吧上面,现在正式开始在博客中记录工作技术,努力成长,加油 接口测试的步骤1.组装好该接口需要的参数数据2.使用get或post附带参数数 ...

  2. 接口自动化-python+requests+pytest+csv+yaml

    本套代码和逻辑 是本人的劳动成果,如果有转载需要标注, 非常适合公司做项目的同学!!!小白也可以学哦! 1.项目目录  2.公共方法的封装 2.1如果不用配置文件 可以使用这个方法进行封装--但是有一 ...

  3. 2020年第二期《python接口自动化+测试开发》课程,已开学!

    2020年第二期<python接口自动化+python测试开发>课程,12月15号开学! 主讲老师:上海-悠悠 上课方式:QQ群视频在线教学,方便交流 本期上课时间:12月15号-3月29 ...

  4. python接口自动化(单元测试方法)

    一.环境搭建 python +unittest+ requests实现http请求的接口自动化 Python的优势:语法简洁优美, 功能强大, 标准库跟第三方库灰常强大,建议大家事先了解一下Pytho ...

  5. python+request接口自动化框架

    python+request接口自动化框架搭建 1.数据准备2.用python获取Excel文件中测试用例数据3.通过requests测试接口4.根据接口返回的code值和Excel对比 但本章只讲整 ...

  6. Python接口自动化——soap协议传参的类型是ns0类型的要创建工厂方法纪要

    1:在Python接口自动化中,对于soap协议的xml的请求我们可以使用Suds Client来实现,其soap协议传参的类型基本上是有2种: 第一种是传参,不需要再创建啥, 第二种就是ns0类型的 ...

  7. 转载:python + requests实现的接口自动化框架详细教程

    转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实现的接口自动化框架详细教程 前段时间由于公司测试方向的转型,由 ...

  8. python接口自动化(十)--post请求四种传送正文方式(详解)

    简介 post请求我在python接口自动化(八)--发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等.我们要知道post请求四种传送正文方式首先需要先 ...

  9. python接口自动化(四)--接口测试工具介绍(详解)

    简介 “工欲善其事必先利其器”,通过前边几篇文章的介绍,大家大致对接口有了进一步的认识.那么接下来让我们看看接口测试的工具有哪些. 目前,市场上有很多支持接口测试的工具.利用工具进行接口测试,能够提供 ...

随机推荐

  1. Vue:将px转化为rem,适配移动端vant-UI等框架(px2rem-loader)

    转载:https://www.cnblogs.com/WQLong/p/7798822.html 1.下载lib-flexible 使用的是vue-cli+webpack,通过npm来安装的 npm ...

  2. ElasticSearch相关文章推荐

    1. ElasticSearch查询:http://www.cnblogs.com/ljhdo/p/4486978.html 2. Elasticsearch Java API 的使用—多条件查询:h ...

  3. GIT库代码管理规范

    GIT库代码管理规范 一. 规范要求 1. 每个项目建立单独的GIT库.每个GIT库包括两条线,命名规则如下: 开发线(测试):项目名称_DEV 生产线(正式):项目名称 2. 每条线只允许增量不允许 ...

  4. php Allocator Jemalloc TCMalloc那个内存分配器比较好?

    php Allocator Jemalloc TCMalloc那个内存分配器比较好? php一键安装脚本可以选择是否安装内存优化 You have 3 options for your Memory ...

  5. Javascript深入理解构造函数和原型对象

    1.在典型的oop的语言中,如java,都存在类的概念,类就是对象的模板,对象就是类的实例.但在js中不存在类的概念,js不是基于类,而是通过构造函数(constructor)和原型链(propoty ...

  6. 大数据学习路线分享-Hbase shell的基本操作完整流程

    HBase的命令行工具,最简单的接口,适合HBase管理使用,可以使用shell命令来查询HBase中数据的详细情况.安装完HBase之后,启动hadoop集群(利用hdfs存储),启动zookeep ...

  7. Django框架----用户认证auth模块

    一.auth模块 auth模块:针对auth_user表 创建超级管理用户命令: Python manage.py createsuperuser添加用户名添加密码(至少8位)确认密码添加邮箱(可为空 ...

  8. ubuntu 18.04下安装Hadoop

    在Ubuntu里装完Java环境后,接下来就开始学习安装Hadoop了,参照的是以下链接 https://blog.csdn.net/xuan314708889/article/details/805 ...

  9. 怎样从外网访问内网Node.js?

    本地安装了一个Node.js,只能在局域网内访问,怎样从外网也能访问到本地的Node.js呢?本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Node.js 默认安装的Node.js端口 ...

  10. word2vec原理(一) CBOW与Skip-Gram模型基础——转载自刘建平Pinard

    转载来源:http://www.cnblogs.com/pinard/p/7160330.html word2vec是google在2013年推出的一个NLP工具,它的特点是将所有的词向量化,这样词与 ...