一文学懂 python3+selenium

一文学懂 python3+selenium

一、目录结构及架构

image-20210617103904796

  • common:存放公共使用库
  • config:配置目录
  • data:测试数据,yaml格式
  • driver:存放浏览器驱动的exe
  • elements:测试页面元素,yaml格式
  • img:存放执行用例时截图后图片的路径
  • logs:日志路径
  • pages:每个页面py文件,包括basepage
  • reports:执行用例后生成报告路径
  • testcases:存放每个用例
  • venv:环境
  • run_testcase.py:程序入口

为了降低web自动化测试的维护成本,降低代码冗余,提升测试用例的可读性,故衍生出了PageObject模式。

PO模式主要体现在对界面交互细节的封装,大体分为如下三层:

1、BasePage层:封装页面操作最基本的方法,如:打开/关闭浏览器,定位元素等,可被其他对象继承

2、Page层:提供对具体页面元素的定位、操作方法的封装

3、testcase业务层:传入具体的参数,组织业务流程,执行自动化

二、目录及代码介绍

  1. common

    image-20210617104539913

    代码:

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    import configparser
    import os
    import sys
    
    from selenium import webdriver
    from common.global_variable import Common
    
    from time import sleep
    
    from common.logger import Logger
    log = Logger()
    
    
    class BrowserEngine(object):
        # 配置文件路径
        config_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'config', 'config.ini')
        # chromedriver 路径
        chrome_driver_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'driver', 'chromedriver.exe')
        # msedgedriver 路径
        edge_driver_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), 'driver', 'msedgedriver.exe')
    
        def open_browser(self):
            """
            打开浏览器
            :param driver:
            :return:
            """
            # 读取配置文件,获取浏览器驱动类型、目标 url
            config = configparser.ConfigParser()
            config.read(self.config_path)
            browser = config.get("browserType", "browserName")
            url = config.get("baseUrl", "url")
            # 判断配置文件读取到的浏览器驱动类型
            if browser == "chrome":
                self.driver = webdriver.Chrome(self.chrome_driver_path)
            elif browser == "edge":
                self.driver = webdriver.Edge(self.edge_driver_path)
    
            self.driver.get(url)
            self.driver.maximize_window()
    
            log.info("打开浏览器, browser is [%s], url is [%s]" % (browser, url))
            Common().set_driver(self.driver)
    
        def close_browser(self):
            """
            关闭浏览器
            :return:
            """
            log.info("关闭浏览器")
            Common.driver.quit()
    
    
    import os
    
    import yaml
    
    
    class GetYamlUtils(object):
        def __init__(self, page_name):
            """
            拼接页面地址,如果不存在则自动创建
            """
            self.page_name = page_name
            self.cur_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    
        def get_elements(self):
            """
            获取页面元素
            """
            self.page_path = os.path.join(os.path.join(self.cur_path, 'elements'), self.page_name)
            if not os.path.exists(self.page_path):
                os.mkdir(self.page_path)
            with open(self.page_path, 'r', encoding='utf-8') as f:
                elements = yaml.load(f, Loader=yaml.FullLoader)
            return elements
    
        def get_data(self):
            """
            获取数据
            """
            self.page_path = os.path.join(os.path.join(self.cur_path, 'data'), self.page_name)
            if not os.path.exists(self.page_path):
                os.mkdir(self.page_path)
            with open(self.page_path, 'r', encoding='utf-8') as f:
                data = yaml.load(f, Loader=yaml.FullLoader)
            return data
    
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    
    class Common:
        driver = None  # 类变量driver,全局其他地方通过这个类变量来访问driver对象
    
        def set_driver(self, driver):
            Common.driver = driver
            return Common.driver
    
    import logging
    import time
    import os
    import sys
    
    
    class Logger:
        def __init__(self):
            # 设置日志存储路径/日志名称
            root_path = os.path.dirname(os.path.abspath(sys.argv[0]))
            current_time = time.strftime('%Y-%m-%d-%H%M%S')
            self.log_name = os.path.join(root_path, 'logs', f'faxservertest-{current_time}.log')
    
        def printConsoleLog(self, level, message):
            # 创建一个 logger
            logger = logging.getLogger()
            logger.setLevel(logging.DEBUG)
            # 创建一个 handler,用于写入日志文件
            file_handler = logging.FileHandler(self.log_name, 'a', encoding='utf-8')
            file_handler.setLevel(logging.DEBUG)
            # 再创建一个 handler,用于输出到控制台
            console_handler = logging.StreamHandler()
            console_handler.setLevel(logging.DEBUG)
            # 定义 handler 的输出格式
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            file_handler.setFormatter(formatter)
            console_handler.setFormatter(formatter)
            # 给logger添加handler
            logger.addHandler(file_handler)
            logger.addHandler(console_handler)
            # 记录一条日志
            if level == 'info':
                logger.info(message)
            elif level == 'debug':
                logger.debug(message)
            elif level == 'warning':
                logger.warning(message)
            elif level == 'error':
                logger.error(message)
            logger.removeHandler(file_handler)
            logger.removeHandler(console_handler)
            # 关闭打开的文件
            file_handler.close()
    
        def debug(self, message):
            self.printConsoleLog('debug', message)
    
        def info(self, message):
            self.printConsoleLog('info', message)
    
        def warning(self, message):
            self.printConsoleLog('warning', message)
    
        def error(self, message):
            self.printConsoleLog('error', message)
    
    
    if __name__ == '__main__':
        pass
    
    import unittest
    import os
    import sys
    
    from common.logger import Logger
    from common.global_variable import Common
    
    
    log = Logger()
    
    
    class UnittestCommon(unittest.TestCase):
        def setUp(self):
            """
            执行测试用例前的操作
            :return:
            """
            log.info("==================== Start Testing ====================")
    
        @classmethod
        def setUpClass(cls):
            pass
            # log.info("==================== Start Testing ====================")
    
        @classmethod
        def tearDownClass(cls):
            pass
            # log.info("==================== End Testing ====================")
    
        def tearDown(self):
            """
            执行完测试用例后的操作
            :return:
            """
            log.info("==================== End Testing ====================")
    
        def save_img(self, img_name):
            root_path = os.path.dirname(os.path.abspath(sys.argv[0]))
            screenshots_name = os.path.join(root_path, 'img', f'{img_name}.png')
            if os.path.exists(screenshots_name):
                os.remove(screenshots_name)
            try:
                Common.driver.get_screenshot_as_file(screenshots_name)
            except NameError as e:
                log.error("failed to get windows img with %s" % e)
    
    
    if __name__ == '__main__':
        pass
    
    
  2. config

    image-20210617105044502

    配置:

    [browserType]
    browserName = chrome
    
    [baseUrl]
    url = http://193.1.1.121/webserver/
    
  3. data

    image-20210617105221215

    例如

    #用户名
    username: test
    #密码
    password: 123456
    
  4. driver

    image-20210617105412980

  5. elements

    image-20210617105451414

    例如:

    #提示界面,如果有多个,取最后一个
    #header
    header: xpath=>//div[@class='x-window x-message-box x-layer x-window-default x-closable x-window-closable x-window-default-closable x-border-box'][last()]/div[contains(@id,'header')]
    #body
    body: xpath=>//div[@class='x-window x-message-box x-layer x-window-default x-closable x-window-closable x-window-default-closable x-border-box'][last()]/div[contains(@id,'body')]
    #toolbar
    toolbar: xpath=>//div[@class='x-window x-message-box x-layer x-window-default x-closable x-window-closable x-window-default-closable x-border-box'][last()]/div[contains(@id,'toolbar')]
    
    #显示内容:display
    span_text_mode: //td/div[contains(@id,'displayfield-input')]/span
    #按钮:button
    span_button_mode: //a/span/span/span[text()='{}']/..
    
  6. pages

    image-20210617105642313

    base_page.py

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    """
    @File    :base_page.py
    @Desc    :页面基类,封装一些浏览器操作常用方法
    """
    import os
    import sys
    import time
    
    from selenium.common.exceptions import NoSuchElementException,TimeoutException,WebDriverException
    from common.global_variable import Common
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.action_chains import ActionChains
    from selenium.webdriver.common.keys import Keys
    from common.browser_engine import BrowserEngine
    
    
    from common.logger import Logger
    log = Logger()
    
    
    class BasePage(object):
        """
        封装页面通用方法,比如:driver的实例化
        """
        def __init__(self, base_driver=None):
            if base_driver is not None:
                self.driver = base_driver
            else:
                self.driver = Common.driver
            #如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常,换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0
            self.driver.implicitly_wait(30) #隐式等待20秒,webdriver驱动器对象下的方法;针对是一次会话所有操作,相当于是一个全局等待;只需要声明定义一次,通常在设计脚本中会应用于setUp方法;
    
        def close_browser(self):
            """
            退出浏览器
            :return:
            """
            try:
                self.driver.quit()
            except NameError as e:
                log.error("failed to close browser with %s" % e)
    
        def forward(self):
            """
            浏览器前进操作
            :return:
            """
            try:
                self.driver.forward()
            except NameError as e:
                log.error("failed to forward browser with %s" % e)
    
        def back(self):
            """
            浏览器返回操作
            :return:
            """
            try:
                self.driver.back()
            except NameError as e:
                log.error("failed to back browser with %s" % e)
    
        def close_current_window(self):
            """
            关闭当前窗口
            :return:
            """
            try:
                self.driver.close()
            except NameError as e:
                log.error("failed to close the current window with %s" % e)
    
        def find_element(self, selector):
            """
            元素定位
            :param selector:
            :return:
            """
            element = ''
            if '=>' not in selector:
                return self.driver.find_element_by_id(selector)
            selector_by = selector.split('=>')[0]
            selector_value = selector.split('=>')[1]
    
            if selector_by == 'id':
                try:
                    element=WebDriverWait(self.driver,20).until(EC.presence_of_element_located((By.ID,selector_value)))
                    #element = self.driver.find_element_by_id(selector_value)
                    log.info("by is [%s], value is [%s]" % (selector_by, selector_value))
                except NoSuchElementException as e:
                    log.error("failed to find element with %s" % e)
                except TimeoutException as e:
                    log.error("find element timeout: %s" % e)
            elif selector_by == 'xpath':
                try:
                    element = WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.XPATH, selector_value)))
                    #element = self.driver.find_element_by_xpath(selector_value)
                    log.info("by is [%s], value is [%s]" % (selector_by, selector_value))
                except NoSuchElementException as e:
                    log.error("failed to find element with %s" % e)
                except TimeoutException as e:
                    log.error("find element timeout: %s" % e)
            else:
                raise NameError("please enter a valid type of targeting elements.")
    
            return element
    
        def find_elements(self, selector):
            """
                    元素定位
                    :param selector:
                    :return:
                    """
            elements = ''
            if '=>' not in selector:
                return self.driver.find_elements_by_id(selector)
            selector_by = selector.split('=>')[0]
            selector_value = selector.split('=>')[1]
    
            if selector_by == 'id':
                try:
                    elements = WebDriverWait(self.driver, 20).until(EC.presence_of_all_elements_located((By.ID, selector_value)))
                    #elements = self.driver.find_elements_by_id(selector_value)
                    log.info("by is [%s], value is [%s]" % (selector_by, selector_value))
                except NoSuchElementException as e:
                    log.error("failed to find element with %s" % e)
                except TimeoutException as e:
                    log.error("find element timeout: %s" % e)
            elif selector_by == 'xpath':
                try:
                    elements = WebDriverWait(self.driver, 20).until(
                        EC.presence_of_all_elements_located((By.XPATH, selector_value)))
                    #elements = self.driver.find_elements_by_xpath(selector_value)
                    log.info("by is [%s], value is [%s]" % (selector_by, selector_value))
                except NoSuchElementException as e:
                    log.error("failed to find element with %s" % e)
                except TimeoutException as e:
                    log.error("find element timeout: %s" % e)
            else:
                raise NameError("please enter a valid type of targeting elements.")
    
            return elements
    
    
        def input(self, selector, text, s=False):
            """
            文本输入
            :param selector:
            :param text:
            :return:
            """
            if s:
                eles = self.find_elements(selector)
                try:
                    for ele in eles:
                        if ele.is_displayed():
                            ele.clear()
                            ele.send_keys(text)
                            self.sleep(0.5)
                            log.info("send keys is [%s]" % text)
                except NameError as e:
                    log.error("failed to entered in the input box with %s" % e)
            else:
                ele = self.find_element(selector)
                ele.clear()
                try:
                    ele.send_keys(text)
                    self.sleep(0.5)
                    log.info("send keys is [%s]" % text)
                except NameError as e:
                    log.error("failed to entered in the input box with %s" % e)
    
        def clear(self, selector):
            """
            清除文本框内容
            :param selector:
            :return:
            """
            ele = self.find_element(selector)
            try:
                ele.clear()
            except NameError as e:
                log.error("failed to clear the input box content with %s" % e)
    
        def click(self, selector, s=False):
            """
            点击元素事件
            :param selector:
            :return:
            """
            # log.info("---click is in: " + selector)
            if s:
                eles=self.find_elements(selector)
                try:
                    for ele in eles:
                        if ele.is_displayed():
                            #self.sleep(0.5)
                            ele.click()
                except NameError as e:
                    log.error("failed to click the element with %s" % e)
            else:
                ele = self.find_element(selector)
                try:
                    #self.sleep(0.5)
                    ele.click()
                except NameError as e:
                    log.error("failed to click the element with %s" % e)
    
        def get_page_title(self):
            """
            获取网页标题
            :return:
            """
            log.info("Current page title is [%s]" % self.driver.title)
            return self.driver.title
    
        def get_page_text(self, selector):
            """
            获取span标签的内容
            :return:
            """
            ele = self.find_element(selector)
            text=''
            try:
                log.info("text is [%s]" % ele.text)
                text=ele.text
            except NameError as e:
                log.error("failed to find span text %s" % e)
            finally:
                return text
    
        def get_attribute(self,selector,keyword):
            """
            获取标签某一属性
            :return:
            """
            ele = self.find_element(selector)
            value = ''
            try:
                value=ele.get_attribute(keyword)
                if keyword is "innerHTML":
                    log.info("keyword id [%s];value is [html...]" % (keyword))
                else:
                    log.info("keyword id [%s];value is [%s]" % (keyword,value))
            except NameError as e:
                log.error("failed to find span text %s" % e)
            finally:
                return value
    
        def switch_to_alert(self, accept=True):
            try:
                alert=self.driver.switch_to_alert()
                log.info("alert text is : [%s]" % (alert.text))
                if accept:
                    alert.accept()
                else:
                    alert.dismiss()
    
            except Exception as e:
                log.error("not find alert %s" % e)
    
        def get_all_handles(self):
            all_handles = self.driver.window_handles
            return all_handles
    
        #将某个元素拖拽到某个元素然后松开 ----> drag_and_drop(source, target)
    
        def select_move_drop(self, source_selector, target_selector):
            try:
                dragElement=self.find_element(source_selector)
                targetElement=self.find_element(target_selector)
                Action=ActionChains(self.driver)
                Action.drag_and_drop(dragElement,targetElement).perform()
                self.sleep(5)
            except Exception as e:
                log.error("failed to drag and drop %s" % e)
    
        def move_to_element_xy(self,to_element,x,y):
            e=self.find_element(to_element)
            ActionChains(self.driver).move_to_element_with_offset(e,x,y).click().perform()
    
    
        #某个键盘键被按下
        def key_down(self,value):
            ActionChains(self.driver).key_down(value=value).perform()
        #松开某个键
        def key_up(self,value):
            ActionChains(self.driver).key_up(value=value).perform()
        #鼠标右键单击
        def right_click(self):
            ActionChains(self.driver).context_click().perform()
        #鼠标左键双击
        def double_click(self):
            ActionChains(self.driver).double_click().perform()
    
        @staticmethod
        def sleep(seconds):
            """
            等待
            :param seconds:
            :return:
            """
            time.sleep(seconds)
    

    例如:login_page.py

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    
    from pages.base_page import BasePage
    from common.get_yaml_utils import GetYamlUtils
    from common.logger import Logger
    log = Logger()
    
    """
    在这个页面登录界面,例如登录,忘记密码等
    """
    
    class LoginPage(BasePage):
        login_ele = GetYamlUtils('login_page.yaml').get_elements()
        username_input = (login_ele['username_input'])
        password_input = (login_ele['password_input'])
        login_button = (login_ele['login_button'])
        login_success=(login_ele['login_success'])
    
        login_data = GetYamlUtils('login_page.yaml').get_data()
        username= (login_data['username'])
        password= (login_data['password'])
    
        def __init__(self):
            super(LoginPage, self).__init__()
            log.info("----------进入登录界面----------")
    
        def input_username(self, username=None):
            if username is None:
                username = self.username
            log.info("----------输入用户名: {}----------".format(username))
            self.input(self.username_input, username)
    
        def input_password(self, password=None):
            if password is None:
                password = self.password
            log.info("----------输入密码: {}----------".format(password))
            self.input(self.password_input, password)
    
        def click_login_btn(self):
            log.info("----------点击 登录 按钮----------")
            self.click(self.login_button)
    
        def check_login_success(self):
            log.info("----------检查登录是否成功?----------")
            return self.get_page_text(self.login_success)
    
  7. testcases

    image-20210617105911744

    例如:test_a_login_page.py

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    
    import time
    import os
    import sys
    
    
    from pages.login_page import LoginPage
    from common.logger import Logger
    from common.unittest_common import UnittestCommon
    from BeautifulReport import BeautifulReport
    from pages.tip_page import TipPage
    
    log = Logger()
    
    
    class TestLoginPage(UnittestCommon):
        @BeautifulReport.add_test_img('用户名不存在-登录失败')
        def test_a_login_fail(self):
            """
            登录-用户名不存在,登录失败
            """
            try:
                login = LoginPage()
                #输入用户名,用户名不存在
                login.input_username(username='zhangsan')
                #输入密码
                login.input_password()
                #点击登录按钮
                login.click_login_btn()
                time.sleep(2)
                self.save_img(img_name='用户名不存在-登录失败')
                #关闭提示
                tip=TipPage()
                tip.click_btn(name='确定')
                time.sleep(5)
                log.info('Test pass')
            except Exception as e:
                log.error('Test fail with: %s.' % e)
    
        @BeautifulReport.add_test_img('密码错误-登录失败')
        def test_b_login_fail(self):
            """
            登录-密码错误,登录失败
            """
            try:
                login = LoginPage()
                # 输入用户名,用户名不存在
                login.input_username()
                # 输入密码
                login.input_password(password='abcdefg')
                # 点击登录按钮
                login.click_login_btn()
                time.sleep(2)
                # 保存图片
                self.save_img(img_name='密码错误-登录失败')
                # 关闭提示
                tip = TipPage()
                tip.click_btn(name='确定')
                time.sleep(5)
                log.info('Test pass')
            except Exception as e:
                log.error('Test fail with: %s.' % e)
    
        def test_login_success(self):
            """
            登录-用户名,密码正确,登录成功
            """
            login = LoginPage()
            login.input_username()
            login.input_password()
    
            login.click_login_btn()
            time.sleep(10)
            try:
                assert '登录成功' in login.check_login_success()
                log.info('Test pass')
            except Exception as e:
                log.error('Test fail with: %s.' % e)
    
    
    
    if __name__ == '__main__':
        pass
    
  8. run_testcase.py

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    
    import time
    import unittest
    import os
    from BeautifulReport import BeautifulReport as bf
    from common.browser_engine import BrowserEngine
    
    
    def all_case():
        current_time = time.strftime("%Y-%m-%d-%H%M%S", time.localtime(time.time()))
        file_name = current_time + '-TestReport.html'
        case_path = os.path.join(os.getcwd(), "testcases")
        discover = unittest.defaultTestLoader.discover(case_path, pattern="test*.py")
        bf(discover).report(filename=file_name, description='测试报告', report_dir='reports')
    
    def driver_init():
        BrowserEngine().open_browser()
    
    def driver_end():
        BrowserEngine().close_browser()
    
    
    
    if __name__ == '__main__':
        #driver初始化
        driver_init()
        #执行所有用例
        all_case()
        #关闭浏览器
        driver_end()
    

三、结果展示

image-20210617111423474

image-20210617111520593

四、关键代码分析

1. 在测试报告html中展示截图图片

image-20210617112103056

self.save_img代码调用:

 def save_img(self, img_name):
        root_path = os.path.dirname(os.path.abspath(sys.argv[0]))
        screenshots_name = os.path.join(root_path, 'img', f'{img_name}.png')
        if os.path.exists(screenshots_name):
            os.remove(screenshots_name)
        try:
            Common.driver.get_screenshot_as_file(screenshots_name)
        except NameError as e:
            log.error("failed to get windows img with %s" % e)

@BeautifulReport.add_test_img 装饰器代码分析:

image-20210617112618383

def add_test_img(*pargs):
        """
            接受若干个图片元素, 并展示在测试报告中
        :param pargs:
        :return:
        """

        def _wrap(func):
            @wraps(func)
            def __wrap(*args, **kwargs):
                img_path = os.path.abspath('{}'.format(BeautifulReport.img_path))
                os.makedirs(img_path, exist_ok=True)
                testclasstype = str(type(args[0]))
                #print(testclasstype)
                testclassnm = testclasstype[testclasstype.rindex('.') + 1:-2]
                #print(testclassnm)
                img_nm = testclassnm + '_' + func.__name__
                #print(img_nm)
                try:
                    result = func(*args, **kwargs)
                except Exception:
                    #print("出现异常")
                    if 'save_img' in dir(args[0]):
                        #print("save_img")
                        save_img = getattr(args[0], 'save_img')
                        save_img(os.path.join(img_path, img_nm + '.png'))
                        data = BeautifulReport.img2base(img_path, img_nm + '.png')
                        print(HTML_IMG_TEMPLATE.format(data, data))
                    sys.exit(0)
                print('<br></br>')
                #print(img_path)
                #print(pargs[0])
                if len(pargs) > 1:
                    for parg in pargs:
                        print(parg + ':')
                        data = BeautifulReport.img2base(img_path, parg + '.png')
                        print(HTML_IMG_TEMPLATE.format(data, data))
                    return result
                #print(img_path + pargs[0] + '.png')   
                if not os.path.exists(img_path +'\\'+ pargs[0] + '.png'):
                    return result
                data = BeautifulReport.img2base(img_path, pargs[0] + '.png')
                print(HTML_IMG_TEMPLATE.format(data, data))
                return result

            return __wrap

        return _wrap

