• 关于Selemium那些事


    近期在看虫师编著的selenium 3自动化测试实战这本书,整体感觉这本书还是挺不错的,适用于一些初学者的入门书籍,它里面除了包含一些selenium相关的操作介绍,还浅谈了一下pytest和unittest这两个测试框,以及pom模型和appnium。不足的是,书中整个过程都是围绕百度首页的搜索功能为例,个人感觉实战性其实不是很强,另外就是在整本书中,并没有一个完整性的项目实例,对于一些selenium操作功能的讲解也不是非常深入。因为我之前已经了解过这块,并且还出了一篇博客,所以其实对于我个人来说参考价值不是很大,但整本书作为初学者的资料参考还是有一定的价值的。今天就给大家介绍下我这几天浅显的学习成果,希望各位能够介绍一些包含源码解析以及整体性实战项目的书籍给我

    实践项目框架

    在这里插入图片描述

    project
        - base
            - 存放基础类
        - config
            - setting.py   配置日志、测试报告、测试数据存放的地址等信息
        - data
            - locatorData  存放定位数据
            - test_data    存放测试数据
        - logs
            - 存放生成日志
        - page
            - 页面元素定位即相关操作方法包
        - test_case
            - 测试用例包
        - test_report
            - 生成的测试报告
            - screenshots  失败截图
        - tools
            - loadData.py  加载读取文件数据
            - log.py  生成日志文件
            - sendMessage.py 发送邮件
        - conftest.py 本地测试配置文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    项目整体POM模型

    Page Object Model , 页面对象模型 , 对页面进行抽象或者说建模的过程,是把一个具体的页面转化为编程语言中的一个对象,页面特性转化为
    对象的属性,页面操作转化为对象的方法。主要用来实现页面操作和测试逻辑的一个分离, 将业务和实现分开,这样不仅提高了一些基础常用代码的
    复用性, 也降低了代码间的耦合度, 使代码层级变得更加清晰,代码更易维护
    
    • 1
    • 2
    • 3

    本项目在base文件夹下创建了一个base_Page.py文件,其中创建了一个Tools类,该类封装了一些常用到的页面定位方法。在page下对每个具体的页面进行抽象化,一个页面测试点对应一个具体的类,这些类都继承了Tools方法,并且封装了当前测试点所用到的页面的特性定位和页面操作动作,为了实现更好地分离,页面定位数据均放在data.locatorData下的文件中,这样,一旦前端对页面元素进行了修改,我们只需要修改这些定位数据。而test_case下的测试用例只需要通过调用每个page类中便于识别的方法实现测试逻辑即可。

    在这里插入图片描述

    base_page.py

    # 作者:yaxin.liang
    # 日期:2022/9/13 10:43
    # python版本:3.0
    from selenium.webdriver import ActionChains
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    
    
    class Tools:
        '''
        初始化浏览器
        :param  driver = webdriver.Chrome()
        '''
        def __init__(self,driver):
            self.driver = driver
    
        # 访问浏览器
        def open(self,url):
            self.driver.get(url)
    
        '''
        设置浏览器窗口的大小
        :param 不传则为None 即自适应浏览器界面大小
        '''
        def set_Windows_size(self,width=None,high=None):
            if width != None and high != None:
                self.driver.set_window_size(width,high)
            else:
                self.driver.maximize_window()
    
    
        # 元素定位 find_element(By.ID,"pwd")  *解包元组
        def locator(self,loc):
            try:
                a = WebDriverWait(self.driver, 10, 0.5).until(
                    EC.visibility_of_element_located(loc)
                )
                return self.driver.find_element(*loc)
            except Exception as e:
                # print('页面中未找到 %s 元素'(loc))
                raise e
    
        # 定位一组元素
        def locators(self,loc):
            try:
                a = WebDriverWait(self.driver, 5, 0.5).until(
                    EC.visibility_of_any_elements_located(loc)
                )
                return self.driver.find_elements(*loc)
            except Exception as e:
                # print('页面中未找到 %s 元素'(loc))
                raise e
    
        # 输入 定位后才能输入
        def input(self,loc,txt):
            self.locator(loc).send_keys(txt)
    
        # 转换frame
        def switch_frame(self,frame):
            self.driver.switch_to.frame(frame)
    
        # 点击
        def on_click(self,loc):
            self.locator(loc).click();
    
        # 执行 JavaScript 脚本
        def js(self,script):
            self.driver.execute_script(script)
    
        # 鼠标悬浮
        def actionPerform_move(self,loc):
            action = ActionChains(self.driver)
            action.move_to_element(self.locator(loc))
            action.perform()
    
        # 判断元素是否存在
        def isElementExist(self,loc):
            flag = True
            try:
                self.locator(loc)
                return flag
            except:
                flag = False
                return flag
    
        # 关闭
        def quit(self):
            self.driver.quit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    login_page_location.py

    # 作者:yaxin.liang
    # 日期:2022/10/8 13:53
    # python版本:3.0
    
    from selenium.webdriver.common.by import By
    
    # 页面地址
    url = "http://beta.kktv8.com/?pageId=100&actionid=10001"
    
    # 定位首页登录按钮
    login_link_id_local = (By.ID, "loginLink")
    # 定位登录弹窗
    login_frame_local = (By.XPATH, "/html/body/div[5]/div/div/div/div/iframe")
    # 定位输入账号文本框
    login_zhanghao_local = (By.XPATH, "/html/body/div[1]/div[1]/div/div[2]/div[1]/input")
    # 定位输入密码文本框
    login_password_local = (By.XPATH, "/html/body/div[1]/div[1]/div/div[2]/div[2]/input")
    # 定位登录弹窗内的登录按钮
    login_click_local = (By.XPATH, "/html/body/div[1]/div[1]/div/a")
    # 定位登录成功后弹出的message提醒窗关闭按钮
    login_message_click_local = (By.XPATH, "/html/body/div[6]/div/table/tbody/tr[3]/td/div[2]/button")
    # 定位已登录头像 用来确定当前登录状态
    login_sure_is_logined_local = (By.CSS_SELECTOR,
                             '#ReactWrap > div > div.nav_wrap.false > div > div > div.sub_wrap.clearfix > div.nav_right > ul > div > ul > li > a > img')
    # 定位已登录的退出按钮
    exit_local = (By.XPATH, '//*[@id="ReactWrap"]/div/div[1]/div/div/div[3]/div[2]/ul/div/ul/li/div/div/div[2]/div[2]/a')
    # 定位登陆失败
    login_sure_is_fail_local = (By.XPATH, '/html/body/div[1]/div[1]/div/div[6]/span/span[contains(text(),"请输入正确的账号和密码")]')
    # 定位登录账号密码输入框清除按钮
    login_zhanghao_clear_local = (By.XPATH, '/html/body/div[1]/div[1]/div/div[2]/div[1]/input')
    login_password_clear_local = (By.XPATH, '/html/body/div[1]/div[1]/div/div[2]/div[2]/input')
    # 定位退出登录弹窗按钮
    login_iframe_exit_local = (By.XPATH, '/html/body/div[1]/div[1]/a')
    
    # 定位登录成功后的用户头像信息
    login_success_local = (By.XPATH, '//*[@id="ReactWrap"]/div/div[1]/div/div/div[3]/div[2]/ul/div/ul/li/a/img')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    login_page.py

    # 作者:yaxin.liang
    # 日期:2022/9/13 11:00
    # python版本:3.0
    
    
    from selenium import webdriver
    
    from myPractice.base.base_Page import Tools
    
    # 八大定位元素:id、name、class_name、xpath、css_selector、tag_name、link_text、partial_link_text
    from myPractice.tools.logger import atp_log
    from myPractice.data.locatorData.login_page_location import *
    
    
    
    class LoginPage(Tools):
    
        def get_login_page(self):
            atp_log.info("点击首页登录按钮,弹出登陆弹窗")
            ele = self.on_click(login_link_id_local)
            return ele
    
        def input_login_message(self,login_zhanghao_text,login_password_text):
            atp_log.info("输入登录账号密码")
            self.input(login_zhanghao_local,login_zhanghao_text)
            self.input(login_password_local,login_password_text)
    
        def local_frame(self):
            atp_log.info("定位登录弹窗")
            frame = self.locator(login_frame_local)
            return frame
    
        def local_exit_login(self):
            atp_log.info("退出登录弹窗")
            self.on_click(login_iframe_exit_local)
    
        def local_success_message(self):
            atp_log.info("定位登录成功后的信息")
            src = self.locator(login_success_local).get_attribute('src')
            return src
    
        def local_is_logined(self):
            atp_log.info("定位是否已经有账号登录")
            flag = self.isElementExist(login_sure_is_logined_local)
            return flag
    
        def local_and_exit(self):
            atp_log.info("正在退出当前登录")
            self.actionPerform_move(login_sure_is_logined_local)
            self.actionPerform_move((exit_local))
            self.on_click(exit_local)
    
        def local_login_button(self):
            atp_log.info("登录")
            self.on_click(login_click_local)
    
        def local_login_button_class_name(self):
            atp_log.info("检查登录按钮是否可点击")
            class_name = self.locator(login_click_local).get_attribute("class")
            return class_name
    
        def local_login_sure_is_fail(self):
            atp_log.info("定位是否登陆失败")
            flag = self.isElementExist(login_sure_is_fail_local)
            return flag
    
        def local_and_exit_login_message(self):
            # 判断是否弹出协议,是的话点击隐藏
            atp_log.info("关闭消息提醒弹窗")
            if self.isElementExist(login_message_click_local):
                self.on_click(login_message_click_local)
    
        def local_and_clear_login_message(self):
            atp_log.info("清除登录弹窗内的账号密码信息")
            if self.locator(login_zhanghao_local).text:
                self.on_click(self.locators(login_zhanghao_clear_local))
            if self.locator(login_password_local).text:
                self.on_click(self.locators(login_password_clear_local))
    
    
        def login(self,login_zhanghao_text,login_password_text):
            # 判断是否已经有账号登录
            if self.local_is_logined():
                atp_log.info("当前已登录!")
                self.local_and_exit()
                atp_log.info("已退出当前登录")
            else:
                atp_log.info("未登录!")
            self.get_login_page()
            frame = self.local_frame()
            self.switch_frame(frame)
            self.input_login_message(login_zhanghao_text,login_password_text)
            self.local_login_button()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    test_case_login.py

    # 作者:yaxin.liang
    # 日期:2022/10/9 13:59
    # python版本:3.0
    import os
    import time
    
    import allure
    import pytest
    from selenium import webdriver
    
    from myPractice.config.setting import url
    from myPractice.conftest import browser, base_url
    from myPractice.tools.common import loadYaml, loadJson, get_html_reports
    from myPractice.page.login_page import LoginPage
    from myPractice.tools.logger import atp_log
    
    @allure.feature('登录')
    class TestLogin:
        # 用例执行前要做的事
        def setup_class(cls) -> None:
            cls.driver = webdriver.Chrome()
            cls.driver.maximize_window()
            cls.lp = LoginPage(cls.driver)
            cls.lp.open(url)
            print('start setup_class...............')
    
        @allure.story('登录成功01')
        @allure.description('读取yaml文件数据')
        # # 读取yaml格式文件
        @pytest.mark.parametrize('utxt', loadYaml('../data/test_data/login.yaml'))
        def test_01(self, utxt):
            # driver = browser
            # lp = LoginPage(driver)
            # lp.open(base_url)
            try:
                self.lp.login(utxt['username'], utxt['pwd'])
                # 判断登陆结果是否正确
                scr = str(self.lp.local_success_message())
                assert utxt['username'] in scr
                self.lp.local_and_exit_login_message()
            except Exception as e:
                atp_log.info("TestLogin_test_01登录出错,具体报错:",e)
                assert False
    
        @allure.story('登录成功02')
        @allure.description('读取json文件数据')
        # 读取json格式文件
        def test_02(self):
            # 获取测试数据
            utxt = loadJson('../data/test_data/login.json')[0]
            # driver = browser
            # lp = LoginPage(driver)
            # lp.open(base_url)
            try:
                atp_log.info("开始对数据"+utxt['username']+":"+utxt['pwd']+"测试")
                self.lp.login(utxt['username'], utxt['pwd'])
                # 判断登陆结果是否正确
                scr = str(self.lp.local_success_message())
                assert utxt['username'] in scr
                atp_log.info("TestLogin_test_02登录成功")
                self.lp.local_and_exit_login_message()
            except Exception as e:
                atp_log.info("TestLogin_test_02登录出错,具体报错:", e)
                assert False
    
    
        # @allure.story('登陆失败01')
        # @allure.description('用户名错误,登陆失败')
        @pytest.mark.parametrize('utxt', loadJson('../data/test_data/login_fail.json'))
        def test_03(self,utxt):
            # driver = browser
            # lp = LoginPage(driver)
            # lp.open(base_url)
            story, description = utxt["story"], utxt["description"]
            allure.dynamic.story(story)
            allure.dynamic.description(description)
            try:
                atp_log.info("开始对数据" + utxt['username'] + ":" + utxt['pwd'] + "测试")
                self.lp.login(utxt['username'], utxt['pwd'])
                class_name = self.lp.local_login_button_class_name()
                # 判断登陆结果是否失败,失败则清除输入账号密码文本框,并关闭登录窗
                if class_name == 'back btn disabled':
                    atp_log.info("登录按钮不可点击:" + class_name)
                    assert True
                else:
                    atp_log.info("登录按钮可点击")
                    assert self.lp.local_login_sure_is_fail()
                atp_log.info("TestLogin_test_03登录失败,失败理由:"+ utxt["description"])
            except Exception as e:
                atp_log.info("TestLogin_test_03登录出错,具体报错:", e)
                assert False
            finally:
                self.lp.local_and_clear_login_message()
                self.lp.local_exit_login()
    
        # 用例执行后要做的事
        def teardown_class(cls) -> None:
            cls.driver.quit()
            atp_log.info("test 结束!")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    Selenium基础

    主流的web端UI自动化测试工具,支持多种编程语言,Selenium API提供了多种操作web的类和方法,Selenium Grid支持自动化测试的分布式执行。Selenium底层使用的是HTTP协议。

    工作原理:在Selenium客户端使用Java、Python等语言编写操作指令,通过webDriver启动各个浏览器对象,并使用相应的API对浏览器对象进行操作,然后浏览器对象将响应结果传回到webDriver,由webDriver再传回到我们的客户端程序。在这个过程中,webDriver充当了一个代理服务器的角色。

    八大元素定位

    定位单个元素:find_element(定位方式,定位值)

    定位一组元素:find_elements(定位方式,定位值)

    - id 通过元素的唯一id值定位
    	find_element_by_id("id值")
    	find_element(By.ID, "id值")
    - name 通过元素的name属性值定位
        find_element_by_name("name值")
        find_element(By.NAME, "name值")
    - class 通过元素的class属性值定位
        find_element_by_class_name("class的值")
        find_element(By.CLASS_NAME, "class的值")
    - tag 通过元素的标签名定位
        find_element_by_tag_name("tag的值")
        find_element(By.TAG_NAME, "tag的值")
    - link 通过链接文本内容定位文本链接
        find_element_by_link_text("链接文本的值")
        find_element(By.LINK_TEXT, "链接文本的值")
    - partial link 通过部分链接文本内容定位文本链接
        find_element_by_partial_link_text("部分链接文本的值")
        find_element(By.PARTIAL_LINK_TEXT, "部分链接文本的值")
    - xpath 通过HTML规则进行定位
        - 绝对路径定位
        	find_element_by_xpath("xml文件规则的路径")
        	find_element(By.XPATH, "xml文件规则的路径")
        - 元素属性定位 元素需要是唯一
        	find_element(By.XPATH, "//元素的标签[@标签内属性='属性值']")
        	find_element(By.XPATH, "//*[@标签内属性='属性值']")
        - 层级与属性结合定位
        	find_element(By.XPATH, "//上一级元素标签/.../上一级元素标签[@标签内属性='属性值']/标签名")
        - 逻辑运算符定位
        	find_element(By.XPATH, "//元素标签名[@标签内属性='属性值' and @标签内属性='属性值']")
        	find_element(By.XPATH, "//元素标签名[@标签内属性='属性值' or @标签内属性='属性值']")
        - contains定位
        	find_element(By.XPATH, "//元素标签名[contains(@标签内属性,'属性值')]"
        - text定位
        	find_element(By.XPATH, "//标签名[text(),'text值']")
        	find_element(By.XPATH, "//标签名[contains(text(),'text值')]")
    - css
        - class定位
        	find_element(By.CSS_SELECTOR, ".class的值")
        - id定位
        	find_element(By.CSS_SELECTOR, "#id的值")
        - 标签名定位
        	find_element(By.CSS_SELECTOR, "标签名")
        - 标签层级关系定位
        	find_element(By.CSS_SELECTOR, "上一级标签名 > 上一级标签名 > ... > 标签名")
        - 属性定位
        	find_element(By.CSS_SELECTOR, "[属性名='属性值']")
        - 组合定位
        	find_element(By.CSS_SELECTOR, "上一级标签名.标签名内的clas属性值 > 上一级标签名 > 上一级标签名#标签名内的id属性值 > 标签名.标签名内的clas属性值")
        - 更多定位
        	find_element(By.CSS_SELECTOR, "[属性*=包含的属性值")
        	find_element(By.CSS_SELECTOR, "[属性^=属性值开头的部分值]")
        	find_element(By.CSS_SELECTOR, "[属性$=属性值结尾的部分值]")
        	find_element(By.CSS_SELECTOR, "上一级标签名 > 标签名:nth-child(标签序列)")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    浏览器控制

    - 浏览器控制
        set_window_size('宽', '高') 设置浏览器窗口的大小
        set_maximize_window()  设置浏览器窗口全屏展示
        forward()   前进到新的网页
        back()  后退(返回)到前一个网页
        refresh()   刷新浏览器
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    常用方法

    clear() 清除文本
    send_keys('输入的内容value')    模拟按键输入
    click() 单击元素
    submit()    提交表单
    size    返回元素尺寸
    text    获取元素的文本
    title   获取当前页面的标题
    current_url 获取当前页面的URL
    get_attribute('属性的name') 获取属性值
    is_displayed()  判断该元素是否可见
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    鼠标操作

    from selenium.webdriver import ActionChains
    ActionChains(driver).方法(定位).perform()
    
    • 1
    • 2
    - ActionChains方法列表
        click(on_element=None) 单击鼠标左键
        click_and_hold(on_element=None)	点击鼠标左键,不松开
        context_click(on_element=None) 点击鼠标右键
        double_click(on_element=None) 双击鼠标左键
        drag_and_drop(source, target) 拖拽到某个元素然后松开
        drag_and_drop_by_offset(source, xoffset, yoffset) 拖拽到某个坐标然后松开
        key_down(value, element=None) 按下某个键盘上的键
        key_up(value, element=None) 松开某个键
        move_by_offset(xoffset, yoffset) 鼠标从当前位置移动到某个坐标
        move_to_element(to_element) 鼠标移动到某个元素
        move_to_element_with_offset(to_element, xoffset, yoffset) 移动到距某个元素(左上角坐标)多少距离的位置
        perform()	执行链中的所有动作,即ActionChains类中存储的所有行为
    
        release(on_element=None) 在某个元素位置松开鼠标左键
    
        send_keys(*keys_to_send) 发送某个键到当前焦点的元素
    
        send_keys_to_element(element, *keys_to_send) 发送某个键到指定元素
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    键盘操作

    from selenium.webdriver.common.Keys import Keys
    
    • 1
    send_keys(Keys.BACK_SPACE)  删除键
    send_keys(Keys.SPACE)   空格键
    send_keys(Keys.TAB) 制表键(Tab)
    send_keys(Keys.ESCAPE)  回退键
    send_keys(Keys.ENTER)   回车键
    send_keys(Keys.CONTROL, 'a')    全选
    send_keys(Keys.CONTROL, 'c')    复制
    send_keys(Keys.CONTROL, 'x')    剪切
    send_keys(Keys.CONTROL, 'v')    粘贴
    send_keys(Keys.F1)  键盘F1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    元素等待

    显式等待:等待某个条件成立则继续执行,否则在达到最大时长时抛出异常,这个等待过程不会执行其它接下来的操作

    # WebDriverWait()一般与until()或until_not()方法配合使用
    WebDriverWait(driver, timeout='最长超长时间,秒单位', poll_frequency='检测的间隔时长,默认为0.5s', ignored_exceptions='超时后的异常').until(
        等待达到的预期条件判断方法
    )
    
    • 1
    • 2
    • 3
    • 4
    一般会使用expectd_conditions类提供的预期条件判断方法:
    	title_is('title包含的预期value')    判断当前页的标题是否等于预期
    	title_contains(title包含的的部分预期value)  判断当前页面的标题是否包含预期字符串
    	presence_of_element_located('预期的元素定位') 判断元素是否被加在DOM树里,并不代表该元素一定可见
    	visibility_of_element_located('预期的元素定位')   判断元素是否可见,可见不包括宽和高为0
    	visibility_of('元素的预期value值')  判断元素是否可见,可见不包括宽和高为0
    	presence_of_all_elements_located('预期的元素定位')    判断是否至少有一个元素存在于DOM树中
    	text_to_be_present_in_element('text属性值包含的预期字符串')   判断某个元素的text是否包含预期的字符串
    	text_to_be_precent_in_element_value('value属性值包含的预期字符串')   判断某个元素的value属性值是否包含预期的字符串
    	frame_to_be_available_and_switch_to_it('预期的表单frame')    判断该表单是否可以切换进去,如果可以,则返回True并切换进去
    	invisibility_of_element_located('元素的预期定位')  判断某个元素是否不在DOM树或不可见
    	element_to_be_clickable('预期的元素定位') 判断某个元素是否可见并且可以点击
    	staleness_of('预期的元素定位')  等到一个元素从DOM树中移除
    	element_to_be_selected('预期的元素定位')    判断某个元素是否被选中,一般用在下拉列表中
    	element_selection_state_to_be('预期定位后的元素') 判断某个元素的选中状态是否符合预期
    	element_located_selection_state_to_be('预期的元素定位')   判断某个元素的选中状态是否符合预期
    	alert_is_present()  判断页面是否存在alert
    is_displayed()  判断元素是否存在
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    隐式等待:在达到最大超时时长前,对整个页面采用轮询的方式不断判断元素是否存在,等待过程中不影响接下来的操作执行,即在等待时会执行后面的操作。如果在在达到最大超时时长前定位到了元素,则在达到最大超时时长后继续执行,如果在达到最大超时时长时还未定位到元素,则抛出异常

    driver.implicitly_wait('等待最大时长')
    
    • 1

    强制等待:即线程等待,通过线程休眠的方式完成等待,一般情况下不太使用强制等待,主要应用的场景在于不同系统交互的地方

    Thread.sleep('等待时长,ms为单位')
    
    • 1

    主体切换

    多表单切换

    driver.switch_to.frame('frame定位')
    
    • 1

    多窗口切换

    driver.current_window_handle 获得当前窗口句柄
    window_handles	获得所有窗口的句柄到当前对话
    switch_to.window('需要切换到的窗口的句柄') 切换到相应的窗口
    
    • 1
    • 2
    • 3

    警告框切换

    # 切换到警告框
    alert = switch_to.alert()	
    # 获取alert、confirm、prompt中的文字信息
    alert.text
    # 接受现有警告框
    alert.accept()
    # 解散现有警告框
    alert.dismiss()
    # 在警告框中输入文本(可输入的话)
    alert.send_keys('value')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    下拉框处理

    Select类用于定位