Python+excel+unittest+ddt+requests数据驱动接口自动化

1、环境准备

Python3、request、unittest、ddt、mock、cx_Oracle、pymysql、openpyxl

2、实现的功能

对requests请求方法封装

获取Excel数据读取数据及测试 结果写入方法的封装

HTTPTestRunner生产测试报告,进行自动邮件发送

token使用获取依赖的方法实现

logging日志文件写入

对读取数据库方法封装

加入mock测试

项目结构

 

 

 

excel测试数据

 

 

 

requests请求方法的封装

对get、post、put、delete方法进行封装

import json,requests
from Base.read_db import oracle

class BaseRequest():

    def send_post(self,url,data,headers=None):
        """post请求"""
        res = requests.post(url=url,data=data,headers=headers).text
        return res

    def sen_get(self,url,data =None,headers=None):
        """get请求"""
        res = requests.get(url,params =data,headers=headers).text
        return res
    def send_put(self,url,data =None,headers=None):
        """put请求"""
        res = requests.put(url=url, data=data, headers=headers).text
        return res
    def send_delete(self,url,data =None,headers=None):
        """delete请求"""
        res = requests.delete(url,data=data,headers=headers).text
        return res

    def run_man(self,method,url,data=None,headers=None):
        """执行方法,传递method、URL、data参数"""
        if method == "post":
            res = self.send_post(url,data,headers)
        elif method == "put":
            res = self.send_put(url,data,headers)
        elif method == "delete":
            res = self.send_delete(url,data,headers)
        else:
            res = self.sen_get(url,data,headers)
        try:
            res=json.loads(res)
        except:
            print('解析失败')
        return res

 

读取oracle,MySQL方法封装

读取数据库中文乱码解决,开头增加 os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.AL32UTF8'

import pymysql.cursors
import os,pymysql
import cx_Oracle
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.AL32UTF8'
class ReadDB():

    def read_oracle(self,sql):
        '''查询oracel的数据库'''
        conn = cx_Oracle.connect('', '', '')
        cursor = cx_Oracle.Cursor(conn)
        cursor.execute(sql)
        result = cursor.fetchall()
        cols = [d[0] for d in cursor.description]
        a = []
        for row in result:
            b = dict(zip(cols, row))
            a.append(b)
        cursor.close()
        conn.close()
        return a

    def del_mysqldb(self,sql,name):
        '''MySQL数据库删除数据'''
        db = pymysql.connect(host='', port=3306, user='', passwd='', db=name, charset='utf8',
                             cursorclass=pymysql.cursors.DictCursor)
        cursor = db.cursor()
        cursor.execute(sql)
        db.commit()
        print(cursor.rowcount,'记录删除条数')

    def read_mysqldb(self,sql,name):
        '''MySQL数据库查询数据'''
        db = pymysql.connect(host='', port=, user='', passwd='', db=name, charset='utf8',
                             cursorclass=pymysql.cursors.DictCursor)
        cursor = db.cursor()
        cursor.execute(sql)
        data = cursor.fetchall()
        return data



oracle = ReadDB()

if __name__ == "__main__":

    # 
    # print(oracle.read_oracle(sql)[0]["CONTENT"])

    sql = "'"

    print(oracle.read_mysqldb(sql,'hsp_user')) 

 

获取依赖方法封装

获取Excel中的数据使用split()方法进行拆分,使用Excel获取单元格数据的方法获取依赖数据

import sys,os,json
from Base.read_excel import readExcel
from jsonpath_rw import parse

pwd = os.getcwd()
sys.path.append(pwd)
base_path=os.path.abspath(os.path.dirname(pwd)+os.path.sep+".")


def split_data(data):
    '''拆分单元格数据'''
    list_data = data.split(">")
    case_id = list_data[0]
    row_num = list_data[1]
    rule_data = list_data[2]
    return case_id,row_num,rule_data


