Python+Requests-2-接口自动化脚本实现(虫师-Django接口测试实例)

编写脚本前分析项目架构

需求:python脚本实现【添加发布会信息】的接口测试,以邮件形式发送测试报告

1.新建一个case目录,存放测试用例

2.新建一个config目录,存放配置信息和读取配置信息

3.新建一个db_fixture目录,初始化数据

4.新建report目录,用来存放生成的测试报告

5.run_main.py文件,执行接口测试脚本

(一般还会新建一个common目录,存放一些公共方法,例如读取excel方法等)

 

编写脚本

1.config部分

(1)db_config.ini 数据库配置信息(此处需注意,这里的数据库需要与实际项目的数据库一致)

# coding:utf-8
# 数据库配置信息

[mysqlconf]
host = 47.xx.xxx.xx
port = 3306
user = root
password = 123456
db = guest

 

(2) readDbConfig.py 读取数据库信息,封装清除数据和插入数据的方法,以便进行初始化数据的操作

#coding:utf-8

from pymysql import connect,cursors
from pymysql.err import OperationalError
import os
import configparser

# ================读取db_config.ini文件设置=================


cur_path = os.path.dirname(os.path.realpath(__file__))
configPath = os.path.join(cur_path,"db_config.ini")
cf = configparser.ConfigParser()
cf.read(configPath,encoding='UTF-8')

host = cf.get("mysqlconf","host")
port = cf.get("mysqlconf","port")
db = cf.get("mysqlconf","db")
user = cf.get("mysqlconf","user")
password = cf.get("mysqlconf","password")


# ================封装MySQL基本操作=================
class DB:
    def __init__(self):
        try:
            # 连接数据库
            self.conn = connect(
                host = host,
                user = user,
                password = password,
                db = db,
                charset = "utf8mb4",
                cursorclass = cursors.DictCursor
                )
        except OperationalError as e:
            print("Mysql Error %d:%s"%(e.args[0],e.args[1]))

    # 清除表数据
    def clear(self,tabel_name):
        real_sql = "delete from "+ tabel_name +";"
        with self.conn.cursor() as cursor:
            cursor.execute("SET FOREIGN_KEY_CHECKS = 0;")
            cursor.execute(real_sql)
        self.conn.commit()

    # 插入表数据
    def insert(self,table_name,table_data):
        for key in table_data:
            table_data[key] = "'"+str(table_data[key])+"'"
        key = ','.join(table_data.keys())
        value = ",".join(table_data.values())
        real_sql = "INSERT INTO " + table_name + " (" + key + ") VALUES (" + value +")" + ";"
        print(real_sql)
        with self.conn.cursor() as cursor:
            cursor.execute(real_sql)
        self.conn.commit()

    # 关闭数据库连接
    def close(self):
        self.conn.close()

if __name__ == '__main__':
    db = DB()
    table_name = "sign_event"
    data = {"id":12,
            "name":"红米",
            "limit2":2000,
            "status":1,
            "address":"北京会展中心",
            "start_time":"2018-10-30 08:00:00",
            }
    db.clear(table_name)
    db.insert(table_name,data)
    db.close()

 

(3) email_config.ini 邮箱信息

# coding:utf-8
# 邮箱配置信息

[email]
smtp_server = smtp.qq.com
port = 465
sender = 907xxxx@qq.com
psw = xxxxxxxx
receiver = 2092xxxxx@qq.com

 

(4) readEmailConfig.py 读取邮件信息

#coding:utf-8

# ================读取cfg.ini文件设置=================

import os
import configparser

# os.path.realpath(__file__):返回当前文件的绝对路径
# os.path.dirname(): 返回()所在目录
cur_path = os.path.dirname(os.path.realpath(__file__)) # 当前文件的所在目录
configPath = os.path.join(cur_path,"email_config.ini") # 路径拼接:/config/email_config.ini
conf = configparser.ConfigParser()
conf.read(configPath,encoding='UTF-8') # 读取/config/email_config.ini 的内容

# get(section,option) 得到section中option的值,返回为string类型
smtp_server = conf.get("email","smtp_server")
sender = conf.get("email","sender")
psw = conf.get("email","psw")
receiver = conf.get("email","receiver")
port = conf.get("email","port")

2.db_fixture部分

(1)test_data.py 添加测试数据

# coding:utf-8

from config.readDbConfig import DB
# 创建测试数据
datas = {
    # 发布会表数据
    "sign_event":[
        {"id":1,"name":"红米Pro发布会","limit2":2000,"status":1,"address":"北京会展中心","start_time":"2018-10-31 08:00:00"},
        {"id":2,"name":"可参加人数为0","limit2":0,"status":1,"address":"北京会展中心","start_time":"2018-10-31 08:00:00"},
        {"id":3,"name":"当前状态为0关闭","limit2":2000,"status":0,"address":"北京会展中心","start_time":"2018-10-31 08:00:00"},
        {"id":4,"name":"发布会已结束","limit2":2000,"status":1,"address":"北京会展中心","start_time":"2017-10-31 08:00:00"},
        {"id":5,"name":"小米5发布会","limit2":2000,"status":1,"address":"北京会展中心","start_time":"2018-10-31 08:00:00"}
    ]
}

# 将测试数据插入表
def init_data():
    db = DB()
    for table,data in datas.items():
        db.clear(table)
        for d in data:
            db.insert(table,d)
    db.close()

if __name__ == '__main__':
    init_data()

 

3.case部分

(1)test_add_event.py 测试用例

