用例标题 测试包、文件、类、方法名称 用例的唯一标识
前提条件 setup、setup_class(Pytest);
BeforeEach、BeforeAll(JUnit) 测试用例前的准备动作,比如读取数据或者driver的初始化
用例步骤 测试方法内的代码逻辑 测试用例具体的步骤行为
预期结果 assert 实际结果 = 预期结果 断言,印证用例是否执行成功
实际结果 assert 实际结果 = 预期结果 断言,印证用例是否执行成功
后置动作 teardown、teardown_class(Pytest);
@AfterEach 、 @AfterAll (JUnit) 脏数据清理、关闭driver进程

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
class TestDemo01():
    def setup_method(self, method):
        # 实例化chromedriver
        self.driver = webdriver.Chrome()
        # 添加全局隐式等待
        self.driver.implicitly_wait(5)
    def teardown_method(self, method):
        # 关闭driver
        self.driver.quit()
    def test_demo01(self):
        # 访问网站
        self.driver.get("https://www.baidu.com/")
        # 设置窗口
        self.driver.set_window_size(1330, 718)
        # 点击输入框
        self.driver.find_element(By.ID, "kw").click()
        # 输入框输入信息
        self.driver.find_element(By.ID, "kw").send_keys("霍格沃兹测试开发")
        # 点击搜索按钮
        self.driver.find_element(By.ID, "su").click()
        # 等待界面加载
        time.sleep(5)
        # 元素定位后获取文本信息
        res = self.driver.find_element(By.XPATH, "//*[@id='1']/h3/a").get_attribute("text")
        # 打印文本信息
        print(res)
        # 添加断言
        assert "霍格沃兹测试开发" in res
        # 查看界面展示
        time.sleep(5)
