コード例 #1
0
def get_screenshot_img(file_id):
    """
    获取截屏图片
    :param file_id:
    :return: 1.获取成功、2.找不到该文件、3.mongo连接不上
    """
    if is_null(file_id):
        msg = PARAMS_NOT_NONE
        img_base64 = ""
    else:
        mgf = MongoGridFS()
        img_base64 = mgf.get_base64_by_id(file_id)
        if is_null(img_base64):
            msg = MONGO_CONNECT_FAIL
        elif img_base64 == "no such file":
            msg = NO_SUCH_FILE
        else:
            msg = REQUEST_SUCCESS
            # response = make_response(img_base64)
            # response.headers.set('Content-Type', 'image/png')
            # return response
    re_dict = interface_template(msg, {
        "file_id": file_id,
        "img_base64": img_base64
    })
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #2
0
def set_case_status_all(pro_name, case_status):
    """
    设置整个项目的'测试用例'的'状态'(上下线)
    :param pro_name:
    :param case_status:
    :return:
    """
    test_method_name_list = []
    if is_null(pro_name) or is_null(case_status):
        msg = PARAMS_NOT_NONE
    else:
        if case_status in [True, False, "false", "FALSE", "TRUE", "true"]:
            case_status = case_status in [True, "TRUE", "true"
                                          ] and True or False
            res = update_case_status_all(pro_name, case_status)
            if res == "mongo error":
                msg = MONGO_CONNECT_FAIL
            else:
                msg = UPDATE_SUCCESS
                test_method_name_list = res
        else:
            msg = REQUEST_ARGS_WRONG
    re_dict = interface_template(
        msg, {
            "pro_name": pro_name,
            "case_status": case_status,
            "test_method_name_list": test_method_name_list
        })
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #3
0
def run_case(pro_name):
    """
    同时执行不同的用例 (开启线程执行,直接返回接口结果)
    [ 备 注 ]
        需要判断Android设备连接情况,若都未连接,表示不开启线程进行测试,并给出报错结果
    :param pro_name:
    :return:
    """
    if not pro_exist(pro_name):
        msg = PRO_NOT_EXIST
    else:
        # 获取已连接的设备列表
        connected_android_device_list = get_connected_android_devices_info(pro_name)
        if is_null(connected_android_device_list):
            msg = ANDROID_DEVICES_NOT_CONNECT
        else:
            run_flag = is_exist_start_case(pro_name)
            if run_flag == "mongo error":
                msg = MONGO_CONNECT_FAIL
            else:
                if run_flag:
                    msg = EXIST_RUNNING_CASE
                elif is_exist_online_case(pro_name):
                    sync_run_case(pro_name, connected_android_device_list)
                    msg = CASE_RUNING
                else:
                    msg = NO_ONLINE_CASE
    result_dict = {"pro_name": pro_name}
    re_dict = interface_template(msg, result_dict)
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #4
0
def set_case_status(pro_name, test_method_name):
    """
    设置某个'测试用例'的'状态'(上下线)
    :param pro_name:
    :param test_method_name:
    :return:
    """
    new_case_status = None
    if is_null(pro_name) or is_null(test_method_name):
        msg = PARAMS_NOT_NONE
    else:
        new_case_status = update_case_status(pro_name, test_method_name)
        msg = new_case_status == "mongo error" and MONGO_CONNECT_FAIL or UPDATE_SUCCESS
    re_dict = interface_template(msg, {"pro_name": pro_name, "test_method_name": test_method_name,
                                       "new_case_status": new_case_status})
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #5
0
def import_mongodb(pro_name, excel_list, import_method):
    """
    将excel中的用例按照导入方式,导入mongo
    :param pro_name
    :param excel_list:
    :param import_method: 导入方式(batch_insert、all_replace、batch_insert_and_replace)
    :return:

    【 备 注 】
    all_replace:先清空数据库,然后全部插入
    batch_insert:先找出不在数据库中的用例列表,然后插入
    batch_insert_and_replace:先区分'不在数据库中的用例列表'和'需要更新的用例列表',分别执行插入和更新操作

    【 步 骤 】

    """
    with MongodbUtils(ip=cfg.MONGODB_ADDR, database=cfg.MONGODB_DATABASE, collection=pro_name) as pro_db:
        try:

            if import_method == "all_replace":
                pro_db.drop()
                pro_db.insert_many(filled_other_field(excel_list))
            else:
                # 获取数据库中的'接口名称列表'
                all_case_in_db = pro_db.find()
                interface_name_list_in_db = [case.get("interface_name") for case in all_case_in_db]
                # 区分'不在数据库中的用例列表'和'需要更新的用例列表'
                update_list = []
                insert_list = []
                for index, line_dict in enumerate(excel_list):
                    if line_dict["interface_name"] in interface_name_list_in_db:
                        update_list.append(line_dict)
                    else:
                        insert_list.append(line_dict)
                print(insert_list)
                print(update_list)
                # 插入新增的数据
                if not is_null(insert_list):
                    pro_db.insert_many(filled_other_field(insert_list))
                # 更新数据
                if not is_null(update_list) and import_method == "batch_insert_and_replace":
                    for line_dict in update_list:
                        line_dict["update_time"] = get_current_iso_date()
                        query_dict = {"interface_name": line_dict["interface_name"]}
                        update_dict = {"$set": line_dict}
                        pro_db.update(query_dict, update_dict)
