跳转到3.0版本https://www.cnblogs.com/df888/p/12031649.html

AIM是我用python搭建的第一款接口自动化测试框架,随着技术的提升,框架也在升级,故有了AIM2.0。

附上 AIM1.0链接

什么是AIM2.0?

AIM2.0 makes it easier to interface testing more quickly and with less code.

                                                               ————改编自django

先皮一下啦,哈哈哈。

AIM2.0特点

  • 原生python,简单易用
  • for while if,逻辑控制灵活
  • 随机值、响应值、数据库值,取值简单
  • 友好支持代码级json显示,参数化直接
  • 写代码,调试方便
  • parewise算法等,覆盖场景更多

为了能更好的发挥这些特点,需要一定的编程能力

现在这时代不懂点编程,怎么做测试呢?

AIM2.0怎么用

unittest->pytest

最简单的一个case代码

from common.request import post
from common.assertion import *

def test():
    """一个简单的post请求结构"""
    r = post({
        "url": "",
        "headers": {},
        "body": {}
    })
    check_flag(r)

执行测试

目录结构

Postar

----case 用例

----common 公共

----config 配置

----data 数据

----result 结果

简洁明了的风格

核心代码

request

request是基于requests封装的请求,重中之中。

相比AIM1.0,做了一些重构。1.采用dict来存取请求相关数据;2.改用装饰器来处理post、get、put等方法 3.csv解耦内聚,从csv_reader.py挪到了request.py

req = {
    "default_headres": {"Content-Type": "application/json"},
    "p": None,
    "method": None,
    "r": None,
    "elapsed": None,
    "log_level": 1  # req日志级别 0不log不record 1log 2record 3log+record
}

def _sender(f):
    method = f.__name__

    def s(p, param='json'):
        param_map = {
            'post': param,  # json data
            'get': 'params',
            'put': 'json'
        }

        p['headers'] = p['headers'] if p['headers'] else req['default_headers']

        start = time.process_time()
        _timeout_try(f"requests.{method}(\"{p['url']}\", headers={p['headers']}, "
                     f"{param_map[method]}={p['body']}, verify=False)")
        end = time.process_time()

        req['elapsed'] = decimal.Decimal("%.2f" % float(end - start))
        req['p'] = p
        req['method'] = method
        _req_log()
        return req['r']

    return s

def _timeout_try(expression):
    while True:
        try:
            req['r'] = eval(expression)
        except (requests.exceptions.SSLError, requests.exceptions.ConnectionError) as e:
            if 'bad handshake' in str(e) or '10054' in str(e):
                continue
            else:
                raise Exception(e)
        break

def _req_log():
    if req['log_level'] in (1, 3):
        logger.info(f"{req['p']['url']} {req['method']} 请求头{obj2json(req['p']['headers'])} "
                    f"参数{obj2json(req['p']['body'])}\n响应\n{req['r'].text}\n")

    if req['log_level'] in (2, 3):
        title = ['time', 'status', 'elapsed(s)', 'url', 'headers', 'method', 'body', 'response']
        row = [current_time(),
               req['r'].status_code,
               req['elapsed'],
               req['p']['url'],
               obj2json(req['p']['headers']),
               req['method'],
               obj2json(req['p']['body']),
               req['r'].text,
               ' ']  # 多写一列空格,response列数据显示不会溢出单元格
        write_record(csv_path, title, row)

@_sender
def post():
    """post"""

@_sender
def get():
    """get"""

@_sender
def put():
    """put"""

dao

Data Access Object,目前仅支持mysql。

借助pandas和sqlalchemy做了极大的简化

class Dao:
    def __init__(self, address, user, password):
        self.engine = create_engine(f'mysql+pymysql://{user}:{password}@{address}')

    def select(self, sql):
        """
        查询
        :param sql:
        :return: DataFrame 可以按二维数组来查值 data['col_name']['row_num']
        """
        logger.info(f'执行sql:{sql}')
        return pd.read_sql(sql, self.engine)

randomer

专门用来产生随机数据的

def p_sample(seq, n):
    """
    postar的sample,防止越界
    :param seq:
    :param n:
    :return:
    """
    return random.sample(seq, n if n < len(seq) else len(seq))