web 浏览器控制
浏览器控制
  • 模拟功能测试中对浏览器的操作
    ||操作|使用场景|
    | — | — | — |
    |get|打开浏览器|web自动化测试第一步|
    |refresh|浏览器刷新|模拟浏览器刷新|
    |back|浏览器退回|模拟退回步骤|
    |maximize_window|最大化浏览器|模拟浏览器最大化|
    |minimize_window|最小化浏览器|模拟浏览器最小化|
  • get方法打开浏览器
  • from selenium import webdriver
    import time
    def window_start():
        # 实例化chromedriver
        driver = webdriver.Chrome()
        # 打开网站
        driver.get('http://www.ceshiren.com')
        # 等待一秒
        time.sleep(1)
    if __name__ == '__main__':
        window_start()
    
  • refresh方法刷新页面
  • from selenium import webdriver
    import time
    def window_refresh():
        # 实例化chromedriver
        driver = webdriver.Chrome()
        # 打开网站
        driver.get('http://www.ceshiren.com')
        # 等待一秒
        time.sleep(1)
        # 刷新网页
        driver.refresh()
        # 等待一秒
        time.sleep(1)
    if __name__ == '__main__':
        window_refresh()
    
    from selenium import webdriver
    import time
    from selenium.webdriver.common.by import By
    def window_back():
        # 实例化chromedriver
        driver = webdriver.Chrome()
        # 打开网站
        driver.get('http://www.ceshiren.com')
        # 等待一秒
        time.sleep(1)
        driver.find_element(By.XPATH,"//*[@id='ember35']").click()
        # 等待一秒
        time.sleep(1)
        # 返回上一个界面
        driver.back()
        # 等待一秒
        time.sleep(1)
    if __name__ == '__main__':
        window_back()
    
  • maximize_window方法使窗口最大化
  • def max_window():
        # 实例化chromedriver
        driver = webdriver.Chrome()
        # 打开网站
        driver.get('http://www.ceshiren.com')
        # 等待一秒
        time.sleep(1)
        # 屏幕最大化
        driver.maximize_window()
        # 等待一秒
        time.sleep(1)
    if __name__ == '__main__':
        max_window()
    
  • minimize_window方法使窗口最小化
  • from selenium import webdriver
    import time
    def min_window():
        # 实例化chromedriver
        driver = webdriver.Chrome()
        # 打开网站
        driver.get('http://www.ceshiren.com')
        # 等待一秒
        time.sleep(1)
        # 屏幕最小化
        driver.minimize_window()
        # 等待一秒
        time.sleep(1)
    if __name__ == '__main__':
        min_window()
    常见控件定位方法
    HTML铺垫
    
    <!DOCTYPE html>
    <meta charset="utf-8">
    <title>测试人论坛</title>
    </head>
    <a href="https://ceshiren.com/" class="link">链接</a>
    </body>
    </html>
    
  • 标签:<a>
  • 属性:href
  • 类属性: class
  • Selenium定位方式

    Selenium提供了八种定位方式:Locator strategies | Selenium

    driver.get("https://vip.ceshiren.com/") # 不加等待,可能会因为网速等原因产生报错 driver.find_element(By.XPATH, "//*[text()='个人中心']") if __name__ == '__main__': wait_sleep()
  • 解决方案:在报错的元素操作之前添加等待
  • 原理:强制等待,线程休眠一定时间
  • 演练环境:https://vip.ceshiren.com/
  • time.sleep(3)
  • 问题:难以确定元素加载的具体等待时间。
  • 解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。
  • 演练环境:https://vip.ceshiren.com/
  • 原理:设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常
  • #设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常
    driver.implicitly_wait(3)

    隐式等待无法解决的问题
    元素可以找到,使用点击等操作,出现报错
    页面元素加载是异步加载过程,通常html会先加载完成,js、css其后
    元素存在与否是由HTML决定,元素的交互是由css或者js决定
    隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互
    解决方案:使用显式等待
    显式等待基本使用(初级)
    
  • 示例: WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)
  • 原理:在最长等待时间内,轮询,是否满足结束条件
  • 演练环境: 霍格沃兹测试开发
  • 注意:在初级时期,先关注使用
  • def wait_until():
        driver = webdriver.Chrome()
        driver.get("https://vip.ceshiren.com/#/ui_study")
        WebDriverWait(driver, 10).until(
            expected_conditions.element_to_be_clickable(
                (By.CSS_SELECTOR, '#success_btn')))
        driver.find_element(By.CSS_SELECTOR, "#success_btn").click()
    driver.find_element(By.ID,"kw").click()
    # 输入"霍格沃兹测试开发"
    driver.find_element(By.ID,"kw").send_keys("霍格沃兹测试开发")
    # 清空搜索框中信息
    driver.find_element(By.ID,"kw").clear()
    获取元素属性信息
    
  • 定位到元素后,获取元素的文本信息,属性信息等
  • 根据这些信息进行断言或者调试
  • 演练地址: 霍格沃兹测试开发 获取元素属性信息的方法
  • 获取元素文本
  • 获取元素的属性(html的属性值)
  • 获取元素文本

    driver.find_element(By.ID, “id”).text

    获取这个元素的name属性的值

    driver.find_element(By.ID, “id”).get_attribute(“name”)

    自动化测试定位策略
  • 不知道应该使用哪种定位方式?
  • 元素定位不到无法解决?
  • 选择定位器通用原则

    与研发约定的属性优先(class属性: [name='locate'])

    身份属性 id,name(web 定位)

    复杂场景使用组合定位:

  • xpath,css
  • 属性动态变化(id,text)
  • 重复元素属性(id,text,class)
  • 父子定位(子定位父)
  • Web 弹框定位
  • web 页面 alert 弹框
  • web 需要使用 driver.switchTo().alert() 处理
  • $("#ember63 > td.main-link.clearfix.topic-list-data > span > span > a") # 相对定位 $("#ember63 [title='新话题']")
    css 定位的调试方法
  • 进入浏览器的console
  • $("css表达式")
  • 或者$("css表达式") //input[last()] # 选取属性name的值为passward并且属性pwd的值为123456的input标签 //input[@name='passward' and @pwd='123456'] # 选取属性name的值为passward或属性pwd的值为123456的input标签 //input[@name='passward' or @pwd='123456'] # 选取所有文本信息为'霍格沃兹测试开发'的元素 //*[text()='霍格沃兹测试开发'] # 选取所有文本信息包'霍格沃兹'的元素 //*[contains(text(),'霍格沃兹')] 显式等待高级使用 显示等待原理
  • 在代码中定义等待一定条件发生后再进一步执行代码
  • 在最长等待时间内循环执行结束条件的函数
  • WebDriverWait(driver 实例, 最长等待时间, 轮询时间).until(结束条件函数)
  • 显示等待-expected_conditions
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.support.wait import WebDriverWait
    def wait_until():
        driver = webdriver.Chrome()
        driver.get("https://vip.ceshiren.com/#/ui_study")
        WebDriverWait(driver, 10).until(
            expected_conditions.element_to_be_clickable(
                (By.CSS_SELECTOR, '#success_btn')))
        driver.find_element(By.CSS_SELECTOR, "#success_btn").click()
    常见 expected_conditions
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.remote.webdriver import WebDriver
    from selenium.webdriver.support.wait import WebDriverWait
    class TestWebdriverWait:
        driver = webdriver.Chrome()
        driver.maximize_window()
        driver.implicitly_wait(5)
        driver.get("https://vip.ceshiren.com/#/ui_study")
        def teardown(self):
            self.driver.quit()
        def test_webdriver_wait(self):
            # 解决的问题:有的按钮点击一次没有反应,可能要点击多次,比如企业微信的添加成员
            # 解决的方案:一直点击按钮,直到下个页面出现,封装成显式等待的一个条件
            def muliti_click(button_element,until_ele):
                # 函数封装
                def inner(driver):
                    # 封装点击方法
                    driver.find_element(By.XPATH,button_element).click()
                    return driver.find_element(By.XPATH,until_ele)
                return inner
            time.sleep(5)
            # 在限制时间内会一直点击按钮,直到展示弹框
            WebDriverWait(self.driver,10).until(muliti_click("//*[text()='点击两次响应']","//*[text()='该弹框点击两次后才会弹出']"))
            time.sleep(5)
    高级控件交互方法
            # 演练环境
            self.driver.get("https://ceshiren.com/")
            self.driver.find_element(By.ID, "search-button").click()
            ele = self.driver.find_element(By.ID, "search-term")
            ActionChains(self.driver).key_down(Keys.SHIFT, ele).\
            send_keys("selenium").perform()
    键盘事件-输入后回车
    
  • 直接输入回车: 元素.send_keys(Keys.ENTER)
  • 使用ActionChains: key_down(Keys.ENTER)
  • class TestKeyBoardDemo:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_enter(self):
            # 演练环境
            self.driver.get("https://www.sogou.com/")
            ele = self.driver.find_element(By.ID, "query")
            ele.send_keys("selenium")
            # 第一种方式
            ele.send_keys(Keys.ENTER)
            # 第二种方式
            # ActionChains(self.driver).\
            #     key_down(Keys.ENTER).\
            #     perform()
            time.sleep(3)
    键盘事件-复制粘贴
    
  • 多系统兼容
  • mac 的复制按钮为 COMMAND
  • windows 的复制按钮为 CONTROL
  • 左箭头:Keys.ARROW_LEFT
  • 按下COMMAND或者CONTROL: key_down(cmd_ctrl)
  • 按下剪切与粘贴按钮: send_keys("xvvvvv")
    class TestKeyBoardDemo:
        # driver 初始化
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        # 关闭driver进程
        def teardown_class(self):
            self.driver.quit()
        # 复制粘贴逻辑
        def test_copy_and_paste(self):
            # 演练环境
            self.driver.get("https://ceshiren.com/")
            cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL
            self.driver.find_element(By.ID, "search-button").click()
            ele = self.driver.find_element(By.ID, "search-term")
            # 打开搜索,选择搜索框,输入selenium,剪切后复制,几个v就代表复制几次
            ActionChains(self.driver)\
                .key_down(Keys.SHIFT, ele)\
                .send_keys("Selenium!")\
                .send_keys(Keys.ARROW_LEFT)\
                .key_down(cmd_ctrl)\
                .send_keys("xvvvvv")\
                .key_up(cmd_ctrl)\
                .perform()
            time.sleep(5)
    
  • 指定位置(悬浮)
  • 鼠标事件-双击 double_click(元素对象): 双击元素
  • class TestMouseDemo:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_double_click(self):
            # 演练环境
            self.driver.get("https://vip.ceshiren.com/#/ui_study")
            ele = self.driver.find_element(By.ID, "primary_btn")
            ActionChains(self.driver).double_click(ele).perform()
            time.sleep(2)
    鼠标事件-拖动元素
    drag_and_drop(起始元素对象, 结束元素对象): 拖动并放开元素
    
    class TestMouseDemo:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_drag_and_drop(self):
            # 演练环境
            self.driver.get("https://vip.ceshiren.com/#/ui_study/action_chains")
            item_left = self.driver.find_element(By.CSS_SELECTOR,'#item1')
            item_right = self.driver.find_element(By.CSS_SELECTOR,'#item3')
            ActionChains(self.driver).drag_and_drop(item_left, item_right).perform()
            time.sleep(5)
    鼠标事件-悬浮
    move_to_element(元素对象): 移动到某个元素
    
    class TestMouseDemo:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_hover(self):
            # 演练环境
            self.driver.get("https://vip.ceshiren.com/#/ui_study/action_chains2")
            time.sleep(2)
            title = self.driver.find_element(By.CSS_SELECTOR, '.title')
            ActionChains(self.driver).move_to_element(title).perform()
            options = self.driver.find_element(By.CSS_SELECTOR,'.options>div:nth-child(1)')
            ActionChains(self.driver).click(options).perform()
            time.sleep(5)
    滚轮/滚动操作
    
  • 滚动到元素
  • 根据坐标滚动
  • 注意: selenium 版本需要在 4.2 之后
  • 滚轮/滚动操作-滚动到元素 scroll_to_element(WebElement对象):滚动到某个元素
    class TestScrollDemo:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_scoll_to_element(self):
            # 演练环境  
            self.driver.get("https://ceshiren.com/")
            # 4.2 之后才提供这个方法
            ele = self.driver.find_element\
            (By.XPATH, "//*[text()='怎么写高可用集群部署的测试方案?']")
            ActionChains(self.driver).scroll_to_element(ele).perform()
            time.sleep(5)
    滚轮/滚动操作-根据坐标滚动
    
  • scroll_by_amount(横坐标, 纵坐标)
  • class TestScrollDemo:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_scroll_to_amount(self):
            # 演练环境
            self.driver.get("https://ceshiren.com/")
            # 4.2 之后才提供这个方法
            ActionChains(self.driver).scroll_by_amount(0, 10000).perform()
            time.sleep(5)
    

    #多窗⼜处理与⽹页frame

    自动化关键数据记录 什么是关键数据
  • 代码的执行日志
  • 代码执行的截图
  • page source(页面源代码)
  • 记录关键数据的作用 # 日志打印格式 formatter = logging.Formatter\ ('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 添加格式配置 ch.setFormatter(formatter) # 添加日志配置 logger.addHandler(ch)
    # 日志与脚本结合
    class TestDataRecord:
        def setup_class(self):
            self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(3)
        def teardown_class(self):
            self.driver.quit()
        def test_log_data_record(self):
            # 实例化self.driver
            search_content = "霍格沃兹测试开发"
            # 打开百度首页
            self.driver.get("https://www.sogou.com/")
            logger.debug("打开搜狗首页")
            # 输入霍格沃兹测试学院
            self.driver.find_element(By.CSS_SELECTOR, "#query").\
            send_keys(search_content)
            logger.debug(f"搜索的内容为{search_content}")
            # 点击搜索
            self.driver.find_element(By.CSS_SELECTOR, "#stb").click()
            # 搜索结果
            search_res = self.driver.find_element(By.CSS_SELECTOR, "em")
            logger.info(f"搜索结果为{search_res.text}")
            assert search_res.text == search_content
    步骤截图记录
    
  • save_screenshot(截图路径+名称)
  • 记录关键页面
  • 重要的业务场景页面
  • 容易出错的页面
  • # 调用save方法截图并保存保存在当前路径下的images文件夹下
    driver.save_screenshot('./images/search1.png')
    page_source记录
    
  • 使用page_source属性获取页面源码
  • 在调试过程中,如果有找不到元素的错误可以保存当时的page_source调试代码
  • # 在报错行前面添加保存page_source的操作
    with open("record.html", "w", encoding="u8") as f:
        f.write(self.driver.page_source)
    Web自动化测试之复用浏览器
    复用浏览器简介
    image
    
    
    
    
        
    1044×358 28.3 KB
    为什么要学习复用浏览器
    
  • 自动化测试过程中,存在人为介入场景
  • 提高调试UI自动化测试脚本效率
  • 复用已有浏览器-配置步骤
  • 需要退出当前所有的谷歌浏览器(特别注意)
  • 输入启动命令,通过命令启动谷歌浏览器
  • 找到 chrome 的启动路径(下一页 ppt)
  • 配置环境变量(下一页 ppt)
  • 验证是否启动成功
  • windows:chrome –remote-debugging-port=9222
  • mac:Google Chrome –remote-debugging-port=9222
  • windows 环境变量配置:1. 获取启动路径 windows 环境变量配置:2. 配置环境变量 windows 环境变量配置:3. 重启命令行 windows关闭谷歌浏览器进程 复用已有浏览器-代码设置(Python)
    from selenium.webdriver.chrome.options import Options
    option = Options()
    option.debugger_address = "localhost:9222"
    self._driver = webdriver.Chrome(options=option)
    self._driver.get("https://work.weixin.qq.com/wework_admin/frame")
    复用浏览器实战演示1
    
  • 问题1:企业微信登录无法通过输入用户名密码的方式解决登录问题,后面所有的脚本都无法执行。
  • 解决方案: 通过remote复用浏览器人工登录企业微信。后面的脚本自动执行
  • 复用浏览器实战演示2
  • 问题2:编写自动化测试脚本过程中,用例的某一步骤出现问题。调试时需要将此步骤前面所有的步骤执行完成之后再复现调试。
  • 解决方案:使用复用浏览器的方式跳过前面的自动化执行步骤,轻松复现出问题的场景,只对问题行代码进行调试。
  • Web自动化测试之Cookie登录 cookie 是什么
  • Cookie 是一些认证数据信息,存储在电脑的浏览器上
  • 当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息
  • 为什么要使用Cookie自动化登录
  • 复用浏览器仍然在每次用例开始都需要人为介入
  • 若用例需要经常执行,复用浏览器则不是一个好的选择
  • 大部分cookie的时效性都很长,扫一次可以使用多次
  • 企业微信cookie有互踢机制。在获取cookie成功之后。不要再进行扫码操作!!!!
  • 获取cookie的时候,即执行代码获取cookie时,一定要确保已经登录
  • 植入cookie之后需要进入登录页面,刷新验证是否自动登录成功。
  • 代码(Python)
  • 获取 cookie driver.get_cookies()
  • 添加 cookie driver.add_cookie(cookie)
    class TestCookieLogin:
        def setup_class(self):
            self.drvier = webdriver.Chrome()
        def test_get_cookies(self):
            # 1. 访问企业微信主页/登录页面
            self.drvier.get("https://work.weixin.qq.com/wework_admin/frame#contacts")
            # 2. 等待20s,人工扫码操作
            time.sleep(20)
            # 3. 等成功登陆之后,再去获取cookie信息
            cookie = self.drvier.get_cookies()
            # 4. 将cookie存入一个可持久存储的地方,文件
            # 打开文件的时候添加写入权限
            with open("cookie.yaml", "w") as f:
                # 第一个参数是要写入的数据
                yaml.safe_dump(cookie, f)
        def test_add_cookie(self):
            # 1. 访问企业微信主页面
            self.drvier.get("https://work.weixin.qq.com/wework_admin/frame#contacts")
            # 2. 定义cookie,cookie信息从已经写入的cookie文件中获取
            cookie = yaml.safe_load(open("cookie.yaml"))
            # 3. 植入cookie
            for c in cookie:
                self.drvier.add_cookie(c)
            time.sleep(3)
            # 4.再次访问企业微信页面,发现无需扫码自动登录,而且可以多次使用
            self.drvier.get("https://work.weixin.qq.com/wework_admin/frame#contacts")
    yaml相关依赖
    
    <properties>
      <!--对应解析-->
      <jackson.version>2.13.1</jackson.version>
    </properties>
    <dependencies>
      <!--        yaml文件解析-->
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>${jackson.version}</version>
      </dependency>
      <dependency>
          <groupId>com.fasterxml.jackson.dataformat</groupId>
          <artifactId>jackson-dataformat-yaml</artifactId>
          <version>${jackson.version}</version>
      </dependency>
    </dependencies>
    selenium 多浏览器处理
    多浏览器测试概述
    
  • 是跨不同浏览器组合验证网站或 web 应用程序功能的过程
  • 是兼容性测试的一个分支,用于保持功能和质量的一致性
  • 适用于面向客户的网站和组织内部使用的站点
  • 多浏览器的实现方案 pytest hook 函数 pytest_addoption 添加命令行参数组/命令行参数
  • pytest_configure 解析命令行选项,每个插件都会用到这个hook函数 pytest_addoption 与 pytest_configure
  • pytest_addoption:
  • parser.getgroup 创建/获取组名
  • addoption 添加一个命令行选项
  • pytest_configure:
  • 通过config 对象的getoption()方法获取命令行参数
  • 将命令行获取到的内容赋值给变量
  • pytest_addoption 与 pytest_configure代码示例
    def pytest_addoption(parser):
        # group 将下面所有的 option都展示在这个group下。
        mygroup = parser.getgroup("hogwarts")  
        # 注册一个命令行选项
        mygroup.addoption("--browser",
         # 参数的默认值  
        default='Chrome',
        # 存储的变量 
        dest='browser',  
        # 参数的描述信息
        help='set your browser, \
        such as:Chrome, Firefox, Headless...'  
    
    def pytest_configure(config):
        browser = config.getoption("--browser", default='Chrome')
        tmp = {"browser": browser}
        global_env.append(tmp)
    命令行参数处理
    
  • 通过 pytest_addoption hook 函数,配置命令行参数
  • 通过 pytest_configure 函数,接收命令行参数信息
  • 将参数保存到变量中
  • global_env = {}
    def pytest_addoption(parser):
        # group 将下面所有的 option都展示在这个group下。
        mygroup = parser.getgroup("hogwarts")
        # 注册一个命令行选项
        mygroup.addoption("--browser",
         # 参数的默认值
        default='Chrome',
        # 存储的变量
        dest='browser',
        # 参数的描述信息
        help='set your browser, \
        such as:Chrome, Firefox, Headless...'
    def pytest_configure(config):
        browser = config.getoption("browser", default='Chrome')
        browser_conf = {"browser": browser}
        global_env.update(browser_conf)
    
  • 通过命令行执行测试用例: pytest 测试用例文件.py --browser="浏览器名称"
  • 后续结合 jenkins 实现切换浏览器+持续集成
  • # test_args.py
    from selenium import webdriver
    from conftest import global_env
    class TestArgs():
        def setup(self):
            self.browser = global_env.get("browser")
            print(self.browser)
            if self.browser == 'Firefox':
                self.driver = webdriver.Firefox(executable_path="/path/to/geckodriver")
            elif self.browser == 'Remote':
                executor_url = "https://selenium-node.hogwarts.ceshiren.com/wd/hub"
                capabilities = {"browserName": "chrome", "browserVersion": "99.0"}
                self.driver = webdriver.Remote(command_executor=executor_url, desired_capabilities=capabilities)
            else:
                self.driver = webdriver.Chrome()
            self.driver.implicitly_wait(5)
            self.driver.maximize_window()
        def test_option(self):
            print("用例")
    执行JavaScript脚本
    自动化测试中使用JavaScript脚本
    

    使用场景:部分场景使用selenium原生方法无法解决

  • 修改时间控件
  • 滚动到某个元素
  • JavaScript 使用思路
  • 页面调试 js 脚本
  • Selenium执行js
  • JavaScript调试方法
  • 进入 console 调试
  • js 脚本如果有返回值则会在浏览器返回
  • JS 脚本-元素操作
  • 通过 css 查找元素
  • 点击元素(对应click)
  • input标签对应的值(对应send_keys)
  • 元素的类属性
  • 元素的文本属性
  • // 百度首页:https://www.baidu.com/
    // 修改属性值
    document.querySelector("#kw").value = "霍格沃兹测试学院"
    // 点击操作
    document.querySelector("#su").click()
    // 淘宝首页: https://www.taobao.com/ 
    // 修改元素的类属性
    document.querySelector("#J_SiteNavMytaobao").className\
    ="site-nav-menu site-nav-mytaobao site-nav-multi-menu J_MultiMenu site-nav-menu-hover"
    // 测试人首页:https://ceshiren.com/
    // 获取元素内的文本信息
    document.querySelector("#ember63").innerText
    JS脚本滚动操作
    
  • 页面滚动到底部
  • 指定到滚动的位置
  • document.documentElement.scrollTop=10000
    document.querySelector(‘css表达式’).scrollIntoView();

    Selenium执行js
  • Selenium执行js
  • 调用执行js方法
  • 在 js 语句中添加 return:代码可以获取js的执行结果
  • 结合 find_element 方法
  • driver = webdriver.Chrome() driver.implicitly_wait(3) # 打开网址 driver.get("https://www.taobao.com/") # 修改下拉框属性 sleep(1) driver.execute_script('document.querySelector("#J_SiteNavMytaobao").' 'className="site-nav-menu site-nav-mytaobao ' 'site-nav-multi-menu J_MultiMenu ' 'site-nav-menu-hover"') driver.find_element(By.XPATH, "//*[text()='已买到的宝贝']").click() sleep(5) driver.quit()
    js处理-案例2-时间控件
  • 案例二:通过属性修改时间控件的值
  • 打开12306网站
  • 修改时间控件值
  • 打印出发日期
  • driver = webdriver.Chrome() driver.implicitly_wait(3) driver.get("https://www.12306.cn/index/") sleep(1) # 修改出发日期 driver.execute_script('document.querySelector("#train_date").value="2022-12-22"') sleep(1) # 打印出发日期, 返回值的使用 train_data = driver.execute_script('return document.querySelector("#train_date").value') print(train_data) sleep(3)
    selenium option 常用操作

    headless无头浏览器使用

    Options概述
  • 是一个配置浏览器启动的选项类,用于自定义和配置Driver会话
  • 常见使用场景:
  • 设置无头模式:不会显示调用浏览器,避免人为干扰的问题。
  • 设置调试模式:调试自动化测试代码(浏览器复用)
  • from selenium import webdriver
    from selenium.webdriver.common.by import By
    def test_chrome_pref():
        options = webdriver.ChromeOptions()
        # 无头模式
        options.add_argument('--headless')
        # 窗体最大化
        options.add_argument('start-maximized')
        # 指定浏览器分辨率
        options.add_argument('window-size=1920x3000')
        driver = webdriver.Chrome(chrome_options=options)
        # 打开测试人页面
        driver.get("https://ceshiren.com/")
        # 点击登录
        login_button_text = driver.find_element(By.CSS_SELECTOR, ".login-button").text
        print(login_button_text)  #打印:登录
        driver.quit()
    capability 配置参数解析与分布式运行
    capability概述
    
  • Capabilities是WebDriver支持的标准命令之外的扩展命令(配置信息)
  • 配置web驱动的属性,如浏览器名称、浏览器平台等。
  • 结合Selenium Grid完成分布式、兼容性等测试
  • 官网地址: https://www.selenium.dev/zh-cn/documentation/webdriver/capabilities/shared/ capability 使用示例-Python
    import time
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    def test_ceshiren():
        # 切换成 windows 就会报错
        capabilities = {"browserName":"chrome","platformName":"mac"}
        # 通过 desired_capabilities 添加配置信息
        driver = webdriver.Chrome(desired_capabilities=capabilities)
        driver.implicitly_wait(5)
        driver.get("https://ceshiren.com/")
        text = driver.find_element(By.CSS_SELECTOR, ".login-button").text
        print(text) #打印:登录
        time.sleep(30)
        driver.quit()
    Selenium Grid
    
  • elenium Grid 允许我们在多台机器上并行运行测试,并集中管理不同的浏览器版本和浏览器配置(而不是在每个单独的测试中)。
  • 官网地址:Grid | Selenium
  • 学院搭建的演示环境:Selenium Grid
  • (搭建教程会在 docker 章节讲解)
  • 保证本地可以正常调通
  • 实例化Remote()类并添加相应的配置
  • 代码示例-Python
    def test_ceshiren2():
        hogwarts_grid_url = "https://selenium-node.hogwarts.ceshiren.com/wd/hub"
        capabilities = {"browserName":"chrome","browserVersion":"101.0"}
        # 配置信息
        # 实例化Remote,获取可以远程控制的driver实例对象
        # 通过 command_executor 配置selenium hub地址
        # 通过 desired_capabilities 添加配置信息
        driver = webdriver.Remote(
            command_executor=hogwarts_grid_url,
            desired_capabilities=capabilities)
        driver.implicitly_wait(5)
        driver.get("https://ceshiren.com/")
        text = driver.find_element(By.CSS_SELECTOR, ".login-button").text
        print(text)
        time.sleep(3)
        driver.quit()
    image1578×816 113 KB
    Playwright 自动化测试框架
    Playwright 简介
    
  • Web 自动化测试框架。
  • 跨平台多语言支持。
  • 支持 Chromium、Firefox、WebKit 等主流浏览器自动化操作。
  • Playwright 的优点
  • 支持所有流行的浏览器。
  • 速度更快,更可靠的执行。
  • 更强大的自动化测试配置。
  • 强大的工具库:Codegen、Playwright inspector、Trace Viewer。
  • Playwright 与 selenium 对比
  • Codegen:通过记录你的操作来生成测试。 将它们保存为任何语言。
  • Playwright inspector: 检查页面、生成选择器、逐步执行测试、查看点击点、探索执行日志。
  • Trace Viewer:捕获所有信息以调查测试失败。 Playwright 跟踪包含测试执行截屏、实时 DOM 快照、动作资源管理器、测试源等等。
  • Playwright 环境安装
  • 安装 playwright 插件
  • pip install pytest-playwright
  • 安装所需的浏览器
  • playwright install
  • Playwright 使用实例
    from playwright.sync_api import sync_playwright, expect
    def test_playwright():
        # 实例化playwright
        playwright = sync_playwright().start()
        # 打开chrome浏览器,headless默认是True,无头模式,这里设置为False方便查看效果
        browser = playwright.chromium.launch(headless=False)
        # 打开一个窗口页面
        page = browser.new_page()
        # 在当前窗口页面打开测试人网站
        page.goto("https://ceshiren.com/")
        # 定位搜索按钮并点击
        page.locator("#search-button").click()
        # 定位搜索框并输入web自动化
        page.locator("#search-term").fill("web自动化")
        # 使用keyboard.down模拟键盘的enter事件
        page.keyboard.down("Enter")
        # 断言搜索结果
        result = page.locator(".list>li:nth-child(1) .topic-title>span")
        expect(result).to_contain_text("自动化测试")
        page.screenshot(path='screenshot.png')
        # 用例完成后先关闭浏览器
        browser.close()
        # 然后关闭playwright服务
        playwright.stop()
    Trace Viewer 简介
    Trace Viewer 使用
    
    # trace 在代码中的配置
    browser = chromium.launch()
    # 实例化一个新的context
    context = browser.new_context()
    # 设置trace的参数信息
    context.tracing.start(screenshots=True, snapshots=True, sources=True)
    # 使用context生成的page实例进行对应的操作
    page = context.new_page()
    # 结束追踪
    context.tracing.stop(path = "trace.zip")
    打开trace
    

    playwright show-trace trace.zip

    image1141×722 128 KB image1572×789 89.7 KB image1693×878 97.5 KB
  •