Exemple #1
0
class Gitlab_Client:
    def __init__(self, url: str, access_token: str):
        self.url = url
        self.access_token = access_token
        self.url = urljoin(self.url, '/api/v4')
        self.doRequest = DoRequest(self.url)
        self.doRequest.updateHeaders({'PRIVATE-TOKEN': self.access_token})

    def get_projects(self,
                     page: int = 1,
                     per_page: int = 100,
                     search='',
                     simple=True):
        params = {'page': page, 'per_page': per_page}
        httpResponseResult = self.doRequest.get(
            '/projects?simple=%s&search=%s' % (simple, search), params=params)
        return ujson.loads(httpResponseResult.body)

    def _get_project_id(self, project_name: str):
        projects = self.get_projects(search=project_name)
        for project_info in projects:
            if project_info['name'] == project_name.strip():
                return project_info['id']

    def get_project_file(self, project_name, ref, file_path):
        """
        @param project_name:
        @param ref: 分支名、tag名、commit
        @param file_path:
        @return:
        """
        project_id = self._get_project_id(project_name)
        params = {'ref': ref}
        httpResponsResult = self.doRequest.get(
            '/projects/%s/repository/files/%s' % (project_id, file_path),
            params=params)
        return ujson.loads(httpResponsResult.body)

    def update_project_file(self, project_name: str, branch_name: str,
                            file_path: str, content: str, commit_message: str):
        """
        @param project_name:
        @param branch_name:
        @param file_path:
        @param content:
        @param commit_message:
        @return:
        """
        project_id = self._get_project_id(project_name)
        params = {
            'branch': branch_name,
            'content': content,
            'commit_message': commit_message
        }
        httpResponsResult = self.doRequest.put(
            '/projects/%s/repository/files/%s' % (project_id, file_path),
            params=params)
        return ujson.loads(httpResponsResult.body)
Exemple #2
0
class DemoProjectClient(object):
    __instance = None
    __inited = None

    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self):
        if self.__inited is None:
            self.demoProjectConfig = DemoProjectReadConfig().config
            self.demoProjectDBClients = DemoProjectDBClients()
            self.doRequest = DoRequest(self.demoProjectConfig.url)
            self.csrftoken = self._initCsrftoken()

            self.__inited = True

    def _initCsrftoken(self):
        # 测试接口如果都需要先授权,可以在再次操作,将授权信息放到httpclient的headers或者cookies
        httpResponseResult = self.doRequest.get(
            "/horizon/auth/login/?next=/horizon/")
        cookies = httpResponseResult.cookies
        csrftoken = StrTool.getStringWithLBRB(cookies, 'csrftoken=', ' for')
        return csrftoken
Exemple #3
0
class DemoProjectClient():
    def __init__(self):
        self.demoProjectConfig=DemoProjectInit().getDemoProjectConfig()
        self.doRequest=DoRequest(self.demoProjectConfig.url)
        self.csrftoken=None

        self._initCsrftoken()

    def _initCsrftoken(self):
        # 测试接口如果都需要先授权,可以在再次操作,将授权信息放到httpclient的headers或者cookies
        httpResponseResult = self.doRequest.get("/horizon/auth/login/?next=/horizon/")
        cookies = httpResponseResult.cookies
        csrftoken = StrTool.getStringWithLBRB(cookies, 'csrftoken=', ' for')
        self.csrftoken = csrftoken
Exemple #4
0
def start_app_device_test(index,device_info,keyword,dir,markexpr,capture,reruns,lf):
    for path, dirs, files in os.walk('config/app_ui_tmp'):
        for file in files:
            if(int(file)==index):
                os.rename(os.path.join(path,file),os.path.join(path,str(os.getpid())))

    print('开始检测appium server是否可用......')
    try:
        doRquest = DoRequest('http://'+device_info['server_ip']+':%s/wd/hub'%device_info['server_port'].strip())
        httpResponseResult = doRquest.get('/status')
        result = ujson.loads(httpResponseResult.body)
        if result['status'] == 0:
            print('appium server状态为可用......')
        else:
            sys.exit('appium server状态为不可用')
    except:
        sys.exit('appium server状态为不可用')

    a_devices_desired_capabilities = device_info['capabilities']
    print('开始设备' + device_info['device_desc'] + '测试......')
    for desired_capabilities in a_devices_desired_capabilities:
        FileTool.writeObjectIntoFile(desired_capabilities,
                                     'config/app_ui_tmp/' + str(os.getpid()) + '_current_desired_capabilities')
        if desired_capabilities['appPackage']:
            desired_capabilities_desc = desired_capabilities['appPackage']
        else:
            desired_capabilities_desc = os.path.basename(desired_capabilities['app'])
        print('当前设备开始测试的desired_capabilities为:%s' % desired_capabilities)
        # 执行pytest前的参数准备
        pytest_execute_params = ['-c', 'config/pytest.ini', '-v', '--alluredir',
                                 'output/app_ui/' + device_info['device_desc'] + '/' + desired_capabilities_desc]
        # 判断目录参数
        if not dir:
            dir = 'cases/app_ui/'
        # 判断关键字参数
        if keyword:
            pytest_execute_params.append('-k')
            pytest_execute_params.append(keyword)
        # 判断markexpr参数
        if markexpr:
            pytest_execute_params.append('-m')
            pytest_execute_params.append(markexpr)
        # 判断是否输出日志
        if capture:
            if int(capture):
                pytest_execute_params.append('-s')
        # 判断是否失败重跑
        if reruns:
            if int(reruns):
                pytest_execute_params.append('--reruns')
                pytest_execute_params.append(reruns)
        # 判断是否只运行上一次失败的用例
        if lf:
            if int(lf):
                pytest_execute_params.append('--lf')
        pytest_execute_params.append(dir)
        # 构建孙进程
        process = multiprocessing.Process(target=pytest_main, args=(pytest_execute_params,))
        process.start()
        process.join()
        print('当前设备结束测试的desired_capabilities为:%s' % desired_capabilities)
    print('结束设备' + device_info['device_desc'] + '测试......')
    parser.add_argument('-r', '--reruns', help='失败重跑次数,默认为0', type=str)
    parser.add_argument('-lf',
                        '--lf',
                        help='是否运行上一次失败的用例,1:是、0:否,默认为0',
                        type=str)
    parser.add_argument('-clr',
                        '--clr',
                        help='是否清空已有测试结果,1:是、0:否,默认为0',
                        type=str)
    args = parser.parse_args()

    print('%s开始初始化......' % DateTimeTool.getNowTime())
    print('%s开始检测selenium server是否可用......' % DateTimeTool.getNowTime())
    try:
        doRquest = DoRequest(Read_WEB_UI_Config().web_ui_config.selenium_hub)
        httpResponseResult = doRquest.get('/status')
        result = ujson.loads(httpResponseResult.body)
        if result['status'] == 0:
            print('%sselenium server状态为可用......' % DateTimeTool.getNowTime())
        else:
            sys.exit('%sselenium server状态为不可用' % DateTimeTool.getNowTime())
    except:
        sys.exit('%sselenium server状态为不可用' % DateTimeTool.getNowTime())

    # 处理pytest文件
    deal_pytest_ini_file()

    # 初始化java依赖的libs
    java_maven_init()

    print('%s初始化基础数据......' % DateTimeTool.getNowTime())