def random_hanzi(n):
    """随机中文汉字"""
    return ''.join(random.sample(hanzi.replace('\r', '').replace('\n', ''), n))

def random_id(n):
    """随机id"""
    s = ""
    for i in range(n):
        s += str(random.randint(0, 9))
    return int(s)

def random_01(n):
    """随机01编码 '1010100' """
    return ''.join([random.choice('01') for i in range(n)])

def _timestamp(t):
    """时间戳"""
    y, m, d = tuple(int(x) for x in t.split('-'))
    m = (y, m, d, 0, 0, 0, 0, 0, 0)
    return time.mktime(m)

def random_date(start, end, n):
    """默认返回n个日期 列表"""
    start = _timestamp(start)
    end = _timestamp(end)
    return [time.strftime("%Y-%m-%d", time.localtime(random.randint(start, end))) for i in range(n)]

def range_num(a, b, interval=1.0):
    if interval == 1:
        return [i for i in range(a, b)]
    if interval == 0.5:
        out = []
        for i in range(a, b):
            out.append(i)
            out.append(i + 0.5)
        return out

def range_str(a, b, random_n=None):
    out = [str(i) for i in range(a, b)]
    return out if random_n is None else p_sample(out, random_n)

log

logger = logging.getLogger()
logger.setLevel(logging.INFO)  # 设置日志级别,默认为WARN
_formatter = logging.Formatter('\n[%(asctime)s]%(message)s', '%Y-%m-%d %H:%M:%S')

# 文件
fh = logging.FileHandler(log_path, encoding="utf-8")
fh.setFormatter(_formatter)
logger.addHandler(fh)

# 控制台
stdout = sys.stdout
ch = logging.StreamHandler(stdout)
ch.setFormatter(_formatter)
logger.addHandler(ch)

def stdout_write(msg):
    stdout.write(msg)
    stdout.flush()

if __name__ == '__main__':
    logger.info('hello')

func

一些公共函数

def encrypt(pwd):
    """base64加密"""
    return base64.b64encode(pwd.encode()).decode()

def current_time(n=0):
    time_format = ['%Y-%m-%d %H:%M:%S',  # 时间
                   '%Y-%m-%d',  # 日期
                   '%Y%m%d%H%M%S']  # 数字
    return time.strftime(time_format[n], time.localtime(time.time()))

def last_natural_day():
    """
    上个自然日
    :return:
    """
    return (datetime.datetime.now() + datetime.timedelta(days=-1)).strftime("%Y-%m-%d")

def obj2json(x):
    """
    obj to json
    :param x:
    :return: json
    """
    if isinstance(x, dict):
        return json.dumps(x, ensure_ascii=False)
    elif isinstance(x, str):
        return ast.literal_eval(x.replace('null', '\'\'').replace('false', '\'\''))

def lower_id(s):
    """report/downExcel to report_down_excel"""
    s = ''.join(['_' + c.lower() if c.isupper()
                 else c for c in s.replace('/', '_')])
    return s[1:] if s[0] == '_' else s

def upper_id(s):
    """national_market_index to NationalMarketIndex"""
    return ''.join(x[0].upper() + x[1:] for x in s.replace(' ', '').replace('/', '_').split('_'))

def bar(i):
    """
    进度条
    :param i: 百分比
    :return:
    """
    c = int(i / 10)
    jd = '\r %2d%% [%s%s]'
    a = '■' * c
    b = '□' * (10 - c)
    stdout_write(jd % (i, a, b))

def json2form(body):
    """
    json转表单
    :param body: {"a": 1, "b": 2}
    :return: a=1&b=2
    """
    return '&'.join([f"{k}={v}" for k, v in body.items()])

def form2json(form):
    """
    表单转json
    :param form: a=1&b=2
    :return: {"a": 1, "b": 2}
    """
    body = {}
    for kv in form.split('&'):
        k, v = kv.split('=')
        body[k] = v
    return json.dumps(body, indent=4, ensure_ascii=False)

在实际工作中,发现还有不少优化的余地,期待在未来做到3.0,再出个“手把手教你用AIM做接口自动化”。

