Beispiel #1
0
    def send_post(self, url, data, headers=None):
        """
        发送POST请求
        :param url: url
        :param data: 请求数据
        :param headers: 请求头
        :return: 返回请求结果
        """

        # body = json.dumps(data, ensure_ascii=False).encode('UTF-8')
        body = data
        logger('body').debug(data)
        req = requests.Session()
        try:
            response_rst = req.post(url, json=body, headers=headers)
            rst = json.loads(response_rst.content)
            logger('rst: ').debug(rst)
        except Exception as e:
            logger().error('解析返回结果失败', e)
        if rst['code'] != 2000:
            logger().error('返回结果错误!状态码不为2000')
            logger().error(rst['message'])
            raise AssertionError(url, rst)
        else:
            return rst
Beispiel #2
0
    def random_data_format(self, data):
        '''
        根据随机函数,生成数据
        :param data: 格式化数据(类型为str)
        :return:
        '''
        faker = Faker(locale='zh_CN')
        faker.add_provider(MyProvider)
        if '\\"' in data:
            data_md = data.replace('\\', '')
            self.interface_case_filed_list = re.findall(
                r',\"(.{1,30}?)":\"faker.', data_md)
        else:
            data_md = data
            logger('格式化数据').debug(data_md)
            for key, value in json.loads(data_md).items():
                if 'faker.' in str(value):
                    self.interface_case_filed_list.append(key)

        rely_filed_list = re.findall(r'\"(faker.*?)\"', data_md)
        for i, rely_filed in enumerate(rely_filed_list):
            # 提取key待优化
            rely_filed = rely_filed.strip('\\')
            rely_value = str(eval(rely_filed))
            self.interface_case_globals[
                self.interface_case_filed_list[i]] = rely_value
            data_new = data.replace(rely_filed, rely_value)
            data = data_new
        return data
 def __edit(self, sql, params):
     count = 0
     try:
         self.connect()
         count = self.cursor.execute(sql, params)
         self.conn.commit()
         self.close()
     except Exception as e:
         logger().error(e)
     return count
 def get_one(self, sql, params=()):
     result = None
     try:
         self.connect()
         self.cursor.execute(sql, params)
         result = self.cursor.fetchone()
         self.close()
     except Exception as e:
         logger().error(e)
     return result
def submit_data_and_verify(username, pwd, uri, body, expected_rst, sql_path,
                           yml_path, send_method, **params):
    '''
    提交数据请求后,验证数据库结果
    :param expected_rst: 预期结果
    :param url: 请求url
    :param body: 请求报文
    :param sql_path: sql文件
    :param yml_path: yml格式化文件
    :param send_method: 请求方法
    :return:
    '''
    sql_file = sql_path
    yml_file = yml_path
    # 随机函数格式化body、conditions、expected_rst

    # 格式化前置条件传的数据
    setUp_dict = params['setUp']
    body = format_data_by_setup(body, setUp_dict)
    conditions = format_data_by_setup(params['query'], setUp_dict)
    expected_rst = format_data_by_setup(expected_rst, setUp_dict)

    random_obj = RandomData()
    expected_rst = random_obj.get_random_data_value(expected_rst)
    # 登录
    lg = Login(username, pwd)
    req = lg.req
    headers = {
        "Authorization": 'Bearer ' + lg.access_token,
        "k2": lg.defaultLoc,
        "k1": lg.defaultIns
    }
    # 发送接口请求
    url = URL_INFO['TEST']['url'] + uri
    if send_method == 'POST':
        rst = req.send_post(url, data=body, headers=headers)
    else:
        rst = req.send_get(url, data=body, headers=headers)
    # 数据库查询校验
    # 如果yml配置文件为空,则直接查询数据库,不需要进行格式化
    if yml_path == '':
        db_rst = query_db(sql_file, query=conditions)
        logger('数据库查询结果:').debug(db_rst)
        if len(db_rst) > 0:
            fm_db_rst = json.dumps(db_rst[0])
        else:
            logger('数据库查询结果:').error('数据库查询结果为空')
            fm_db_rst = '{}'
    else:
        fm_db_rst = get_db_format_data(sql_file, yml_file, query=conditions)
        logger('数据库查询结果根据YML格式化为:').debug(fm_db_rst)
    # 数据库查询结果和预期结果比对
    logger('【=====expected_rst预期结果为:=====】').debug(expected_rst)
    logger('【=====数据库需比对数据:=====】').debug(fm_db_rst)
    compare_data(expected_rst, fm_db_rst)
 def get_all(self, sql, params=()):
     list = []
     try:
         self.connect()
         self.cursor.execute(sql, params)
         list = self.cursor.fetchall()
         self.close()
     except Exception as e:
         logger('数据库查询').error(e)
     if len(list) == 0:
         list = []
     return list
Beispiel #7
0
def compare_data_sub(data_a, data_b):
    '''
    数据比对
    :param data_a: 接口返回数据或自己设置的预期数据
    :param data_b: 数据库查询结果
    :return:
    '''
    if isinstance(data_a, dict):
        if len(data_a.keys()) == len(data_b.keys()):
            for key in data_a.keys():
                if isinstance(data_a[key], list) or isinstance(
                        data_a[key], dict):
                    compare_data_sub(data_a[key], data_b[key])
                else:
                    try:
                        assert data_a[key] == data_b[key]
                    except Exception as e:
                        inf = "键值对%s  %s != %s" % (key, data_a[key],
                                                   data_b[key])
                        logger('结果比对失败:').error(inf)
                        raise AssertionError(inf)
        else:
            inf = "data_1 键值对数量是%s != data2 键值对数量%s" % (len(data_a),
                                                        len(data_b))
            logger('结果比对失败:').error("字典长度不相等")
            raise AssertionError(inf)

    elif isinstance(data_a, list):
        if len(data_a) != len(data_b):
            inf = "data_1 长度是%s != data2 长度%s" % (len(data_a), len(data_b))
            logger('结果比对失败:').error("list 长度不相等")
            raise AssertionError(inf)
        else:
            for data_a_value, data_b_value in zip(data_a, data_b):
                if isinstance(data_a_value, list) or isinstance(
                        data_a_value, dict):
                    compare_data_sub(data_a_value, data_b_value)
                else:
                    try:
                        assert data_a_value == data_b_value
                    except Exception as e:
                        inf = "列表%s中 %s != %s" % (data_a, data_a_value,
                                                  data_b_value)
                        logger('结果比对失败:').error(inf)
                        raise AssertionError(inf)
    else:
        try:
            assert data_a == data_b
        except Exception as e:
            inf = " %s != %s" % (data_a, data_b)
            logger('结果比对失败:').error(inf)
            raise AssertionError(inf)
def format_data(original_data, target_yml):
    '''
    根据yml文件格式化json报文
    :param original_data: 原始报文数据
    :param target_yml: yml配置文件
    :return: 格式化后结果
    '''
    with open(target_yml, encoding='utf-8') as file:
        target_yml_data = yaml.full_load(file)
    rst_json = {}
    rst_json = get_sub_data_interface(original_data, target_yml_data, rst_json)
    logger('【接口报文格式化结果为】').debug(rst_json)
    return json.dumps(rst_json, ensure_ascii=False)
Beispiel #9
0
    def send_email(self):
        """ 发送邮件 """

        # 第三方 SMTP 服务
        mail_host = "smtp.163.com"  # 设置服务器
        mail_user = "******"  # 用户名
        mail_pass = "******"  # 口令
        # 获取口令地址 https://www.cnblogs.com/zhangshan33/p/11943755.html

        # 设置收件人和发件人
        sender = '*****@*****.**'
        receivers = [
            '*****@*****.**', '*****@*****.**', '*****@*****.**'
        ]  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱

        # 创建一个带附件的实例对象
        message = MIMEMultipart()

        # 邮件主题、收件人、发件人
        subject = '请查阅--测试报告'  # 邮件主题
        message['Subject'] = Header(subject, 'utf-8')
        # message['From'] = Header("{}".format(sender), 'utf-8')  # 发件人
        message['To'] = Header("{}".format(';'.join(receivers)),
                               'utf-8')  # 收件人
        message['From'] = '*****@*****.**'  # 发件人
        # message['To'] = '*****@*****.**'  # 收件人

        # 邮件正文内容 html 形式邮件
        send_content = self.read_report()  # 获取测试报告
        html = MIMEText(_text=send_content, _subtype='html',
                        _charset='utf-8')  # 第一个参数为邮件内容

        # 构造附件
        att = MIMEText(_text=send_content, _subtype='base64', _charset='utf-8')
        att["Content-Type"] = 'application/octet-stream'
        file_name = 'report.html'
        att["Content-Disposition"] = 'attachment; filename="{}"'.format(
            file_name)  # # filename 为邮件附件中显示什么名字
        message.attach(html)
        message.attach(att)
        try:
            smtp_obj = smtplib.SMTP()
            smtp_obj.connect(mail_host, 25)  # 25 为 SMTP 端口号
            smtp_obj.login(mail_user, mail_pass)
            smtp_obj.sendmail(sender, receivers, message.as_string())
            smtp_obj.quit()
            logger('发送邮件').debug("邮件发送成功!")
        except smtplib.SMTPException:
            logger('发送邮件').error("Error: 无法发送邮件!")