コード例 #6
0
def clear_screen_shot(days):
    """
    删除指定日期之前的所有的截图
    :param days:
    :return:
    """
    date_str = get_date_by_days(days=days, time_type="%Y-%m-%dT%H:%M:%S")
    mgf = MongoGridFS()
    del_num = mgf.del_file_by_date(date_str)
    if is_null(del_num):
        log.error("\n清理'" + date_str + "'之前的截图时出错了!\n")
    else:
        log.info("\n已清理'" + date_str + "'之前的截图:" + str(del_num) + " 个\n")
コード例 #7
0
def stop_run_status(pro_name):
    """
    强行修改用例运行状态 -> 停止
    :param pro_name:
    :return:
    """
    if is_null(pro_name):
        msg = PARAMS_NOT_NONE
    else:
        insert_result = stop_case_run_status(pro_name)
        if insert_result == "mongo error":
            msg = MONGO_CONNECT_FAIL
        else:
            msg = STOP_SUCCESS
    re_dict = interface_template(msg, {"pro_name": pro_name})
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #8
0
def refresh_case_run_status(pro_name):
    """
    刷新用例运行状态
    :param pro_name:
    :return:
    """
    if is_null(pro_name):
        msg = PARAMS_NOT_NONE
    else:
        case_run_status_list = get_case_run_status(pro_name)
        if case_run_status_list == "mongo error":
            msg = MONGO_CONNECT_FAIL
        else:
            msg = REQUEST_SUCCESS
    re_dict = interface_template(msg, {"pro_name": pro_name, "case_run_status_list": case_run_status_list})
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #9
0
def refresh_run_progress(pro_name):
    """
    刷新执行用例进度
    :param pro_name:
    :return:
    """
    if is_null(pro_name):
        msg = PARAMS_NOT_NONE
    else:
        progress_info = get_progress_info(pro_name)
        if progress_info == "mongo error":
            msg = MONGO_CONNECT_FAIL
        else:
            msg = REQUEST_SUCCESS
    re_dict = interface_template(msg, {"pro_name": pro_name, "progress_info": progress_info})
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #10
0
def sync_case_list(pro_name):
    """
    将某项目的所有测试用例同步入mongo库中,默认状态为'下线'
    :param pro_name:
    :return:
    """
    if is_null(pro_name):
        msg = PARAMS_NOT_NONE
    else:
        insert_result = case_import_mongo(pro_name)
        if insert_result == "mongo error":
            msg = MONGO_CONNECT_FAIL
        elif insert_result == "no such pro":
            msg = NO_SUCH_PRO
        else:
            msg = SYNC_SUCCESS
    re_dict = interface_template(msg, {"pro_name": pro_name})
    return json.dumps(re_dict, ensure_ascii=False)
