天天看点

​接口测试框架开发实践6:断言模块封装

​接口测试框架开发实践6:断言模块封装

前文说到DeepDiff这个Python库,可以解决全字段断言难、接口响应嵌套层次多导致的实际结果提取难的问题。本文给大家介绍一下如何将其结合自动化框架做更精准的断言。

传统断言

看一下我们之前用过的例子。

登陆接口测试数据 TEST_LOGIN.yaml

http:
    method: POST
    path: https://account.xinli001.com/login?next=https://www.xinli001.com/user
    headers:
      Content-Type: application/x-www-form-urlencoded; charset=UTF-8
      X-Requested-With: XMLHttpRequest
    body:
      payload: password=xxxxx&username=xxxxx%40163.com
expected:
  response:
    message: 登陆成功
    code: 0      

将登陆接口作为setup()定义在conftest.py文件

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   testcase_001.py
@Time    :   2021/06/20 12:07:09
@Author  :   软件质量保障
@wechat  :   ISTE1024
@Email   :   [email protected]
@Blog    :   https://www.zhihu.com/people/iloverain1024
@Copyright : 侵权必究
'''

import pytest
import yaml
import requests


class RequestHandler:
    def __init__(self):
        """session管理器:维持会话,可以让我们在跨请求时保存某些参数"""
        self.session = requests.session()

    def httpcore(self, method, url, params=None, data=None, json=None, headers=None, **kwargs):
        return self.session.request(method,url, params=params, data=data, json=json, headers=headers,**kwargs)

    def close_session(self):
        """关闭session"""
        self.session.close()


@pytest.fixture(scope='function')
def login():
    data = yaml.safe_load(open('testcases/data/TEST_LOGIN.yaml', encoding='utf-8'))
    http = data['http']
    method = http["method"]
    url = http["path"]
    headers = http["headers"]
    json = http["body"]['payload']
    req = RequestHandler()
    req.httpcore(method, url=url, headers=headers, data=json)
    return req      

而测试用例需要的测试数据文件TEST_DATA_002.yaml定义如下:

- case: 测试登陆查询回答内容001
  http:
    query:
      method: GET
      path: https://m.xinli001.com/get-my-answers.json
      headers:
        User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36
      body:
        payload:
  expected:
    response:
      total: 3
      answer_id: '5903852'
      code: 0      

定义测试用例:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   testcase_001.py
@Time    :   2021/06/20 12:07:09
@Author  :   软件质量保障
@wechat  :   ISTE1024
@Email   :   [email protected]
@Blog    :   https://www.zhihu.com/people/iloverain1024
@Copyright : 侵权必究
'''

import pytest
import yaml


# 用例重载
def data_reload(request, data_key):
    data = request[data_key]
    method = data["method"]
    url = data["path"]
    headers = data["headers"]
    body = data["body"]
    return method, url, headers, body


# 用例集读取
def get_test_data(test_data_path):
    case = []  # 存储测试用例名称
    http = []  # 存储请求对象
    expected = []  # 存储预期结果
    data = yaml.safe_load(open(test_data_path, encoding='utf-8'))
    # test = data['tests']
    for td in data:
        case.append(td.get('case', ''))
        http.append(td.get('http', {}))
        expected.append(td.get('expected', {}))
    parameters = zip(case, http, expected)
    return list(parameters)


@pytest.mark.parametrize("case, http, expected", get_test_data('testcases/data/TEST_DATA_002.yaml'))
def test_main(case, http, expected, login):
    # 数据准备,这块可以再单独封装一层
    method, url, headers, body = data_reload(http, 'query')
    # 发起请求
    query_res = login.httpcore(method, url=url, headers=headers, data=body)
    print(query_res.json())
    # 传统断言方式:提取响应结果数据与预期结果比较
    assert query_res.json()['code'] == expected['response']['code']
    assert query_res.json()['data']['total'] == expected['response']['total']
    assert query_res.json()['data']['list'][2]['answer_id'] == expected['response']['answer_id']      

改进版断言

我们知道deepdiff库提供grep功能,可以查询预期值是否存在于实际响应值中,即​

​expect⊆actual​

​。例子如下:

from deepdiff import grep
obj = {1: [{'2': 'b'}, 3], 2: [4, 5000, 51]}
result = obj | grep(5)
print(result)
>> {}      

我们可以遍历预期JSON串中的每个Key的值是否包含于实际响应中。这样避免了提取响应信息的繁杂操作,写法如下:

# 改进版
    for key, value in expected['response'].items():
        actual = query_res.json() | grep(value)
        assert actual != {}      

断言结果如下:

​接口测试框架开发实践6:断言模块封装

如果我们修改一下预期值:

- case: 测试登陆查询回答内容001
  http:
    query:
      method: GET
      path: https://m.xinli001.com/get-my-answers.json
      headers:
        User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36
      body:
        payload:
  expected:
    response:
      total: 3
      answer_id: '5903853'
      code: 0      

断言结果: