接口自动化如何做?Python接口自动化测试框架实现(源码)


前言

目前主流接口测试方案

工具派;Java派;Python派;接口平台

框架类型

录制回放;数据驱动;行为驱动

框架的分层与规划

框架分层:
表示层:(用户界面)
业务逻辑层:(读取数据,配置并组装发送请求)+执行控制层(pytest)
数据层:(配置读取/数据读取/数据库连接/其他(log/email)

框架规划

case: 测试用例目录
user: (用户模块)
test_user.py: 测试用例
case.py: 用例公共方法
data: 数据文件目录
test_user_data.xlsx: 测试用例数据文件
conf: 配置文件目录
default.conf: 默认配置文件
report: pytest生成的报告保存路径
log: log保存路径,按天生成log
common: 公共方法目录
config.py: 配置文件读取
data.py: 数据文件读取
db.py: 数据库连接
log.py: 日志配置
send_email.py: 发送邮件配置

框架实现

conf/default.conf: 表示层-项目配置文件#

[runtime]
log_level=debug
report_dir=report
log_dir=log
timeout=10

[server]
test = http://127.0.0.1:5000
stage = http://127.0.0.1:6000
prod = http://127.0.0.1:7000

[db_test]
host = localhost
port = 3307
db = api
user = root
passwd = 

[db_stage]

[db_prod]

[email]
server = smtp.sina.com
user = test_results@sina.com
pwd =  ******
subject = Api Test Ressult
receiver = superhin@126.com

data/test_user_data.xlsx: 表示层-用例数据文件

reg表(sheet名为reg)

TestCaseUrlMethodDataTypeDataCodeMsg
test_reg_normal/api/user/reg/POSTJSON{“name”: “{NAME}”, “passwd”: “123456”}100000成功

login表(sheet名为login)

TestCaseUrlMethodDataTypeDataResponseText
test_login_normal/api/user/login/POSTFORM登录成功

SQL表(sheet名为SQL)

checkUserselect * from user where name=
checkUserPasswdselect * from user where name={NAME} and passwd=

common/config.py:数据层-config文件读取

"""
1. 从配置文件中获取各个段信息
2. 返回一个项目的绝对路径
"""
import os
import configparser

# 相对导入包的问题

pro_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


class Config(object):
    def __init__(self, filename="default.conf"):
        self.cf = configparser.ConfigParser()
        self.cf.read(os.path.join(pro_path,"conf",filename))
        
    def get_runtime(self, option):
        return self.cf.get("runtime", option)

    def get_server(self, option):
        return self.cf.get("server", option)

    def get_db_test(self, option):
        return self.cf.get("db_test", option)

    def get_email(self, option):
        return self.cf.get("email",option)

if __name__ == "__main__":
    c = Config()
    print(c.get_runtime("log_level"))
    print(c.get_server("test"))

data.py: 数据层-数据文件读取

"""
1. 从Excel中读取接口的数据
2. 读取Sql命令
"""
import xlrd
import sys
import os
sys.path.append("..")
from common.config import pro_path

class Data(object):
    def __init__(self, filename):
        data_file_path = os.path.join(pro_path,"data",filename)   
        self.wb = xlrd.open_workbook("../data/test_user_data.xlsx")

    def get_case(self,sheet_name, case_name):
        sh = self.wb.sheet_by_name(sheet_name)
        for i in range(1, sh.nrows):
            if sh.cell(i,0).value == case_name:
                return sh.row_values(i)

        print("用例名未找到")
        return None

    def get_sql(self, sql_name):
        sh = self.wb.sheet_by_name("SQL")
        for i in range(sh.nrows):
            if sh.cell(i,0).value == sql_name:
                return sh.cell(i,1).value
        print("sql未找到")
        return None

if __name__ == "__main__":
    d = Data("test_user_data.xlsx")
    print(d.get_case("reg","test_reg_normal"))
    print(d.get_sql("checkUser"))

db.py: 数据层-数据库连接

"""
1. 从配置文件中读取数据库配置
2. 连接数据库
3. 执行sql并返回所有结果
"""
import sys
import pymysql
sys.path.append("..")
from common.config import Config

class DB(object):
    def __init__(self):
        c = Config()
        self.conn = pymysql.connect(host=c.get_db_test("host"),
                                    port=int(c.get_db_test("port")),
                                    db=c.get_db_test("db"),
                                    user=c.get_db_test("user"),
                                    passwd=c.get_db_test("passwd"),
                                    charset="utf8")

        self.cur = self.conn.cursor()

    def do_sql(self, sql):
        self.cur.execute(sql)
        return self.cur.fetchall()

    def __del__(self):
        self.cur.close()
        self.conn.close()

if __name__ == "__main__":
    db = DB()
    print(db.do_sql("select * from user"))

log.py: 数据层-log配置

"""
1. 配置log输出格式 time - loglevel - file - func - line - msg
2. 支持输出到log文件及屏幕
3. 支持返回一个logger,让其他模块调用
"""
import sys
sys.path.append("..")

from common.config import Config, pro_path
import time
import logging
import os

class Log():
    @classmethod
    def config_log(cls):
        cf = Config()
        log_dir = os.path.join(pro_path, cf.get_runtime("log_dir"))
        today = time.strftime("%Y%m%d", time.localtime(time.time()))
        log_file = os.path.join(log_dir, today+".log")

        # 获取一个标准的logger, 配置loglevel
        cls.logger = logging.getLogger()
        cls.logger.setLevel(eval("logging." + cf.get_runtime("log_level").upper()))

        # 建立不同handler
        fh = logging.FileHandler(log_file, mode="a",encoding=‘utf-8)
        ch = logging.StreamHandler()

        # 定义输出格式
        ft = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
        fh.setFormatter(ft)
        ch.setFormatter(ft)

        # 把定制handler 添加到我们logger
        cls.logger.addHandler(fh)
        cls.logger.addHandler(ch)

    @classmethod
    def get_logger(cls):
        cls.config_log()
        return cls.logger

if __name__ == "__main__":
    l= Log.get_logger()
    l.info("abc")
    l.debug("hello, debug")

send_email.py: 数据层-邮件服务器连接

"""
1. 从配置文件中读取stmp配置
2. 从report文件夹下打开report.html,发送邮件
"""
import smtplib
from email.mime.text import MIMEText
import os
import sys
sys.path.append("..")
from common.config import Config, pro_path
from common.log import Log


def send_email(report_name):
    cf = Config()
    logger = Log.get_logger()
    report_file = os.path.join(pro_path, cf.get_runtime("report_dir"),report_name)

    with open(report_file, "rb") as f:
        body = f.read()

    # 格式化email正文
    msg = MIMEText(body, "html", "utf-8")

    # 配置email头
    msg["Subject"] = cf.get_email("subject")
    msg["From"] = cf.get_email("user")
    msg["To"] = cf.get_email("receiver")

    
    # 连接smtp服务器,发送邮件
    smtp = smtplib.SMTP()
    smtp.connect(cf.get_email("server"))
    smtp.login(cf.get_email("user"),cf.get_email("pwd"))
    smtp.sendmail(cf.get_email("user"), cf.get_email("receiver"), msg.as_string())
    print("邮件发送成功")

if __name__ == "__main__":
    send_email("report.html")

case/case.py: 业务逻辑层, 为用例执行封装方法

"""
1. 加载数据
2. 发送接口
3. 为用例封装一些方法

"""
import sys
sys.path.append("..")
from common.log import Log
from common.config import Config
from common.db import DB
from common.data import Data
import json
import requests


class Case(object):
    def __init__(self):
        self.logger = Log.get_logger()
        self.cf = Config()

    def load_data(self, data_file):
        self.data = Data(data_file)

    def set_env(self, env):
        self.env = env

    def run_case(self, sheet_name, case_name, var={}):
        case_data = self.data.get_case(sheet_name, case_name)

        url = self.cf.get_server(self.env) + case_data[1]
        data = case_data[4].format(**var)
        
        if case_data[3].lower() == "form":
            data = json.loads(data)
            headers = {}
        else:
            headers = {"content-type": "application/json"}

        if case_data[2].lower() == "get":
            resp = requests.get(url=url)
        else:
            resp = requests.post(url=url, headers=headers, data=data)
        return resp.text
        
    def check_response(self):
        pass
    
    def check_db(self, sql_name, vars={}):
        sql = self.data.get_sql(sql_name).format(**vars)
        return self.db.exec_sql(sql)
        

if __name__ == "__main__":
    c = Case()
    c.set_env("test")
    c.load_data("test_user_data.xlsx")
    r = c.run_case("login", "test_login_normal")
    print(r)

case/user/test_user.py: 表示层: 测试用例脚本

import sys
import random
import pytest
sys.path.append("../..")
from case.case import Case

case = Case()

def setup_module(module):
    case.set_env('dev')
    case.load_data('test_user_data.xlsx')

def test_login_normal():
    result case.run("login", "test_login_normal")

if __name__ == '__main__':
    pytest.main(["-q", "test_user.py"])
run_all.py: 表示层: 执行所有用例入口#
import os
import time
from util.config import Config
from util.e_mail import send_email
import pytest

def main():
    cf = Config()
    report_dir = cf.get_report_dir()
    now = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    report_name = os.path.join(report_dir, 'report_' + now + '.html')
    pytest.main(["-q", "case", "--html=" + report_name])
    send_email(report_name)

if __name__ == '__main__':
    main()
下面是我整理的2023年最全的软件测试工程师学习知识架构体系图

一、Python编程入门到精通

请添加图片描述

二、接口自动化项目实战

请添加图片描述

三、Web自动化项目实战

请添加图片描述

四、App自动化项目实战

请添加图片描述

五、一线大厂简历

请添加图片描述

六、测试开发DevOps体系

请添加图片描述

七、常用自动化测试工具

请添加图片描述

八、JMeter性能测试

请添加图片描述

九、总结(尾部小惊喜)

在追逐梦想的路上,不要畏惧困难与挫折,坚持奋斗,才能收获成长与成功。相信自己的实力,勇往直前,你将开创属于自己的辉煌,书写精彩的人生篇章。

每一次努力都是一次积累,每一次坚持都是一次进步,不要停下脚步,不要放弃追求,只有奋斗,才能超越自我,创造属于自己的辉煌人生。相信自己,勇往直前,你一定能够成功。

在困境中,不要退缩,要坚持奋斗,因为只有经历挫折才能成长,只有付出汗水才能收获成功。相信自己的实力,勇敢面对挑战,你将创造属于自己的辉煌,让梦想在奋斗中绽放光芒。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值