Exemple #6
0
def start_app_device_test(index,device_info,keyword,dir,markexpr,capture,reruns,lf,clr):
    for path, dirs, files in os.walk('config/app_ui_tmp'):
        for file in files:
            if(int(file)==index):
                os.rename(os.path.join(path,file),os.path.join(path,str(os.getpid())))

    print('%s开始检测appium server是否可用......'%DateTimeTool.getNowTime())
    try:
        doRquest = DoRequest('http://'+device_info['server_ip']+':%s/wd/hub'%device_info['server_port'].strip())
        httpResponseResult = doRquest.get('/status')
        result = ujson.loads(httpResponseResult.body)
        if result['status'] == 0:
            print('%sappium server状态为可用......'%DateTimeTool.getNowTime())
        else:
            sys.exit('%sappium server状态为不可用'%DateTimeTool.getNowTime())
    except:
        print('%sappium server状态为不可用'%DateTimeTool.getNowTime())
        raise Exception('%sappium server状态为不可用'%DateTimeTool.getNowTime())

    a_devices_desired_capabilities = device_info['capabilities']
    print('%s开始设备%s测试......'%(DateTimeTool.getNowTime(),device_info['device_desc']))
    print('%s当前设备所需测试的desired_capabilities为:%s'%(DateTimeTool.getNowTime(),a_devices_desired_capabilities))
    for desired_capabilities in a_devices_desired_capabilities:
        FileTool.writeObjectIntoFile(desired_capabilities,'config/app_ui_tmp/'+str(os.getpid())+'_current_desired_capabilities')
        desired_capabilities_desc=None
        if 'appPackage' in desired_capabilities.keys():
            desired_capabilities_desc = desired_capabilities['appPackage']
        elif 'app' in desired_capabilities.keys():
            desired_capabilities_desc = desired_capabilities['app'].split('/')[-1]
        elif 'bundleId' in desired_capabilities.keys():
            desired_capabilities_desc = desired_capabilities['bundleId']
        print('%s当前设备开始测试的desired_capabilities为:%s'%(DateTimeTool.getNowTime(),desired_capabilities))
        # 执行pytest前的参数准备
        pytest_execute_params = ['-c', 'config/pytest.ini', '-v', '--alluredir', 'output/app_ui/%s/%s/report_data/'%(device_info['device_desc'],desired_capabilities_desc)]
        # 判断目录参数
        if not dir:
            dir = 'cases/app_ui/'
        # 判断关键字参数
        if keyword:
            pytest_execute_params.append('-k')
            pytest_execute_params.append(keyword)
        # 判断markexpr参数
        if markexpr:
            pytest_execute_params.append('-m')
            pytest_execute_params.append(markexpr)
        # 判断是否输出日志
        if capture:
            if int(capture):
                pytest_execute_params.append('-s')
        # 判断是否失败重跑
        if reruns:
            if int(reruns):
                pytest_execute_params.append('--reruns')
                pytest_execute_params.append(reruns)
        # 判断是否只运行上一次失败的用例
        if lf:
            if int(lf):
                pytest_execute_params.append('--lf')
        # 判断是否清空已有测试结果
        if clr:
            if int(clr):
                pytest_execute_params.append('--clean-alluredir')
        pytest_execute_params.append(dir)
        # 构建孙进程
        process = multiprocessing.Process(target=pytest_main,args=(pytest_execute_params,))
        process.start()
        process.join()
        print('%s当前设备结束测试的desired_capabilities为:%s' % (DateTimeTool.getNowTime(),desired_capabilities))
    print('%s结束设备%s测试......'%(DateTimeTool.getNowTime(),device_info['device_desc']))
class Gitlab_Client:
    def __init__(self, url: str, username: str, password: str):
        self.url = url
        self.username = username
        self.password = password
        self.url = urljoin(self.url, '/api/v3')
        self.doRequest = DoRequest(self.url)
        self.private_token = self._get_private_token()
        self._path_private_token = '?private_token=%s' % self.private_token

    def _login(self):
        httpResponseResult = self.doRequest.post_with_form(
            '/session?login=%s&password=%s' % (self.username, self.password))
        return httpResponseResult

    def _get_private_token(self):
        user_info = self._login().body
        user_info = ujson.loads(user_info)
        return user_info['private_token']

    def get_user(self):
        return ujson.loads(self._login().body)

    def get_projects(self, page: int = 1, per_page: int = 100):
        params = {'page': 1, 'per_page': 100}
        httpResponseResult = self.doRequest.get('/projects%s' %
                                                self._path_private_token,
                                                params=params)
        return ujson.loads(httpResponseResult.body)

    def _get_project_id(self, project_name: str):
        projects = self.get_projects()
        for project_info in projects:
            if project_info['name'] == project_name.strip():
                return project_info['id']

    def get_project_tree(self, project_name: str):
        project_id = self._get_project_id(project_name)
        httpResponsResult = self.doRequest.get(
            '/projects/%s/repository/tree%s' %
            (project_id, self._path_private_token))
        return ujson.loads(httpResponsResult.body)

    def get_project_file(self, project_name, ref, file_path):
        """
        @param project_name:
        @param ref: 分支名、tag名、commit
        @param file_path:
        @return:
        """
        project_id = self._get_project_id(project_name)
        params = {'file_path': file_path, 'ref': ref}
        httpResponsResult = self.doRequest.get(
            '/projects/%s/repository/files%s' %
            (project_id, self._path_private_token),
            params=params)
        return ujson.loads(httpResponsResult.body)

    def update_project_file(self, project_name: str, branch_name: str,
                            file_path: str, content: str, commit_message: str):
        """
        @param project_name:
        @param branch_name:
        @param file_path:
        @param content:
        @param commit_message:
        @return:
        """
        project_id = self._get_project_id(project_name)
        params = {
            'file_path': file_path,
            'branch_name': branch_name,
            'content': content,
            'commit_message': commit_message
        }
        httpResponsResult = self.doRequest.put(
            '/projects/%s/repository/files%s' %
            (project_id, self._path_private_token),
            params=params)
        return ujson.loads(httpResponsResult.body)