def depend_data(data):
    '''获取依赖结果集'''
    case_id = split_data(data)[0]
    num = split_data(data)[1]
    row_number = readExcel.get_rows_number(case_id)
    rul_data = readExcel.get_cell_value(row_number,int(num))
    return rul_data


def get_depend_data(res_data,key):
    '''获取依赖字段'''
    res_data = json.loads(res_data)
    json_exe = parse(key)
    madle = json_exe.find(res_data)
    return [math.value for math in madle][0]

def get_data(data):
    '''获取依赖数据'''
    res_data = depend_data(data)
    # print(res_data)
    rule_data = split_data(data)[2]
    return get_depend_data(res_data,rule_data)




if __name__ == "__main__":
    data = 'case_001>15>data'

    print(get_data(data))

  

测试用例使用unittest+ddt

# -*- coding: utf-8 -*-
import json
import unittest,os,sys

import mock
from ddt import ddt,data
pwd = os.getcwd()
base_path=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
sys.path.append(base_path)

from Base.read_excel import readExcel
from Base.read_ini import config_data
from Base.base_request import request
from Base.read_db import oracle
from Base.depend_date import get_data
from Base.read_json import get_value
from Base.log import logger

excel_data = readExcel.get_excel_data()
token = request.token()
config_url = config_data.get_value('host')
@ddt
class Test_case01(unittest.TestCase):

    @data(*excel_data)
    def test_user(self,excel_data):
        print(excel_data)
        case_id = excel_data[0]
        """获取测试用例的行号i"""
        i = readExcel.get_rows_number(case_id)
        depend = excel_data[3]
        is_run = excel_data[2]
        base_url = excel_data[5]
        url = config_url + base_url
        para_data = json.loads(excel_data[7])
        if is_run == "yes":
            """该用例是否进行执行"""
            if depend:
                """使用获取依赖的方法获取依赖数据,把数据添加到url或data中"""
                depend_data = get_data(depend)
                if excel_data[14] == "url":
                    url = url+'/'+str(depend_data)
                elif excel_data[14] == "data":
                    para_data['id']=depend_data
            headers = json.loads(excel_data[8])
            """把token添加到headers中"""
            headers['Authorization'] = token
            method = excel_data[6]
            """使用mock数据"""
            # request.run_man = mock.Mock(return_value=get_value(base_url))
            """使用run_man方法进行get/post/put/delete请求"""
            if method == "get" or method == "delete":
                res = request.run_man(method, url, para_data, headers)
            else:
                res = request.run_man(method, url, json.dumps(para_data), headers)
            print(res)
            """把接口返回的结果写入Excel中"""
            readExcel.excel_write_data(i, 13, json.dumps(res, ensure_ascii=False).encode('utf-8'))
            assert_ = excel_data[10]
            expect_msg = excel_data[9]
            """根据预期结果方式msg/code/sql结果进行断言"""
            if assert_ == "msg":
                try:
                    self.assertEqual(expect_msg,res['msg'])
                    readExcel.excel_write_data(i, 12, '成功')
                except Exception as msg:
                    logger.info(msg)
                    readExcel.excel_write_data(i, 12, '失败')
            elif assert_ == "code":
                try:
                    self.assertEqual(expect_msg,res['status'])
                    readExcel.excel_write_data(i, 12, '成功')
                except Exception as msg:
                    logger.info(msg)
                    readExcel.excel_write_data(i, 12, '失败')
            elif assert_ == "sql":
                sql_data = excel_data[4]
                try:
                    result_data = oracle.read_mysqldb(sql_data,'hsp_user')
                    self.assertEqual(para_data['username'], result_data[0]['username'])
                    """把自己后面测试用例使用到的数据可以添加到字典中,写入Excel"""
                    excel_sql_data = {"id":result_data[0]['id'],'name':result_data[0]['username']}
                    readExcel.excel_write_data(i, 12, '成功')
                    readExcel.excel_write_data(i, 14, json.dumps(excel_sql_data))
                except Exception as msg:
                    logger.info(msg)
                    readExcel.excel_write_data(i, 12, '失败')