Beispiel #10
0
def connect_db_and_execute(sql, **params):
    '''
    连接数据库,并执行SQL语句
    :param sql: SQL语句
    :param params: 执行参数
    :return:
    '''
    sql = sql.format(**params['query'])
    logger('【执行SQL语句】').debug(sql)
    # 获取数据库db信息
    db_name = (re.findall('(.+?)\.', sql.split('FROM')[1])[0]).replace('\t', '').strip()
    # 连接数据库并查询
    db = MysqlHelper('mysql-test', db_name)
    query_rst = db.get_all(sql)
    return query_rst
def format_data_by_setup(data, setup):
    if isinstance(data, dict):
        data = json.dumps(data)
    if setup:
        data = data.replace('\\', '')
        filed_all = re.findall(r'\"@(.*?)"', data)
        for filed in filed_all:
            try:
                rely_value = setup[filed]
                new_data = data.replace('@'+filed, rely_value)
            except Exception as e:
                logger('接口间数据传递').error(filed)
                logger('接口间数据传递').error(e)
            data = new_data
    return json.loads(data)
Beispiel #12
0
 def login(username, password):
     '''
     登录
     :return: 返回token,请求对象
     '''
     url = '%s/app-sso/oauth/token?grant_type=password&username=%s&password=%s&verifyCode=&sessionId=' % (URL_INFO['TEST']['url'], username, password)
     headers = {"authorization": "Basic bm9idWc6Z2l2ZW1lZml2ZQ=="}
     req = HttpRquests()
     rst = req.send_post(url, data=None, headers=headers)
     if rst['code'] == 2000:
         logger('登录:').debug('登录成功')
         access_token = rst['body']['access_token']
     else:
         logger('登录').error('登录失败')
         raise AssertionError('登录失败')
     return access_token, req
def format_body_by_rely(body, rely_data):
    '''
    根据依赖关系格式化请求参数
    :param body:
    :param rely_data:
    :return:
    '''
    rely_filed_list = re.findall(r'\"(\$.*?)\"', body)
    for rely_filed in rely_filed_list:
        try:
            rely_value = str(jsonpath.jsonpath(rely_data, rely_filed)[0])
            new_body = body.replace(rely_filed, rely_value)
        except Exception as e:
            logger('接口间数据传递').error(rely_filed)
            logger('接口间数据传递').error(e)
        body = new_body
    return body
Beispiel #14
0
 def get_default_setting(self, req, access_token):
     '''
     获取默认配置
     :param req: session会话
     :param access_token: token
     :return:
     '''
     url = '%s/app-portal/get/default/setting' % (URL_INFO['TEST']['url'])
     headers = {"Authorization": 'Bearer ' + access_token}
     rst = req.send_post(url, data=None, headers=headers)
     if rst['code'] == 2000:
         defaultLoc = str(rst['body']['defaultLoc'])
         defaultIns = str(rst['body']['defaultIns'])
     else:
         logger('获取默认配置').error('获取默认配置失败')
         raise AssertionError('获取默认配置失败')
     return defaultLoc, defaultIns
