自动化测试配置 hook 函数

在自动化测试中如果要做到数据驱动,有时候需要在数据表中配置hook函数,然后后台动态调用函数执行,尤其是在平台化的时候会比较有用。

比如在测试注册功能时,动态生成手机号码。在配置数据时可以先指定需要调用的hook函数。

{
    "mobile_phone": "${fake_phone()}", 
    "pwd": "${fake_password(length=6)}"
}

先把 hook 函数写在指定的文件中:

import faker

def fake_phone():
    """手机号"""
    fk = faker.Faker(locale=['zh_CN'])
    return fk.phone_number()

def fake_password(lens=9):
    """密码"""
    fk = faker.Faker()
    return fk.pystr(min_chars=int(lens), max_chars=int(lens))

通过字符串调用函数的解析函数:

def parse_hook(hook):
    """根据 hook 字符串解析
    generate_mobile(a, b, x='') -> generate_mobile, args, kwargs
    """
    hook_name,args = hook.split('(')
    args = args[:-1]
    args_list = args.split(',')
    if not args.strip():
        args_list = list()
    postion_args = list()
    kw_args = dict()
    for args in args_list:
        if '=' not in args:
            postion_args.append(args)
        else:
            key, value = args.split('=')
            # TODO: value 是字符串,会有隐藏 bug
            kw_args[key.strip()] = value
    return (hook_name, postion_args, kw_args)

所有的 hook 函数可以事先约定保存在一个固定文件中,比如 hooks.py,每次运行时只需要按规则从模块中获取指定的 hook 函数,得到返回结果。

def run_hook(hook):
    """运行hook函数
    run_hook('generate_mobile()')
    """
    name, args, kwargs = parse_hook(hook)
    try:
        import hooks
    except ImportError:
        logging.error('没有 hook.py 文件')
    else:
        hook_name = getattr(hooks, name)
        return hook_name(*args, **kwargs)

运行得到的数据,再替换原来的占位符

def replace_by_hook(string, patten=''):
    """根据正则表达式替换成方法中的数据"""
    if not patten:
        patten = r'\${(.*?)}'
    compiler = re.finditer(patten, string)
    for result in compiler:
        old = result.group()
        hook = result.group(1)
        new = run_hook(hook)
        string = string.replace(old, new)
    return string

最终只需要调用替换函数,就能动态调用指定的 hook:

case_data = """
    {
        "mobile_phone": "${fake_phone()}", 
        "pwd": "${fake_password(lens=6)}"
    }
    """
new_case_data = replace_by_hook( case_data)