# coding:utf-8
import unittest
import requests
import os,sys

cur_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,cur_path)
from db_fixture import test_data

class TestAddEvent(unittest.TestCase):
    """添加发布会"""
    def setUp(self):
        self.base_url = "http://47.xx.xxx.xx:8000/api/add_event/"

    def tearDown(self):
        print("")

    def test_add_event_all_null(self):
        """所有参数为空添加"""
        payload = {"eid":"","name":"","limit2":"","address":"","start_time":""}
        r = requests.post(self.base_url,data=payload)
        self.result = r.json()
        self.assertEqual(self.result["status"],10021)
        self.assertEqual(self.result["message"],"parameter error")

    def test_add_event_eid_exist(self):
        """id已经存在"""
        payload = {"eid":1,"name":"一加4发布会","limit2":2000,"address":"深圳宝体","start_time":"2018-11-01 08:00:00"}
        r = requests.post(self.base_url, data=payload)
        self.result = r.json()
        self.assertEqual(self.result["status"], 10022)
        self.assertEqual(self.result["message"], "event id already exists")

    def test_add_event_name_exists(self):
        """名称已经存在"""
        payload = {"eid": 88, "name": "红米Pro发布会", "limit2": 2000, "address": "深圳宝体", "start_time": "2018-11-01 08:00:00"}
        r = requests.post(self.base_url, data=payload)
        self.result = r.json()
        self.assertEqual(self.result["status"], 10023)
        self.assertEqual(self.result["message"], "event name already exists")

    def test_add_event_data_type_error(self):
        """日期格式错误"""
        payload = {"eid": 102, "name": "一加4发布会", "limit2": 2000, "address": "深圳宝体", "start_time": "2018"}
        r = requests.post(self.base_url, data=payload)
        self.result = r.json()
        self.assertEqual(self.result["status"], 10024)


    def test_add_event_success(self):
        """添加成功"""
        payload = {"eid": 88, "name": "孙小二发布会", "limit2": 2000, "address": "深圳宝体", "start_time": "2018-11-01 08:00:00"}
        r = requests.post(self.base_url, data=payload)
        self.result = r.json()
        print(self.result)
        self.assertEqual(self.result["status"], 200)


if __name__ == '__main__':
    test_data.init_data() # 初始化接口测试数据
    unittest.main()

 

4.run_main.py 执行脚本

# coding:utf-8
import os
import unittest
import time
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from db_fixture import test_data
import HTMLTestRunnerCN_test
from config import readEmailConfig

# 当前脚本所在文件真实路径
cur_path = os.path.dirname(os.path.realpath(__file__))

def add_case(caseName="case",rule="test_*.py"):
    """第一步:加载所有测试用例"""
    case_path = os.path.join(cur_path,caseName) # 用例文件夹
    # 文件夹不存在就创建一个文件夹
    if not os.path.exists(case_path):os.mkdir(case_path)

    # 定义discover加载所有测试用例
    # case_path:执行用例的目录;pattern:匹配脚本名称的规则;top_level_dir:默认为None
    discover = unittest.defaultTestLoader.discover(case_path,pattern=rule,top_level_dir=None)
    return discover

def run_case(all_case,reportName="report"):
    """第二步:执行所有的用例,并把结果写入到html测试报告中"""
    now = time.strftime("%Y_%m_%d_%H_%M_%S")
    report_path = os.path.join(cur_path,reportName)
    if not os.path.exists(report_path):os.mkdir(report_path)
    report_abspath = os.path.join(report_path,now+"result.html")
    print("report path:%s"%report_abspath)

    fp = open(report_abspath,"wb")
    runner = HTMLTestRunnerCN_test.HTMLTestRunner(stream=fp,title="自动化接口测试报告,测试结果如下:",
                                           description="用例执行情况")
    # 调用add_case函数
    runner.run(all_case)
    fp.close()


def get_report_file(report_path):
    """第三步:获取最新的测试报告"""
    lists = os.listdir(report_path)
    lists.sort(key=lambda fn:os.path.getmtime(os.path.join(report_path,fn)))
    print("最新测试生成的报告:"+lists[-1])
    # 找到生成最新的报告文件
    report_file = os.path.join(report_path,lists[-1])
    return report_file

def send_mail(sender,psw,receiver,smtpserver,report_file,port):
    """第四步:发送最新的测试报告内容"""
    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.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)
    try:
        smtp = smtplib.SMTP_SSL(smtpserver,port)
    except:
        smtp = smtplib.SMTP()
        smtp.connect(smtpserver,port)

    # 用户名密码
    smtp.login(sender,psw)
    smtp.sendmail(sender,receiver,msg.as_string())
    smtp.quit()
    print("test report email has send out")

if __name__ == '__main__':

    test_data.init_data() # 初始化接口测试数据

    all_case = add_case() # 加载用例
    run_case(all_case)  # 执行用例

    report_path = os.path.join(cur_path,"report")
    report_file = get_report_file(report_path)

    # 邮箱配置,邮箱信息获取
    sender = readEmailConfig.sender
    psw = readEmailConfig.psw
    smtp_server = readEmailConfig.smtp_server
    port = readEmailConfig.port
    receiver = readEmailConfig.receiver
    send_mail(sender,psw,receiver,smtp_server,report_file,port) # 调用发送邮件方法

 

执行脚本

1.执行run_main.py 脚本会在report目录生成一个html文件

2.用例全部执行通过

 

展开阅读全文

没有更多推荐了,返回首页