Beispiel #15
0
def get_query_compare_rst(username, pwd, uri, body, expected_rst,
                          sql_file_name, yml_file_name, send_method, **params):
    '''
    接口查询数据并和数据库结果比对
    :param username: 登录用户名
    :param pwd: 登录密码
    :param uri: 请求uri
    :param body: 请求报文
    :param expected_rst: 期望结果
    :param sql_file_name: sql文件
    :param yml_file_name: yml格式化文件
    :param current_dir: 当前目录
    :param send_method: 请求方法
    :return:
    '''
    sql_file = sql_file_name
    yml_file = yml_file_name
    # 格式化前置条件传的数据
    setUp_dict = params['setUp']
    body = format_data_by_setup(body, setUp_dict)
    conditions = format_data_by_setup(params['query'], setUp_dict)
    expected_rst = format_data_by_setup(expected_rst, setUp_dict)

    # 登录
    lg = Login(username, pwd)
    access_token, req = lg.login()
    defaultLoc, defaultIns = lg.get_default_setting(req, access_token)
    headers = {
        "Authorization": 'Bearer ' + access_token,
        "k2": defaultLoc,
        "k1": defaultIns
    }
    # 发送接口请求
    url = URL_INFO['TEST']['url'] + uri
    if send_method == 'POST':
        rst = req.send_post(url, data=body, headers=headers)
    else:
        rst = req.send_get(url, data=body, headers=headers)
    # 接口返回结果格式化
    target_json = format_data(rst, yml_file)
    logger('接口返回结果格式化结果:').debug(target_json)
    # 如果期望结果expected_rst不为空,则不需要查询数据库,直接使用expected_rst与target_json比对
    if expected_rst:
        compare_data(target_json, expected_rst)
    else:
        # 执行数据库查询并返回格式化后的结果
        fm_db_rst = get_db_format_data(sql_file, yml_file, query=conditions)
        logger('数据库查询结果后根据YML格式化:').debug(fm_db_rst)
        # 数据库查询结果和接口返回结果比对
        logger('【=====接口需比对数据:=====】').debug(target_json)
        logger('【=====数据库需比对数据:=====】').debug(fm_db_rst)
        compare_data(target_json, fm_db_rst)
Beispiel #16
0
def compare_data(json1, json2):
    '''
    数据对比
    :param json1: 数据1
    :param json2: 数据2
    :return:
    '''
    # 将str转dict
    if isinstance(json1, str):
        json1 = json.loads(json1)
    if isinstance(json2, str):
        json2 = json.loads(json2)

    if type(json1) == type(json2):
        if json1 == {} or json2 == {}:
            logger('【结果比对失败】').error('json1 或者 json2数据为空')
            raise AssertionError('json1 或者 json2数据为空')
        else:
            compare_data_sub(json1, json2)
    else:
        raise AssertionError('json1和json2数据类型不一致')
Beispiel #17
0
def case(request):
    '''
    测试用例前置和后置
    :param request:
    :return:
    '''
    caseData = request.param
    if isinstance(caseData, dict):
        setUp = caseData['setUp']
        # 如果有前置条件,则将前置条件的返回结果存取
        if setUp:
            logger('前置条件').debug('【测试前置条件测试】')
            setUp_value = globals()[setUp]()
            request.param['setUp'] = setUp_value
    # 如果是场景类型
    elif isinstance(caseData, list):
        setUp = caseData[0]['setUp']
        # 如果有前置和后置条件,则将前置条件的返回结果存取
        if setUp:
            logger('前置条件').debug('【测试前置条件执行】')
            setUp_value = globals()[setUp]()
            request.param[0]['setUp'] = setUp_value
    return request.param
Beispiel #18
0
 def send_get(self, url, data, headers=None):
     """
     发送GET请求
     :param url: url
     :param data: 请求数据
     :param headers: 请求头
     :return: 返回请求结果
     """
     logger('body').debug(data)
     req = requests.Session()
     try:
         response_rst = req.get(url, params=data, headers=headers)
         rst = json.loads(response_rst)
     except Exception as e:
         logger().error('解析返回结果失败', e)
     if rst['code'] != 2000:
         logger().error('返回结果错误!状态码不为2000')
         raise AssertionError(url, rst)
     else:
         return rst