if __name__ == "__main__":
    unittest.main()

 

 

 

生产测试报告

生产html测试报告,并以邮件的形式发送

import os
import sys

"""
author:
ad_date:
brief:  运行全部测试用例
"""
pwd = os.getcwd()
base_path=os.path.abspath(os.path.dirname(pwd)+os.path.sep+".")

import unittest,time,smtplib,configparser
from Base.HTMLTestRunner_jpg import HTMLTestRunner
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from Base.get_path import GetPath



def add_case():
    """
    添加报告路径,添加所有的测试用例
    :return: 一个包含路径下所有测试用例(test*.py)的list集合˚
    """
    testunit = unittest.TestSuite()
    case_path = base_path+'/interface/Case'
    print("测试用例的路径 %s" % case_path)
    discover = unittest.defaultTestLoader.discover(case_path,
                                                   pattern="test*.py",
                                                   top_level_dir=None)
    testunit.addTests(discover)
    return testunit


def report_path():
    """报告路径"""
    result_path = os.path.join(os.getcwd(), 'report')
    if os.path.isdir(result_path):
        pass
    else:
        os.makedirs(result_path)
    return result_path


def run_case():
    now = time.strftime("%Y_%m_%d_%H_%M_%S")
    result_abspath = os.path.join(report_path(), ('%s.html' % now))
    print(result_abspath)
    fp = open(result_abspath, 'wb')
    runner = HTMLTestRunner(title="自动化测试报告",
                            description="用例执行情况",
                            stream=fp,
                            retry=0,
                            )
    runner.run(add_case())
    fp.close()


def get_report_file():
    lists = os.listdir(report_path())
    lists.sort(key=lambda fn: os.path.getmtime(os.path.join(report_path(), fn)))
    report_file = lists[-1]
    print("最新的测试的报告为:%s" % report_file)
    return os.path.join(report_path(), report_file)


def send_mail():
    """
    发送最新的测试报告
    :return:
    """
    configPath = GetPath().get_conf_path('server.ini')
    conf = configparser.ConfigParser()
    conf.read(configPath, encoding='UTF-8')
    sender = conf.get('email', 'sender')
    pwd = conf.get('email', 'psw')
    server = conf.get('email', 'smtp_server')
    port = conf.get('email', 'port')
    receiver = conf.get('email', 'receiver')
    time.sleep(2)
    report_file = get_report_file()
    with open(report_file, 'rb') as f:
        mail_body = f.read()
    msg = MIMEMultipart()
    body = MIMEText(mail_body, _subtype='html', _charset='utf-8')
    msg['Subject'] = '自动化测试报告'
    msg['from'] = sender
    msg['to'] = receiver
    #添加时间
    msg['ad_date'] = time.strftime('%a,%d,%b,%Y_%M_%S %Z')
    msg.attach(body)
    #添加附件
    att = MIMEText(open(report_file, 'rb').read(), 'base64', 'utf-8')
    att['Content-Type'] = 'application/octet-stream'
    att['Content-Disposition'] = 'attachment; filename = "report.html"'
    msg.attach(att)
    #发件人邮箱中的SMTP服务器,端口是465
    smtp = smtplib.SMTP_SSL(server, port)

    # 登录用户名和密码
    smtp.login(sender, pwd)
    smtp.sendmail(sender, receiver.split(','), msg.as_string())
    smtp.quit()
    print('邮件已经发送给:%s' % str(receiver))


if __name__ == '__main__':

    run_case()
    # send_mail()

  

生产html格式测试报告

测试报告中用例名称可以在ddt方法中进行修改,按下面截图中进行修改即可

 

 

 

 

 

 

 

posted @ 2021-07-20 11:22  顺逆流  阅读(359)  评论(0)    收藏  举报