image-20210617112856633

​ 先调用save_img函数进行截图,存放路径必须是项目目录下的img目录,因为BeautifulReport库写的是img,然后BeautifulReport调用add_test_img(‘xxx’)函数时,就会取img目录的名称为xxx.png的图片,然后写进报告html中。

2. 使用共同的driver

image-20210617114422635

image-20210617114505433

image-20210617114551386

其它地方调用:

image-20210617114658051

3. ActionChains使用

#将某个元素拖拽到某个元素然后松开 ----> drag_and_drop(source, target)

    def select_move_drop(self, source_selector, target_selector):
        try:
            dragElement=self.find_element(source_selector)
            targetElement=self.find_element(target_selector)
            Action=ActionChains(self.driver)
            Action.drag_and_drop(dragElement,targetElement).perform()
            self.sleep(5)
        except Exception as e:
            log.error("failed to drag and drop %s" % e)

    def move_to_element_xy(self,to_element,x,y):
        e=self.find_element(to_element)
        ActionChains(self.driver).move_to_element_with_offset(e,x,y).click().perform()

image-20210617115010988

image-20210617115309754

4. XPATH

  • contains:

    //div[@class='x-window x-layer x-window-default x-border-box'][last()]/div[contains(@id,'body')]
    
    //tr/td/label[contains(text(),'{}')]/../../td/input
    
  • text:

    //a/span/span/span[text()='{}']/..
    
  • starts-with:

    //div[@class='x-panel x-border-item x-box-item x-panel-default']//div[starts-with(@id,'{}')]/div[contains(@id,'body')]
    

    注意:没有ends-with

  • and:

    //input[contains(@id,'fileuploadfield') and @name='filePath']
    
  • 可以多次使用//

    image-20210617135605223

    5. 元素

    • get_attribute():

      value=e.get_attribute(keyword)
      
    • text:

      e.text
      
    • is_displayed(): 是否显示

    • is_enabled(): 是否可编辑或者点击

    • is_selected(): 是否可选

    6. 等待

    • 智能等待

      WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.XPATH, xpath)))
      
    • 隐式等待

       #如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常,换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0
              self.driver.implicitly_wait(30) #隐式等待20秒,webdriver驱动器对象下的方法;针对是一次会话所有操作,相当于是一个全局等待;只需要声明定义一次,通常在设计脚本中会应用于setUp方法;
      
      

    7. yaml

    • 字典型,:后面需要空格

      username: test
      
    • 数组型,-后面需要空格

      phone_book_add:
        - dispName: 显示名
        - lastName:- firstName:- gender:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值