コード例 #11
0
def suite_sync_run_case(pro_name, connected_android_device_list=[]):
    """
    同时执行不同用例( 通过动态修改'suite.py'文件中'TestSuite'类中的'run'方法,使得每个线程中的结果都可以记录到测试报告中 )
    :param pro_name: 项目名称
    :param connected_android_device_list: 已连接的设备列表 ( 以 列表数量 作为 线程数量 )
            (1)若 == [] :表示当前是'定时任务'
            (2)若 =! [] :表示当前是'页面执行',并且 已经获取到已连接的Android设备

        【 备 注 】
        1.suite 实例对象(包含了所有的测试用例实例,即继承了'unittest.TestCase'的子类的实例对象 test_instance )
        2.启动 Android 设备中的 APP 应用(每个用例执行一次):在每个'测试类'的 setUp 方法中执行 ( 继承 ParaCase 父类 )
        3.关闭 Android 设备中的 APP 应用 (每个用例执行一次):在每个'测试类'的 tearDown 方法中执行 ( 继承 ParaCase 父类 )

        【 保 存 截 屏 图 片 ID 的 逻 辑 】
        1.为实例对象'suite'<TestSuite>动态添加一个属性'screen_shot_id_dict' -> screen_shot_id_dict = {}
        2.每个测试方法中将所有截屏ID都保存入'screen_shot_id_list' -> screen_shot_id_dict = ['aaa', 'bbb', 'ccc']
        3.实例对象'suite'在重写的'new_run'方法中 将'screen_shot_id_list'添加入'screen_shot_id_dict'
        4.screen_shot_id_dict = { "测试类名.测试方法名":['aaa', 'bbb'], "测试类名.测试方法名":['cccc'] }

        【 并 发 线 程 数 逻 辑 】
        1.通过 adb 命令 查看 Android 设备 连接情况 ( 已连接 | 未连接 | 未授权 )
        2.将'已连接'的设备列表数量 作为 并发线程数量
         [ { "thread_index": 1, "device_name": "小米5S", "device_udid": "192.168.31.136:5555" } } ,
           { "thread_index": 2, "device_name": "坚果Pro", "device_udid": "192.168.31.253:4444"} } ]

        【 每 个 用 例 使 用 Android 设 备 逻 辑 】
        通过'当前线程名索引' 获取已连接设备列表中对应的'Android'设备信息

    """

    if is_null(connected_android_device_list):  # 表示当前是'定时任务'

        # (定时任务)需要判断 是否存在运行中的用例
        if is_exist_start_case(pro_name):
            send_DD_for_FXC(title=pro_name,
                            text="#### '" + pro_name +
                            "' 项目存在<运行中>的用例而未执行测试(定时任务)")
            return "Done"

        # (定时任务)需要获取 已连接的 Android 设备信息列表
        connected_android_device_list = get_connected_android_devices_info(
            pro_name)
        if len(connected_android_device_list) == 0:
            send_DD_for_FXC(title=pro_name,
                            text="#### '" + pro_name + "' 项目 未连接任何 Android 设备")
            return "Done"

    # '已连接设备的' 列表数量 作为 线程数量
    log.info("线程数量 : " + str(len(connected_android_device_list)))
    log.info("已连接的Android设备信息列表:" + str(connected_android_device_list) + "\n")

    # 将'测试类'中的所有'测试方法'添加到 suite 对象中(每个'测试类'实例对象包含一个'测试方法')
    from TestBase.test_case_unit import ParaCase
    suite, on_line_test_method_name_list = ParaCase.get_online_case_to_suite(
        pro_name, connected_android_device_list)

    if suite != "mongo error":
        if is_null(on_line_test_method_name_list):
            send_DD_for_FXC(title=pro_name,
                            text="#### '" + pro_name +
                            "' 项目<没有上线>的用例而未执行测试(定时任务)")
        else:
            # 为实例对象'suite'<TestSuite>动态添加一个属性'screen_shot_id_dict'(目的:保存截图ID)
            setattr(suite, "screen_shot_id_dict", {})

            # 为实例对象'suite'<TestSuite>动态添加一个属性'android_device_name_dict'(目的:保存使用的Android设备名称)
            setattr(suite, "android_device_name_dict", {})

            # 为实例对象'suite'<TestSuite>动态添加一个属性'thread_num'(目的:控制多线程数量)
            setattr(suite, "thread_num", len(connected_android_device_list))

            # 为实例对象'suite'<TestSuite>动态添加两个方法'run_test_custom'、'show_result_custom'( 目的:供多线程中调用 )
            suite.run_test_custom = MethodType(run_test_custom, suite)
            suite.show_result_custom = MethodType(show_result_custom, suite)

            # 为实例对象'suite'<TestSuite>动态修改实例方法'run'( 目的:启用多线程来执行case )
            suite.run = MethodType(new_run, suite)

            # 运行测试,并生成测试报告
            test_result, current_report_file = generate_report(
                pro_name=pro_name,
                suite=suite,
                title='Android自动化测试报告 - ' + pro_name,
                description='详细测试用例结果',
                tester="自动化测试",
                verbosity=2)
