自动化测试无代码化断言

在自动化测试中如果要做到数据驱动,需要在数据表中配置所有的断言,然后后台动态读取断言表达式,依次进行断言,尤其是在平台化的时候会比较有用。

比如在测试注册功能时,接口返回的数据是一个 json 数据,我需要对 code 字段和 msg 字段中的值依次断言。

{
    "code": 2,
    "msg": "账号已存在",
    "data": null
}

如果是采用代码方式,可以分别写两个 assert ,但是如果实行无代码化配置,则可以把断言表达式写在数据表中,通用代码读取表达式,再进行断言,以 yaml 配置为例:

request:
  headers: {"content_type": "runapi"}

assertions:
  - ['assertEqual', '$.msg', '账号以存在']
  - ['assertEqual', '$.code', '2']

assertion 表达式中第一个元素是断言的函数,二个元素是 jsonpath 表达式,用来提取json数据,第三个元素是需要断言的预期结果。

先封装一个能解析 json 数据的函数:

def parse_jsonpath(expr, json_data):
    """根据jsonpath 提取 json数据"""
    result = jsonpath(json_data, expr)
    if result:
        data, *_ = result
        return data

然后可以封装 TestCase 类读取 yaml 中的 assertion 表达式断言:

class BaseCase(unittest.TestCase):
    def __init__(self, methodName='runTest'):
        super().__init__(methodName)
        
    def assert_one(self, validator, expected, actual):
        """断言一个表达式
        assert_one("assertEqual", "a", "a")
        """
        assert_method = getattr(self, validator)
        assert_method(expected, actual)

    def assert_all_jsonpath(self, assertions, json_data):
        """通过 jsonpath 断言所有
        [
            ["assertEqual", "$..msg", "a"],
            ["assertEqual", "$..data", "b"]
        ]
        """
        for assertion in assertions:
            validator, jp_expr, expected = assertion
            actual = parse_jsonpath(jp_expr, json_data)
            self.assert_one(validator, expected, actual)

在测试用例函数中,就可以直接调用 assert_all_jsonpath 依次断言了

class TestRegister(BaseCase):
    def test_register(self):
        # 没有读取yaml, 使用变量代替yaml 中的 assertions
        assertions =   [
            ['assertEqual', '$.msg', '账号以存在'],
  		    ['assertEqual', '$.code', '2']
        ]
        resp = requests.request(**request_data)
        self.assert_all_jsonpath(assertions, resp.json())