python+requests+excel 接口自动化测试框架(二)

前言:该篇重点讲数据依赖、cookie处理和发送邮件(部分方法在第一篇中已经编写)

一、 数据依赖简单说明

接口B的请求数据依赖于接口A的返回数据,即为数据依赖。比如说:接口B(图2)是一个支付接口,接口A(图1)是一个订单提交接口。接口B中请求数据trade_number的值来源于接口A的响应数据out_trade_no的值

                                                      图 1

                                                       图 2

二、 解决数据依赖方法封装

创建文件 dataconfig/dependent_data.py

from utils.operation_excel import OperationExcel
from base.run_method import RunMethod
from dataconfig.get_data import GetData
import json
from jsonpath_rw import jsonpath,parse


class DependentData(object):
    def __init__(self, case_id):
        self.opera_excel = OperationExcel()
        self.case_id = case_id
        self.data = GetData()

    # 通过case_id获取该case_id的整行数据
    def get_case_line_data(self):
        rows_data = self.opera_excel.get_rows_data(self.case_id)
        return rows_data

    # 执行依赖测试,获取结果
    def run_dependent(self):
        run_method = RunMethod()
        row_num = self.opera_excel.get_row_num(self.case_id)
        request_data = self.data.get_data_from_json(row_num)
        method = self.data.get_request_method(row_num)
        url = self.data.get_url(row_num)
        res = run_method.run_main(method, url, request_data)
        return json.loads(res)

    # 根据依赖的key去获取执行依赖测试的case响应,然后返回
    def get_data_for_key(self, row):
        # 依赖的返回数据的格式要注意层级关系
        depend_data = self.data.get_depend_key(row)
        response_data = self.run_dependent()
        # jsonpath_rw类似于xpath
        json_exe = parse(depend_data)
        # 从响应数据结果集中找到依赖的返回数据
        model = json_exe.find(response_data)
        # 类似于for循环,i是字典类型的
        return [math.value for math in model][0]

三、 cookie处理简单说明

访问某些接口前需要登录,即需要携带cookies才能访问成功,则需要先访问登录接口,然后把cookies信息存储在json文件中

实例:接口A(登录接口)请求后,自动调用接口B。接口B使用接口A中的token作为请求数据,且返回cookies。访问接口C时,必须携带cookies才能访问成功,如下图所示,接口顺序依次是A、B和C

用例修改如下,运行时会判断“是否携带header”字段的值:

四、 封装处理cookies方法

1. 创建 utils/operation_header.py

import requests
import json
from utils.operation_json import OperationJson


class OperationHeader(object):
    def __init__(self, response):
        self.response = json.loads(response)

    # 获取登录返回的响应数据中url的内容,根据实际接口情况来编写该方法
    def get_response_url(self):
        url = self.response['data']['url'][0]
        return url

    # 获取cookie的jar文件
    def get_cookie(self):
        # 请求数据中除了url,还有另外两个参数callback和_
        url = self.get_response_url()+"&callback=jQuery21008240514814031887_1508666806688&_=1508666806689"
        cookie = requests.get(url).cookies
        return cookie

    def write_cookie(self):
        cookie = requests.utils.dict_from_cookiejar(self.get_cookie())
        op_json = OperationJson()
        op_json.write_data(cookie)

2. 创建空文件data/cookie.json ,运行程序后该文件中存储cookies的值

五、 发送邮件

创建文件 utils/send_mail.py

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.mime.text import MIMEText
import smtplib


class SendEmail(object):
    def send_mail(self, user_list, subject, content, file):

        smtpserver = 'smtp.qq.com'
        user = '[email protected]'
        password = "XXX"
        sender = '[email protected]'
        receives = user_list

        # 构造邮件对象
        msg = MIMEMultipart('mixed')
        # 定义邮件的标题
        subject = subject
        # HTML邮件正文,定义成字典
        msg['Subject'] = Header(subject, "utf-8")
        msg['From'] = sender
        msg['To'] = ','.join(receives)
        # 构造文字内容
        text_plain = MIMEText(content)
        msg.attach(text_plain)
        # 构造附件
        text_attr = MIMEText(file, 'base64', 'utf-8')
        text_attr["Content-Type"] = 'application/octet-stream'
        text_attr['Content-Disposition'] = 'attachment; filename = "report.xls"'
        msg.attach(text_attr)

        # 邮箱设置时勾选了SSL加密连接,进行防垃圾邮件,SSL协议端口号要使用465???
        smtp = smtplib.SMTP_SSL(smtpserver, 465)
        # 向服务器标识用户身份
        smtp.helo(smtpserver)
        # 向服务器返回确认结果
        smtp.ehlo(smtpserver)
        # 登录邮箱的账号和授权密码
        smtp.login(user, password)

        print("start send email...")
        # 开始进行邮件的发送,msg表示已定义的字典
        smtp.sendmail(sender, receives, msg.as_string())
        smtp.quit()
        print("send email end")

    def send_main(self, pass_list, fail_list):
        pass_num = float(len(pass_list))
        fail_num = float(len(fail_list))
        count_num = pass_num + fail_num
        pass_result = "%.2f%%" % (pass_num/count_num*100)
        fail_result = "%.2f%%" % (fail_num / count_num * 100)

        user_list = ["[email protected]"]
        subject = "接口自动化测试报告"
        content = "此次一共运行接口个数为%s个,通过个数为%s个,失败个数为%s,通过率为%s,失败率为%s" % (count_num, pass_num, fail_num, pass_result, fail_result)
        file = open("../data/imooc_case.xls", 'rb').read()
        self.send_mail(user_list, subject, content, file)

六、 连接数据库

创建文件 utils/connect_db.py

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


class OperationMysql(object):
    def __init__(self):
        self.connect = pymysql.Connect(
            host='localhost',
            port=3306,
            user='admin',
            passwd='111111',
            db='MySQL',
            charset='utf8'
        )
        self.cur = self.connect.cursor()

    # 查询一条数据
    def search_one(self, sql):
        # 用execute系列方法执行sql
        self.cur.execute(sql)
        # fetchone()每次获取一条记录
        result = self.cur.fetchone()
        # result = self.cur.fetchall()
        result = json.dumps(result)
        return result

七、 修改run_test.py文件(添加数据依赖、cookies处理和发送邮件)

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from base.run_method import RunMethod
from dataconfig.get_data import GetData
from dataconfig.dependent_data import DependentData
from utils.operation_header import OperationHeader
from utils.operation_json import OperationJson
from utils.common_util import CommonUtil
from utils.send_mail import SendEmail


class RunTest(object):
    def __init__(self):
        self.data = GetData()
        self.run_method = RunMethod()
        self.com_util = CommonUtil()
        self.send_mail = SendEmail()

    # 执行程序
    def go_on_run(self):
        pass_count = []
        fail_count = []
        # 下标从0开始
        rows_count = self.data.get_case_lines()
        # 从下标1开始循环取数据,忽略第一行表头数据
        for i in range(1, rows_count):
            is_run = self.data.get_is_run(i)
            if is_run:
                method = self.data.get_request_method(i)
                url = self.data.get_url(i)
                # data = self.data.get_request_data(i)
                data = self.data.get_data_from_json(i)
                headers = self.data.get_is_header(i)
                # expect = self.data.get_expect_data_from_mysql(i)
                expect = self.data.get_expect_data(i)
                depend_case = self.data.get_is_depend(i)
                '''
                暂时没用到数据依赖
                '''
                if depend_case != None:
                    self.depend_data = DependentData(depend_case)
                    # 获取依赖的响应数据
                    depend_response_data = self.depend_data.get_data_for_key(i)
                    # 获取数据依赖字段
                    depend_key = self.data.get_depend_field(i)
                    # 请求数据中的“数据依赖字段"的值更新成“依赖的返回数据”
                    data[depend_key] = depend_response_data
                if headers == "write":
                    res = self.run_method.run_main(method, url, data)
                    op_header = OperationHeader(res)
                    op_header.write_cookie()

                elif headers == "yes":
                    op_json = OperationJson('../data/cookie.json')
                    cookie = op_json.get_data('apsid')
                    cookies = {
                        'apsid': cookie
                    }
                    res = self.run_method.run_main(method, url, data, cookies)

                else:
                    res = self.run_method.run_main(method, url, data)

                if self.com_util.is_contain(expect, res):
                    self.data.write_result(i, 'pass')
                    pass_count.append(i)
                else:
                    self.data.write_result(i, res)
                    fail_count.append(i)
        print("成功的用例数:", len(pass_count))
        print("失败的用例数:", len(fail_count))
        self.send_mail.send_main(pass_count, fail_count)


if __name__ == '__main__':
    run = RunTest()
    run.go_on_run()

运行结果:

备注:数据依赖未调试通,暂时删除了需要用到数据依赖的接口

八、 项目目录:

九、 持续集成

1. 使用jenkins,配置项目信息。具体步骤:新建任务(选择第一个自由风格)->使用自定义的工作空间(目录是要运行的文件所在的路径),如图1->构建选择“执行windows批处理命令”,并输入如下命令,如图2

                                                                                                     图1

                                                                  图2

2.运行结果如下:

3.报错解决办法:

https://blog.csdn.net/changyixue/article/details/100707205

发布了26 篇原创文章 · 获赞 24 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/changyixue/article/details/100652755