コード例 #12
0
def suite_sync_run_case(pro_name):
    """
    同时执行不同用例( 通过动态修改'suite.py'文件中'TestSuite'类中的'run'方法,使得每个线程中的结果都可以记录到测试报告中 )
    :param pro_name: 项目名称

        【 备 注 】
        1.suite 实例对象(包含了所有的测试用例实例,即继承了'unittest.TestCase'的子类的实例对象 test_instance )
        2.启动 Android 设备中的 APP 应用(每个用例执行一次):在每个'测试类'的 setUp 方法中执行 ( 继承 ParaCase 父类 )
        3.关闭 Android 设备中的 APP 应用 (每个用例执行一次):在每个'测试类'的 tearDown 方法中执行 ( 继承 ParaCase 父类 )

        【 保 存 截 屏 图 片 ID 的 逻 辑 】
        1.为实例对象'suite'<TestSuite>动态添加一个属性'screen_shot_id_dict' -> screen_shot_id_dict = {}
        2.每个测试方法中将所有截屏ID都保存入'screen_shot_id_list' -> screen_shot_id_dict = ['aaa', 'bbb', 'ccc']
        3.实例对象'suite'在重写的'new_run'方法中 将'screen_shot_id_list'添加入'screen_shot_id_dict'
        4.screen_shot_id_dict = { "测试类名.测试方法名":['aaa', 'bbb'], "测试类名.测试方法名":['cccc'] }

        【 并 发 线 程 数 逻 辑 】
        前提:需要先手动检查: Appium服务是否正常启动、Android设备是否正确连接
        1.获取已连接设备信息列表
         [ { "thread_index": 1, "device_name": "小米5S", "platform_version": "7.0", "device_udid": "192.168.31.136:5555", "appium_server": "http://127.0.0.1:4724/wd/hub" } } ,
           { "thread_index": 2, "device_name": "坚果Pro", "platform_version": "7.1.1", "device_udid": "192.168.31.253:4444", "appium_server": "http://127.0.0.1:4723/wd/hub" } } ]
        2.返回的列表数量 作为 线程数量

        【 每 个 用 例 使 用 Android 设 备 逻 辑 】
        通过'当前线程名索引' 获取已连接设备列表中对应的'Android'设备信息和'Appium'服务

    """
    # (定时任务)需要判断 是否存在运行中的用例
    if is_exist_start_case(pro_name):
        send_DD_for_FXC(title=pro_name, text="#### '" + pro_name + "' 项目存在<运行中>的用例而未执行测试(定时任务)")
        return "Done"

    # 获取 已连接的 Android 设备信息列表
    connected_android_device_list = config_android_device_with_appium_server_list()
    # 列表数量 作为 线程数量
    thread_num = len(connected_android_device_list)
    log.info("\n线程数量 : " + str(thread_num))
    log.info("已连接的Android设备信息列表:" + str(connected_android_device_list) + "\n")

    if thread_num == 0:
        send_DD_for_FXC(title=pro_name, text="#### '" + pro_name + "' 项目 未连接任何 Android 设备")
        return "Done"

    # 将'测试类'中的所有'测试方法'添加到 suite 对象中(每个'测试类'实例对象包含一个'测试方法')
    from TestBase.test_case_unit import ParaCase
    suite, on_line_test_method_name_list = ParaCase.get_online_case_to_suite(pro_name, connected_android_device_list)

    if suite != "mongo error":
        if is_null(on_line_test_method_name_list):
            send_DD_for_FXC(title=pro_name, text="#### '" + pro_name + "' 项目<没有上线>的用例而未执行测试(定时任务)")
        else:
            # 为实例对象'suite'<TestSuite>动态添加一个属性'screen_shot_id_dict'(目的:保存截图ID)
            setattr(suite, "screen_shot_id_dict", {})

            # 为实例对象'suite'<TestSuite>动态添加一个属性'android_device_name_dict'(目的:保存使用的Android设备名称)
            setattr(suite, "android_device_name_dict", {})

            # 为实例对象'suite'<TestSuite>动态添加一个属性'thread_num'(目的:控制多线程数量)
            setattr(suite, "thread_num", thread_num)

            # 为实例对象'suite'<TestSuite>动态添加两个方法'run_test_custom'、'show_result_custom'( 目的:供多线程中调用 )
            suite.run_test_custom = MethodType(run_test_custom, suite)
            suite.show_result_custom = MethodType(show_result_custom, suite)

            # 为实例对象'suite'<TestSuite>动态修改实例方法'run'( 目的:启用多线程来执行case )
            suite.run = MethodType(new_run, suite)

            # 运行测试,并生成测试报告
            test_result, current_report_file = generate_report(pro_name=pro_name, suite=suite, title='Android自动化测试报告 - ' + pro_name,
                                                               description='详细测试用例结果', tester="自动化测试", verbosity=2)