接口自动化测试框架-AIM2.0的更多相关文章

  1. 接口自动化 [授客]基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0

    基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0   by:授客 QQ:1033553122     博客:http://blog.sina.com.cn/ishou ...

  2. 接口自动化 基于python+Testlink+Jenkins实现的接口自动化测试框架[V2.0改进版]

    基于python+Testlink+Jenkins实现的接口自动化测试框架[V2.0改进版]   by:授客 QQ:1033553122 由于篇幅问题,,暂且采用网盘分享的形式: 下载地址: [授客] ...

  3. 基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0

    基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0 目录 1. 开发环境2. 主要功能逻辑介绍3. 框架功能简介 4. 数据库的创建 5. 框架模块详细介绍6. Tes ...

  4. 【转】robot framework + python实现http接口自动化测试框架

    前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了 ...

  5. 【python3+request】python3+requests接口自动化测试框架实例详解教程

    转自:https://my.oschina.net/u/3041656/blog/820023 [python3+request]python3+requests接口自动化测试框架实例详解教程 前段时 ...

  6. 接口自动化 基于python实现的http+json协议接口自动化测试框架源码(实用改进版)

    基于python实现的http+json协议接口自动化测试框架(实用改进版)   by:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436     目录 1.      ...

  7. robot framework + python实现http接口自动化测试框架

    https://www.jianshu.com/p/6d1e8cb90e7d 前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测 ...

  8. python+requests接口自动化测试框架实例详解

    python+requests接口自动化测试框架实例详解   转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实 ...

  9. Maven+TestNG+ReportNG/Allure接口自动化测试框架初探(上)

    转载:http://www.51testing.com/html/58/n-3721258.html 由于一直忙于功能和性能测试,接口自动化测试框架改造的工作被耽搁了好久.近期闲暇一些,可以来做点有意 ...

随机推荐

  1. appium常见问题11_小米手机初次启动app,报错255“Requires permission android.permission.WRITE_SECURE_SETTINGS”

    问题: 新申请的测试机到啦,申请机型是小米9.打开开发者模式.USB调试后,连接电脑,准备跑一下自动化脚本.但是在pycharm中点击run后,出现报错,报错code:255,提示“Requires ...

  2. Linux操作系统(三)_部署JDK

    一.通过tar.gz压缩包安装 1.在usr目录下创建java目录 cd usr mkdir java 2.用rz命令上传tar.gz安装包到java目录 3.解压tar.gz安装包到当前目录 tar ...

  3. upc组队赛15 Supreme Number【打表】

    Supreme Number 题目链接 题目描述 A prime number (or a prime) is a natural number greater than 1 that cannot ...

  4. WireShark 自带工具 editcap 和 text2pcap 配合完成改包操作

    一.拆包 首先声明这种方法比较复杂而且需要点技术水平,不建议菜鸟尝试(可以使用WireEdit编辑pcap包,不过要联网)其实在熟练这种方法后也可以很快的,但这种方法主要还是方便吧,不用下载其他什么软 ...

  5. [伯努利数] poj 1707 Sum of powers

    题目链接: http://poj.org/problem?id=1707 Language: Default Sum of powers Time Limit: 1000MS   Memory Lim ...

  6. maven更换下载镜像源-解决下载慢问题(转)

    转自:http://www.cnblogs.com/duking1991/p/6110192.html maven更换下载镜像源-解决下载慢问题   Maven是当前流行的项目管理工具,但官方的库在国 ...

  7. Robot Framework使用技巧之内部变量

    [转载] 1.变量的使用 变量可以在命令行中设置,个别变量设置使用--variable (-v)选项,变量文件的选择使用--variablefile (-V)选项. 通过命令行设置的变量是全局变量,对 ...

  8. zabbix自带database monitor

    1. 在zabbix服务器上安装一下两个包: # yum -y install unixODBC mysql-connector-odbc 2. 修改zabbix服务器上ODBC配置: 2.1 Vim ...

  9. 转帖 移动前端开发之viewport的深入理解

    在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或 ...

  10. k8s-mysql搭建

    安装官方文档https://kubernetes.io/docs/tasks/run-application/run-replicated-stateful-application/ 搭建完成,但是没 ...