Exemple #8
0
class AppOperator:
    """
    类中的element参数可以有appium.webdriver.webelement.WebElement和pojo.elementInfo.ElementInfo类型
    """
    def __init__(self, driver):
        self._config = Read_APP_UI_Config().app_ui_config
        self._doRequest = DoRequest(self._config.appium_hub)
        self._doRequest.setHeaders({'Content-Type': 'application/json'})
        self._driver = driver
        self._session_id = driver.session_id
        # 获得设备支持的性能数据类型
        self._performance_types = json.loads(
            self._doRequest.post_with_form(
                '/session/' + self._session_id +
                '/appium/performanceData/types').body)['value']
        # 获取当前窗口大小
        self._windows_size = self.get_window_size()

    def _change_element_to_webElement_type(self, element):
        if isinstance(element, ElementInfo):
            webElement = self.getElement(element)
        elif isinstance(element, WebElement):
            webElement = element
        else:
            return None
        return webElement

    def get(self, url):
        self._driver.get(url)

    def get_current_url(self):
        return self._driver.current_url

    def getTitle(self):
        return self._driver.title

    def getText(self, element):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            return webElement.text

    def click(self, element):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement.click()

    def submit(self, element):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement.submit()

    def sendText(self, element, text):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement.clear()
            webElement.send_keys(text)

    def is_displayed(self, element):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            flag = webElement.is_displayed()
            return flag

    def is_enabled(self, element):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            flag = webElement.is_enabled()
            return flag

    def is_selected(self, element):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            flag = webElement.is_selected()
            return flag

    def select_dropDownBox_by_value(self, element, value):
        """
        适用单选下拉框
        :param element:
        :param value:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement = Select(webElement)
            webElement.select_by_value(value)

    def select_dropDownBox_by_text(self, element, text):
        """
        适用单选下拉框
        :param element:
        :param text:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement = Select(webElement)
            webElement.select_by_visible_text(text)

    def select_dropDownBox_by_index(self, element, index):
        """
        适用单选下拉框,下标从0开始
        :param element:
        :param index:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement = Select(webElement)
            webElement.select_by_index(index)

    def select_dropDownBox_by_values(self, element, values):
        """
        适用多选下拉框
        :param element:
        :param values:以数组传参
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement = Select(webElement)
            webElement.deselect_all()
            for value in values:
                webElement.select_by_value(value)

    def select_dropDownBox_by_texts(self, element, texts):
        """
        适用多选下拉框
        :param element:
        :param texts:以数组传参
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement = Select(webElement)
            webElement.deselect_all()
            for text in texts:
                webElement.select_by_visible_text(text)

    def select_dropDownBox_by_indexs(self, element, indexs):
        """
        适用多选下拉框,下标从0开始
        :param element:
        :param indexs: 以数组传参
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement = Select(webElement)
            webElement.deselect_all()
            for index in indexs:
                webElement.select_by_index(index)

    def switch_to_window(self, window_name):
        """
        仅使用web
        :param window_name:
        :return:
        """
        self._driver.switch_to.window(window_name)

    def switch_to_frame(self, frame_name):
        """
        仅使用web
        :param frame_name:
        :return:
        """
        self._driver.switch_to.frame(frame_name)

    def page_forward(self):
        """
        仅使用web
        :return:
        """
        self._driver.forward()

    def pag_back(self):
        """
        仅使用web
        :return:
        """
        self._driver.back()

    def dismiss_alert(self):
        """
        仅使用web
        :return:
        """
        alert = self._driver.switch_to.alert
        alert.dismiss()

    def accept_alert(self):
        """
        仅使用web
        :return:
        """
        alert = self._driver.switch_to.alert
        alert.accept()

    def get_alert_text(self):
        """
        仅使用web
        :return:
        """
        alert = self._driver.switch_to.alert
        return alert.text

    def get_screenshot(self, fileName):
        fileName = DateTimeTool.getNowTime('%Y%m%d%H%M%S%f_') + fileName
        allure.attach(name=fileName,
                      body=self._driver.get_screenshot_as_png(),
                      attachment_type=allure.attachment_type.PNG)

    def refresh(self):
        self._driver.refresh()

    def uploadFile(self, element, filePath):
        """
        仅适用于web
        适用于元素为input且type="file"的文件上传
        :param element:
        :param filePath:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            webElement.send_keys(os.path.abspath(filePath))

    def switch_to_parent_frame(self):
        """
        切换到父frame(仅使用web)
        :return:
        """
        self._driver.switch_to.parent_frame()

    def get_property(self, element, property_name):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            return webElement.get_property(property_name)

    def get_attribute(self, element, attribute_name):
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            return webElement.get_attribute(attribute_name)

    def get_element_outer_html(self, element):
        return self.get_attribute(element, 'outerHTML')

    def get_element_inner_html(self, element):
        return self.get_attribute(element, 'innerHTML')

    def get_page_source(self):
        return self._driver.page_source

    def get_captcha(self, element, language='eng'):
        """
        识别图片验证码
        :param element: 验证码图片元素
        :param language: eng:英文,chi_sim:中文
        :return:
        """
        # 为防止截图包含高亮影响识别,元素不进行高亮
        captcha_webElement = self._change_element_to_webElement_type(element)
        left = captcha_webElement.location['x']
        top = captcha_webElement.location['y']
        right = captcha_webElement.location['x'] + captcha_webElement.size[
            'width']
        bottom = captcha_webElement.location['y'] + captcha_webElement.size[
            'height']
        # 首先进行屏幕截图
        captcha_image_file_name = DateTimeTool.getNowTime(
            '%Y%m%d%H%M%S%f_') + 'captcha.png'
        captcha_image_file_name = os.path.abspath('output/' +
                                                  captcha_image_file_name)
        self._driver.get_screenshot_as_file(captcha_image_file_name)
        img = Image.open(captcha_image_file_name)
        # 验证码图片裁切并保存
        img = img.crop((left, top, right, bottom))
        img.save(captcha_image_file_name)
        # 识别图片验证码
        captcha = CaptchaRecognitionTool.captchaRecognition(
            captcha_image_file_name, language)
        captcha = captcha.strip()
        captcha = captcha.replace(' ', '')
        return captcha

    def get_table_data(self, element, data_type='text'):
        """
        以二维数组返回表格每一行的每一列的数据[[row1][row2][colume1,clume2]]
        :param element:
        :param data_type: text-返回表格文本内容,html-返回表格html内容,webElement-返回表格元素
        :return:
        """
        if isinstance(element, ElementInfo):
            # 由于表格定位经常会出现【StaleElementReferenceException: Message: stale element reference: element is not attached to the page document 】异常错误,
            # 解决此异常只需要用显示等待,保证元素存在即可,显示等待类型中visibility_of_all_elements_located有实现StaleElementReferenceException异常捕获,
            # 所以强制设置表格定位元素时使用VISIBILITY_OF
            element.wait_type = Wait_By.VISIBILITY_OF
            webElement = self.getElement(element)
        elif isinstance(element, WebElement):
            webElement = element
        else:
            return None
        table_data = []
        table_trs = webElement.find_elements_by_tag_name('tr')
        try:
            for tr in table_trs:
                tr_data = []
                tr_tds = tr.find_elements_by_tag_name('td')
                if data_type.lower() == 'text':
                    for td in tr_tds:
                        tr_data.append(td.text)
                elif data_type.lower() == 'html':
                    for td in tr_tds:
                        tr_data.append(td.get_attribute('innerHTML'))
                elif data_type.lower() == 'webelement':
                    tr_data = tr_tds
                table_data.append(tr_data)
        except StaleElementReferenceException as e:
            print('获取表格内容异常:' + e.msg)
        return table_data

    def get_window_size(self):
        return self._driver.get_window_size()

    def get_geolocation(self):
        """
        返回定位信息,纬度/经度/高度
        :return:
        """
        httpResponseResult = self._doRequest.get('/session/' +
                                                 self._session_id +
                                                 '/location')
        return httpResponseResult.body

    def set_geolocation(self, latitude, longitude, altitude):
        """
        设置定位信息
        :param latitude: 纬度 -90 ~ 90
        :param longitude: 精度 ~180 ~ 180
        :param altitude: 高度
        :return:
        """
        geolocation = {}
        location = {}
        location.update({'latitude': latitude})
        location.update({'longitude': longitude})
        location.update({'altitude': altitude})
        geolocation.update({'location': location})
        self._doRequest.post_with_form('/session/' + self._session_id +
                                       '/location',
                                       params=json.dumps(geolocation))

    def get_current_activity(self):
        """
        获得Android的activity
        :return:
        """
        return self._driver.current_activity

    def get_current_package(self):
        """
        获得Android的package
        :return:
        """
        return self._driver.current_package

    def execute_javascript(self, script):
        """
        仅适用于web
        :param script:
        :return:
        """
        self._driver.execute_script(script)

    def install_app(self, filePath):
        self._driver.install_app(os.path.abspath(filePath))

    def remove_app(self, app_id):
        self._driver.remove_app(app_id)

    def launch_app(self):
        self._driver.launch_app()

    def reset_app(self):
        """
        重置app,可以进入下一轮app测试
        :return:
        """
        return self._driver.reset()

    def close_app(self):
        self._driver.close_app()

    def background_app(self, seconds):
        """
        后台运行
        :param seconds:
        :return:
        """
        self._driver.background_app(seconds)

    def push_file_to_device(self, device_filePath, local_filePath):
        """
        上传文件设备
        :param device_filePath:
        :param local_filePath:
        :return:
        """
        local_filePath = os.path.abspath(local_filePath)
        with open(local_filePath, 'rb') as f:
            data = base64.b64encode(f.read())
            f.close()
        self._driver.push_file(device_filePath, data)

    def pull_file_from_device(self, device_filePath, local_filePath):
        """
        从设备上下载文件
        :param device_filePath:
        :param local_filePath:
        :return:
        """
        local_filePath = os.path.abspath(local_filePath)
        data = self._driver.pull_file(device_filePath)
        with open(local_filePath, 'wb') as f:
            f.write(base64.b64decode(data))
            f.close()

    def shake_device(self):
        """
        仅支持IOS,详见https://github.com/appium/appium/blob/master/docs/en/commands/device/interactions/shake.md
        :return:
        """
        self._driver.shake()

    def lock_screen(self, seconds=None):
        self._driver.lock(seconds)

    def unlock_screen(self):
        self._driver.unlock()

    def press_keycode(self, keycode):
        """
        按键盘按键
        :param keycode: 键盘上每个按键的ascii
        :return:
        """
        self._driver.press_keycode(keycode)

    def long_press_keycode(self, keycode):
        """
        长按键盘按键
        :param keycode:
        :return:
        """
        self._driver.long_press_keycode(keycode)

    def hide_keyboard(self, key_name=None, key=None, strategy=None):
        """
        隐藏键盘,ios需要指定key_name或strategy,Android无需参数
       :param key_name:
        :param key:
        :param strategy:
        :return:
        """
        self._driver.hide_keyboard(key_name, key, strategy)

    def toggle_airplane_mode(self):
        """
        切换飞行模式(开启关闭),仅支持Android
        :return:
        """
        self._doRequest.post_with_form('/session/' + self._session_id +
                                       '/appium/device/toggle_airplane_mode')

    def toggle_data(self):
        """
        切换蜂窝数据模式(开启关闭),仅支持Android
        :return:
        """
        self._doRequest.post_with_form('/session/' + self._session_id +
                                       '/appium/device/toggle_data')

    def toggle_wifi(self):
        """
        切换wifi模式(开启关闭),仅支持Android
        :return:
        """
        self._doRequest.post_with_form('/session/' + self._session_id +
                                       '/appium/device/toggle_wifi')

    def toggle_location_services(self):
        """
        切换定位服务模式(开启关闭),仅支持Android
        :return:
        """
        self._driver.toggle_location_services()

    def get_performance_date(self,
                             data_type,
                             package_name=None,
                             data_read_timeout=10):
        """
        获得设备性能数据
        :param package_name:
        :param data_type: cpuinfo、batteryinfo、networkinfo、memoryinfo
        :param data_read_timeout:
        :return:
        """
        if data_type in self._performance_types:
            params = {}
            if not package_name:
                package_name = self.get_current_package()
            params.update({'packageName': package_name})
            params.update({'dataType': data_type})
            params.update({'dataReadTimeout': data_read_timeout})
            httpResponseResult = self._doRequest.post_with_form(
                '/session/' + self._session_id + '/appium/getPerformanceData',
                params=json.dumps(params))
            return httpResponseResult.body
        else:
            return None

    def start_recording_screen(self):
        """
        默认录制为3分钟,android最大只能3分钟,ios最大只能10分钟。如果录制产生的视频文件过大无法放到手机内存里会抛异常,所以尽量录制短视频
        :return:
        """
        self._driver.start_recording_screen(forcedRestart=True)

    def stop_recording_screen(self, fileName=''):
        """
        停止录像并将视频附加到报告里
        :param fileName:
        :return:
        """
        fileName = DateTimeTool.getNowTime('%Y%m%d%H%M%S%f_') + fileName
        data = self._driver.stop_recording_screen()
        allure.attach(name=fileName,
                      body=base64.b64decode(data),
                      attachment_type=allure.attachment_type.MP4)

    def get_device_time(self):
        """
        获得设备时间
        :return:
        """
        return self._driver.device_time

    def get_element_location(self, element):
        """
        获得元素在屏幕的位置,x、y坐标
        :param element:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            return webElement.location

    def get_element_size_in_pixels(self, element):
        """
        返回元素的像素大小
        :param element:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            return webElement.size

    def get_all_contexts(self):
        """
        获得能够自动化测所有上下文(混合应用中的原生应用和web应用)
        :return:
        """
        return self._driver.contexts

    def get_current_context(self):
        """
        获得当前appium中正在运行的上下文(混合应用中的原生应用和web应用)
        :return:
        """
        return self._driver.current_context

    def switch_context(self, context_name):
        """
        切换上下文(混合应用中的原生应用和web应用)
        :param context_name:
        :return:
        """
        context = {}
        context.update({'name': context_name})
        self._doRequest.post_with_form('/session/' + self._session_id +
                                       '/context',
                                       params=json.dumps(context))

    def mouse_move_to(self, element, xoffset=None, yoffset=None):
        """
        移动鼠标到指定位置(仅适用于Windows、mac)
        1、如果xoffset和yoffset都None,则鼠标移动到指定元素的正中间
        2、如果element、xoffset和yoffset都不为None,则根据元素的左上角做x和y的偏移移动鼠标
        :param element:
        :param xoffset:
        :param yoffset:
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if element:
            actions = ActionChains(self._driver)
            if xoffset and yoffset:
                actions.move_to_element_with_offset(webElement, xoffset,
                                                    yoffset)
            actions.move_to_element(webElement)
            actions.perform()

    def mouse_click(self):
        """
        点击鼠标当前位置(仅适用于Windows、mac)
        :return:
        """
        actions = ActionChains(self._driver)
        actions.click()
        actions.perform()

    def mouse_double_click(self):
        """
        双击鼠标当前位置(仅适用于Windows、mac)
        :return:
        """
        actions = ActionChains(self._driver)
        actions.double_click()
        actions.perform()

    def mouse_click_and_hold(self):
        """
        长按鼠标(仅适用于Windows、mac)
        :return:
        """
        actions = ActionChains(self._driver)
        actions.click_and_hold()
        actions.perform()

    def mouse_release_click_and_hold(self):
        """
        停止鼠标长按(仅适用于Windows、mac)
        :return:
        """
        actions = ActionChains(self._driver)
        actions.release()
        actions.perform()

    def touch_tap(self,
                  element,
                  xoffset=None,
                  yoffset=None,
                  count=1,
                  is_perfrom=True):
        """
        触屏点击
        1、如果xoffset和yoffset都None,则在指定元素的正中间进行点击
        2、如果element、xoffset和yoffset都不为None,则根据元素的左上角做x和y的偏移然后进行点击
        :param element:
        :param xoffset:
        :param yoffset:
        :param count: 点击次数
        :param is_perfrom 是否马上执行动作,不执行可以返回动作给多点触控执行
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            actions = TouchAction(self._driver)
            actions.tap(element, xoffset, yoffset, count)
            if is_perfrom:
                actions.perform()
            return actions

    def touch_long_press(self,
                         element,
                         xoffset=None,
                         yoffset=None,
                         duration_sconds=10,
                         is_perfrom=True):
        """
        触屏长按
        1、如果xoffset和yoffset都None,则在指定元素的正中间进行长按
        2、如果element、xoffset和yoffset都不为None,则根据元素的左上角做x和y的偏移然后进行长按
        :param element:
        :param xoffset:
        :param yoffset:
        :param duration_sconds: 长按秒数
        :param is_perfrom 是否马上执行动作,不执行可以返回动作给多点触控执行
        :return:
        """
        webElement = self._change_element_to_webElement_type(element)
        if webElement:
            actions = TouchAction(self._driver)
            actions.long_press(webElement, xoffset, yoffset,
                               duration_sconds * 1000)
            if is_perfrom:
                actions.perform()
            return actions

    def multi_touch_actions_perform(self, touch_actions):
        """
        多点触控执行
        :param touch_actions:
        :return:
        """
        multiActions = MultiAction(self._driver)
        for actions in touch_actions:
            multiActions.add(actions)
        multiActions.perform()

    def touch_slide(self,
                    start_element=None,
                    start_x=None,
                    start_y=None,
                    end_element=None,
                    end_x=None,
                    end_y=None,
                    duration=None):
        """
        滑动屏幕,在指定时间内从一个位置滑动到另外一个位置
        1、如果start_element不为None,则从元素的中间位置开始滑动
        2、如果end_element不为None,滑动结束到元素的中间位置
        :param start_element:
        :param end_element:
        :param start_x:
        :param start_y:
        :param end_x:
        :param end_y:
        :param duration: 毫秒
        :return:
        """
        start_webElement = self._change_element_to_webElement_type(
            start_element)
        end_webElement = self._change_element_to_webElement_type(end_element)
        if start_webElement:
            start_webElement_location = self.get_element_location(
                start_webElement)
            start_x = start_webElement_location['x']
            start_y = start_webElement_location['y']
        if end_webElement:
            end_webElement_location = self.get_element_location(end_webElement)
            end_x = end_webElement_location['x']
            end_y = end_webElement_location['y']
        self._driver.swipe(start_x, start_y, end_x, end_y, duration)

    def touch_left_slide(self, duration=500):
        """
        从屏幕正中间进行左滑
        :return:
        """
        start_x = self._windows_size['width'] * 0.45
        start_y = self._windows_size['height'] * 0.45
        end_x = 0
        end_y = start_y
        self._driver.swipe(start_x, start_y, end_x, end_y, duration)

    def touch_right_slide(self, duration=500):
        """
        从屏幕正中间进行右滑
        :return:
        """
        start_x = self._windows_size['width'] * 0.45
        start_y = self._windows_size['height'] * 0.45
        end_x = self._windows_size['width'] * 0.9
        end_y = start_y
        self._driver.swipe(start_x, start_y, end_x, end_y, duration)

    def touch_up_slide(self, duration=500):
        """
        从屏幕正中间进行上滑
        :return:
        """
        start_x = self._windows_size['width'] * 0.45
        start_y = self._windows_size['height'] * 0.45
        end_x = start_x
        end_y = 0
        self._driver.swipe(start_x, start_y, end_x, end_y, duration)

    def touch_down_slide(self, duration=500):
        """
        从屏幕正中间进行下滑
        :return:
        """
        start_x = self._windows_size['width'] * 0.45
        start_y = self._windows_size['height'] * 0.45
        end_x = start_x
        end_y = self._windows_size['height'] * 0.9
        self._driver.swipe(start_x, start_y, end_x, end_y, duration)

    def getElement(self, elementInfo):
        """
        定位单个元素
        :param elementInfo:
        :return:
        """
        webElement = None
        locator_type = elementInfo.locator_type
        locator_value = elementInfo.locator_value
        wait_type = elementInfo.wait_type
        wait_seconds = elementInfo.wait_seconds
        wait_expected_value = elementInfo.wait_expected_value
        if wait_expected_value:
            wait_expected_value = wait_expected_value

        # 查找元素,为了保证元素被定位,都进行显式等待
        if wait_type == Wait_By.TITLE_IS:
            webElement = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.title_is(wait_expected_value))
        elif wait_type == Wait_By.TITLE_CONTAINS:
            webElement = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.title_contains(wait_expected_value))
        elif wait_type == Wait_By.PRESENCE_OF_ELEMENT_LOCATED:
            webElement = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.presence_of_element_located(
                    (locator_type, locator_value)))
        elif wait_type == Wait_By.ELEMENT_TO_BE_CLICKABLE:
            webElement = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.element_to_be_clickable(
                    (locator_type, locator_value)))
        elif wait_type == Wait_By.ELEMENT_LOCATED_TO_BE_SELECTED:
            webElement = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.element_located_to_be_selected(
                    (locator_type, locator_value)))
        elif wait_type == Wait_By.VISIBILITY_OF:
            webElements = WebDriverWait(self._driver, wait_seconds).until(
                (expected_conditions.visibility_of_all_elements_located(
                    (locator_type, locator_value))))
            if len(webElements) > 0:
                webElement = webElements[0]
        else:
            if locator_type == By.ID:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_id(locator_value))
            elif locator_type == By.NAME:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_name(locator_value))
            elif locator_type == By.LINK_TEXT:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_link_text(
                        locator_value))
            elif locator_type == By.XPATH:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_xpath(locator_value))
            elif locator_type == By.PARTIAL_LINK_TEXT:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_partial_link_text(
                        locator_value))
            elif locator_type == By.CSS_SELECTOR:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_css_selector(
                        locator_value))
            elif locator_type == By.CLASS_NAME:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_class_name(
                        locator_value))
            elif locator_type == By.TAG_NAME:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_tag_name(
                        locator_value))
            elif locator_type == Locator_Type.ACCESSIBILITY_ID:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_accessibility_id(
                        locator_value))
            elif locator_type == Locator_Type.IMAGE:
                webElement = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_element_by_image(locator_type))
        return webElement

    def getElements(self, elementInfo):
        """
        定位多个元素
        :param elementInfo:
        :return:
        """
        webElements = None
        locator_type = elementInfo.locator_type
        locator_value = elementInfo.locator_value
        wait_type = elementInfo.wait_type
        wait_seconds = elementInfo.wait_seconds

        # 查找元素,为了保证元素被定位,都进行显式等待
        if wait_type == Wait_By.PRESENCE_OF_ELEMENT_LOCATED:
            webElements = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.presence_of_all_elements_located(
                    (locator_type, locator_value)))
        elif wait_type == Wait_By.VISIBILITY_OF:
            webElements = WebDriverWait(self._driver, wait_seconds).until(
                expected_conditions.visibility_of_all_elements_located(
                    (locator_type, locator_value)))
        else:
            if locator_type == By.ID:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_id(locator_value))
            elif locator_type == By.NAME:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_name(locator_value))
            elif locator_type == By.LINK_TEXT:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_link_text(
                        locator_value))
            elif locator_type == By.XPATH:
                webElements = WebDriverWait(
                    self._driver,
                    wait_seconds).until(lambda driver: driver.
                                        find_elements_by_xpath(locator_value))
            elif locator_type == By.PARTIAL_LINK_TEXT:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_partial_link_text(
                        locator_value))
            elif locator_type == By.CSS_SELECTOR:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_css_selector(
                        locator_value))
            elif locator_type == By.CLASS_NAME:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_class_name(
                        locator_value))
            elif locator_type == By.TAG_NAME:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_tag_name(
                        locator_value))
            elif locator_type == Locator_Type.ACCESSIBILITY_ID:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_accessibility_id(
                        locator_value))
            elif locator_type == Locator_Type.IMAGE:
                webElements = WebDriverWait(self._driver, wait_seconds).until(
                    lambda driver: driver.find_elements_by_image(locator_type))
        return webElements

    def getSubElement(self, parent_element, sub_elementInfo):
        """
        获得元素的单个子元素
        :param parent_element: 父元素
        :param sub_elementInfo: 子元素,只能提供pojo.elementInfo.ElementInfo类型
        :return:
        """
        webElement = self._change_element_to_webElement_type(parent_element)
        if not webElement:
            return None
        if not isinstance(sub_elementInfo, ElementInfo):
            return None

        # 通过父元素查找子元素
        locator_type = sub_elementInfo.locator_type
        locator_value = sub_elementInfo.locator_value
        wait_seconds = sub_elementInfo.wait_seconds

        # 查找元素,为了保证元素被定位,都进行显式等待
        if locator_type == By.ID:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_id(locator_value))
        elif locator_type == By.NAME:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_name(locator_value))
        elif locator_type == By.LINK_TEXT:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_link_text(locator_value))
        elif locator_type == By.XPATH:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_xpath(locator_value))
        elif locator_type == By.PARTIAL_LINK_TEXT:
            subWebElement = WebDriverWait(webElement, wait_seconds).until(
                lambda webElement: webElement.
                find_element_by_partial_link_text(locator_value))
        elif locator_type == By.CSS_SELECTOR:
            subWebElement = WebDriverWait(webElement, wait_seconds).until(
                lambda webElement: webElement.find_element_by_css_selector(
                    locator_value))
        elif locator_type == By.CLASS_NAME:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_class_name(locator_value))
        elif locator_type == By.TAG_NAME:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_tag_name(locator_value))
        elif locator_type == Locator_Type.ACCESSIBILITY_ID:
            subWebElement = WebDriverWait(webElement, wait_seconds).until(
                lambda webElement: webElement.find_element_by_accessibility_id(
                    locator_value))
        elif locator_type == Locator_Type.IMAGE:
            subWebElement = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_element_by_image(locator_type))
        else:
            return None
        return subWebElement

    def getSubElements(self, parent_element, sub_elementInfo):
        """
        获得元素的多个子元素
        :param parent_element: 父元素
        :param sub_elementInfo: 子元素,只能提供pojo.elementInfo.ElementInfo类型
        :return:
        """
        webElement = self._change_element_to_webElement_type(parent_element)
        if not webElement:
            return None
        if not isinstance(sub_elementInfo, ElementInfo):
            return None

        # 通过父元素查找多个子元素
        locator_type = sub_elementInfo.locator_type
        locator_value = sub_elementInfo.locator_value
        wait_seconds = sub_elementInfo.wait_seconds

        # 查找元素,为了保证元素被定位,都进行显式等待
        if locator_type == By.ID:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_id(locator_value))
        elif locator_type == By.NAME:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_name(locator_value))
        elif locator_type == By.LINK_TEXT:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_link_text(locator_value))
        elif locator_type == By.XPATH:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_xpath(locator_value))
        elif locator_type == By.PARTIAL_LINK_TEXT:
            subWebElements = WebDriverWait(webElement, wait_seconds).until(
                lambda webElement: webElement.
                find_elements_by_partial_link_text(locator_value))
        elif locator_type == By.CSS_SELECTOR:
            subWebElements = WebDriverWait(webElement, wait_seconds).until(
                lambda webElement: webElement.find_elements_by_css_selector(
                    locator_value))
        elif locator_type == By.CLASS_NAME:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_class_name(locator_value))
        elif locator_type == By.TAG_NAME:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_tag_name(locator_value))
        elif locator_type == Locator_Type.ACCESSIBILITY_ID:
            subWebElements = WebDriverWait(webElement, wait_seconds).until(
                lambda webElement: webElement.
                find_elements_by_accessibility_id(locator_value))
        elif locator_type == Locator_Type.IMAGE:
            subWebElements = WebDriverWait(
                webElement,
                wait_seconds).until(lambda webElement: webElement.
                                    find_elements_by_image(locator_type))
        else:
            return None
        return subWebElements

    def explicit_wait_page_title(self, elementInfo):
        """
        仅适用于web
        显式等待页面title
        :param elementInfo:
        :return:
        """
        self.getElement(elementInfo)

    def getDriver(self):
        return self._driver
Exemple #9
0
class Disconf_Client:
    def __init__(self,
                 url: str,
                 username: str,
                 password: str,
                 is_verify_ssl_cer=True):
        self.url = url
        self.username = username
        self.password = password
        self.doRequest = DoRequest(self.url)
        self.doRequest.setVerify(is_verify_ssl_cer)
        self._login()

    def _login(self):
        params = {
            'name': 'admin_test',
            'password': '******',
            'remember': '1'
        }
        httpResponseResult = self.doRequest.post_with_form(
            '/api/account/signin', params)
        return ujson.loads(httpResponseResult.body)

    def get_app_list(self):
        httpResponseResult = self.doRequest.get('/api/app/list')
        app_list = ujson.loads(httpResponseResult.body)
        app_list = app_list['page']['result']
        return app_list

    def get_app_id(self, app_name: str):
        app_list = self.get_app_list()
        for app_info in app_list:
            if app_info['name'] == app_name:
                return app_info['id']

    def get_env_list(self):
        httpResponseResult = self.doRequest.get('/api/env/list')
        env_list = ujson.loads(httpResponseResult.body)
        env_list = env_list['page']['result']
        return env_list

    def get_env_id(self, env_name: str):
        env_list = self.get_env_list()
        for env_info in env_list:
            if env_info['name'] == env_name:
                return env_info['id']

    def get_version_list(self, app_id: int, env_id: int):
        params = {'appId': app_id, 'envid': env_id}
        httpResponseResult = self.doRequest.get('/api/web/config/versionlist',
                                                params)
        version_list = ujson.loads(httpResponseResult.body)
        version_list = version_list['page']['result']
        return version_list

    def get_config_list(self,
                        app_id: int,
                        env_id: int,
                        version: str,
                        pageSize: int = 50,
                        pageNo: int = 1):
        params = {
            'appId': app_id,
            'envId': env_id,
            'version': version,
            "page.pageSize": pageSize,
            "page.pageNo": pageNo
        }
        httpResponseResult = self.doRequest.get('/api/web/config/list', params)
        config_list = ujson.loads(httpResponseResult.body)
        config_list = config_list['page']['result']
        return config_list

    def get_config_id(self, app_name: str, env_name: str, version: str,
                      config_name: str):
        now_page = 1
        # 最多从500个文件获取
        while (not now_page > 10):
            config_list = self.get_config_list(self.get_app_id(app_name),
                                               self.get_env_id(env_name),
                                               version,
                                               pageSize=50,
                                               pageNo=now_page)
            for config_info in config_list:
                if config_info['key'] == config_name:
                    return config_info['configId']
            now_page += 1

    def get_config_info(self, config_id: int):
        httpResponseResult = self.doRequest.get('/api/web/config/%s' %
                                                config_id)
        config_info = ujson.loads(httpResponseResult.body)
        config_info = config_info['result']['value']
        return config_info

    def update_config_info(self, config_id: int, content: str):
        params = {'fileContent': content}
        httpResponseResult = self.doRequest.put(
            '/api/web/config/filetext/%s' % config_id, params)
        config_info = ujson.loads(httpResponseResult.body)
        return config_info