Beispiel #19
0
def scene_middle_verify(username, pwd, scene_data, setUp=None):
    '''
    场景类自动化用例验证
    :param username: 登录用户名
    :param pwd: 登陆密码
    :param scene_data: 场景类的驱动数据
    :param setUp: 前置条件返回的结果数据
    :return:
    '''
    lg = Login(username, pwd)
    req = lg.req
    headers = {
        "Authorization": 'Bearer ' + lg.access_token,
        "k2": lg.defaultLoc,
        "k1": lg.defaultIns
    }
    # 将接口依赖关系存存入dict
    interface_relations = {}
    for interface_data in scene_data:
        interface_relations[interface_data['uri']] = interface_data['rely']

    # 解析接口依赖关系,梳理接口依赖关系;决定接口执行顺序,(场景接口数据根据接口依赖重新排序)
    scene_data_new = []
    for interface, rely_interface in interface_relations.items():
        for scene in scene_data:
            if rely_interface == "" and rely_interface == scene['rely']:
                scene_data_new.append(scene)
    for scene_new in scene_data_new:
        for scene in scene_data:
            if scene['rely'] == scene_new['uri']:
                scene_data_new.append(scene)

    # 然后针对每个接口发送请求,根据接口依赖取值,并保存;提供给其他依赖与此接口的返回值;
    # 接口返回结果
    reponse_rst_dict = {}
    for index, interface_data in enumerate(scene_data_new):
        # 发送接口请求
        uri = interface_data['uri']
        # 根据场景的前置条件格式化body
        body = format_data_by_setup(interface_data['body'], setUp)

        if interface_data['rely']:
            # 获取依赖的数据,并格式化body,将依赖的数据写入填充到body里面
            body = format_body_by_rely(
                interface_data['body'],
                reponse_rst_dict[interface_data['rely']])
        # 打印body日志
        logger('【接口' + str(index + 1) + '】请求报文body为:').debug(body)
        if isinstance(body, str):
            body = json.loads(body)
        url = URL_INFO['TEST']['url'] + uri
        if interface_data['send_method'] == 'POST':
            rst = req.send_post(url, data=body, headers=headers)
        else:
            rst = req.send_get(url, data=body, headers=headers)
        # 打印接口返回结果日志
        logger('【接口' + str(index + 1) + '】返回结果为:').debug(rst)
        # 如果SQL执行字段为空,则保存接口返回结果; 否则查询数据库结果保存
        if interface_data['sql'] and index < len(scene_data_new) - 1:
            sql_file = interface_data['sql']
            condition = json.loads(interface_data['condition'])
            db_rst = query_db(sql_file, query=condition)
            reponse_rst_dict[uri] = db_rst[0]
        else:
            if rst:
                reponse_rst_dict[uri] = rst
            else:
                logger(uri).error('接口返回结果错误!')
                raise AssertionError(uri, '接口返回结果错误')
    # 最后一个接口结束后,验证场景结果
    # 如果最后一个接口是查询类,则写SQL查询校验
    if scene_data_new[-1]['interface_type'] == 0:
        rst = reponse_rst_dict[scene_data_new[-1]['uri']]
        yml_file = scene_data_new[-1]['yml']
        sql_file = scene_data_new[-1]['sql']
        expected_rst = scene_data_new[-1]['expected_rst']
        # condition = json.loads(scene_data_new[-1]['condition'])
        condition = json.loads(
            format_body_by_rely(scene_data_new[-1]['condition'],
                                reponse_rst_dict[interface_data['rely']]))
        target_json = format_data(rst, yml_file)
        logger('接口返回结果根据YML格式化为:').debug(target_json)
        # 如果expected_rst 期望结果不为空,则直接expected_rst与target_json比对;
        if expected_rst:
            compare_data(target_json, expected_rst)
        else:
            # 查询数据库,执行数据库查询并返回格式化后的结果
            fm_db_rst = get_db_format_data(sql_file, yml_file, query=condition)
            logger('数据库查询结果根据YML格式化为:').debug(fm_db_rst)
            # 数据库查询结果和接口返回结果比对
            logger('【=====接口需比对数据:=====】').debug(target_json)
            logger('【=====数据库需比对数据:=====】').debug(fm_db_rst)
            compare_data(target_json, fm_db_rst)
    # 如果最后一个接口是提交类,则直接执行SQL查询结果
    else:
        # 数据库查询校验
        expected_rst = scene_data_new[-1]['expected_rst']
        yml_file = scene_data_new[-1]['yml']
        sql_file = scene_data_new[-1]['sql']
        # condition = json.loads(scene_data_new[-1]['condition'])
        condition = json.loads(
            format_body_by_rely(scene_data_new[-1]['condition'],
                                reponse_rst_dict[interface_data['rely']]))
        if yml_file == '':
            db_rst = query_db(sql_file, query=condition)
            logger('数据库查询结果:').debug(db_rst)
            if len(db_rst) > 0:
                fm_db_rst = json.dumps(db_rst[0])
            else:
                logger('数据库查询结果:').error('数据库查询结果为空')
                fm_db_rst = '{}'

        else:
            fm_db_rst = get_db_format_data(sql_file, yml_file, query=condition)
            logger('数据库查询结果根据YML格式化为:').debug(fm_db_rst)
        # 数据库查询结果和预期结果比对
        logger('【=====expected_rst预期结果为:=====】').debug(expected_rst)
        logger('【=====数据库需比对数据:=====】').debug(fm_db_rst)
        compare_data(expected_rst, fm_db_rst)