SeleniumBase 基础使用与场景举例-使用笔记(一)

自动化福音(爬虫、办公、测试等) SeleniumBase 使用笔记(一)

SeleniumBase是什么?
用于 Web 自动化、端到端测试和用户入门的完整框架。SeleniumBase 使用 Pytest 来运行 Python 脚本,同时使用 WebDriver 来控制 Web 浏览器。

SeleniumBase 基础使用与场景举例

使用 SeleniumBase 很简单,直接安装,然后继承 BaseCase 类即可


目录

  1. 安装
  2. 驱动安装
  3. 创建测试目录或文件
  4. 常用API介绍
  5. 跳过测试
  6. 失败重试
  7. 语法格式
  8. 常用的启动命令介绍
  9. 使用场景举例

安装

推荐直接从 PyPI安装,更多安装,看这里

pip install seleniumbase

驱动

没有安装驱动或驱动版本错误,会自动下载(但是每次执行都会先去下载,故推荐下载驱动)
可以使用下方命令,直接下载驱动,此命令会将驱动下载到\site-packages\seleniumbase\drivers文件夹中,或直接访问这里下载对应版本

sbase get chromedriver  # chrome(自动匹配浏览器版本)
sbase get geckodriver  # gecko(自动匹配浏览器版本)
sbase get edgedriver  # edge(自动匹配浏览器版本)

sbase get chromedriver 107  # chrome(107里版本最新)
sbase get chromedriver 107.0.5304.62  # chrome(107.0.5304.62)
sbase get chromedriver latest  # chrome(最新)

创建测试目录或文件

# 此命令 生成带例子的目录
sbase mkdir ui_tests

image

# 此命令 生成仅配置文件的目录
sbase mkdir ui_tests -b

image

# 此命令 生成一个使用 直接继承格式 的文件
sbase mkfile new_test.py

image


常用方法

一般主要用的为下面这些API,API全部默认使用CSS选择器by="css selector",如需要指定其他方式,如 XPATH,则传参数by="xpath"更多API,见这里

  1. 点击
# 打开页面
self.open(url)

# 单击元素
self.click(selector, by="css selector", timeout=None, delay=0, scroll=True)

# 双击元素
self.double_click(selector, by="css selector", timeout=None)

# 通过元素列表,连续单击
self.click_chain(selectors_list, by="css selector", timeout=None, spacing=0)

  1. 输入
# 先清除文本,再更新文本
# 等同于:self.update_text(selector, text, by="css selector", timeout=None)
self.type(selector, text, by="css selector", timeout=None)

# 不清除文本,直接添加
# 等同于:self.add_text(self, selector, text, by="css selector", timeout=None)
self.send_keys(selector, text, by="css selector", timeout=None)

# 清除文本
self.clear(selector, by="css selector", timeout=None)

# 提交表单
self.submit(selector, by="css selector")

  1. 等待相关
# 等待文本,将返回值
# 等同于:self.find_text(text, selector="html", by="css selector", timeout=None)
self.wait_for_text(text, selector="html", by="css selector", timeout=None)

# 等待元素可见,其元素必须可见,不能被影藏,将返回值
# 等同于:self.find_element(selector, by="css selector", timeout=None)
# 等同于:self.wait_for_element_visible(selector, by="css selector", timeout=None)
self.wait_for_element(selector, by="css selector", timeout=None)

# 等待元素出现,且此元素不要求必须可见,可隐藏
# 等同于:self.get_element(selector, by="css selector", timeout=None)
self.wait_for_element_present(selector, by="css selector", timeout=None)

# 等待元素可点击,但不点击
self.wait_for_element_clickable(selector, by="css selector", timeout=None)

  1. 下拉选项,<select> 按规范选择 HTML 选项
# 按照文本选择选项
self.select_option_by_text(dropdown_selector, option, dropdown_by="css selector", timeout=None)

# 按照索引选择选项
self.select_option_by_index(dropdown_selector, option, dropdown_by="css selector", timeout=None)

# 按照 value 属性值选择选项
self.select_option_by_value(dropdown_selector, option, dropdown_by="css selector", timeout=None)
  1. 文件上传下载
# 文件上传,selector=元素,file_path=需要上传的文件路径
self.choose_file(selector, file_path, by="css selector", timeout=None)

# 文件下载断言,file=文件名
self.assert_downloaded_file(file, timeout=None, browser=False)

# 下载的文件名变化,则可使用下方的正则匹配,regex=下载文件的文件名正则表达式
self.assert_downloaded_file_regex(regex, timeout=None, browser=False)
  1. 断言
# 断言文本,部分匹配
self.assert_text(text, selector="html", by="css selector", timeout=None)

# 断言文本,精确匹配
self.assert_exact_text(text, selector="html", by="css selector", timeout=None)

# 断言元素,如果找不到任何内容,将引发异常
self.assert_element(selector, by="css selector", timeout=None)

# 断言元素存在于HTML中(不需要此元素可见)
self.assert_element_present(selector, by="css selector", timeout=None)

# 断言属性
self.assert_attribute(selector, attribute, value=None, by="css selector", timeout=None)

# 断言属性不存在
self.assert_attribute_not_present(selector, attribute, value=None, by="css selector", timeout=None)

# 断言网页标题
self.assert_title(title)

# 断言网页URL
self.assert_url(url)

# 断言链接文本
self.assert_link_text(link_text, timeout=None)

# 延迟断言,表示多个断言集合在一起,给出一个最终结果,而不是中途失败就退出
# 延迟断言,断言文本,部分匹配
self.deferred_assert_text(text, selector="html", by="css selector", timeout=None, fs=False)

# 延迟断言,断言文本,精确匹配
self.deferred_assert_exact_text(text, selector="html", by="css selector", timeout=None, fs=False)

# 延迟断言,断言元素
self.deferred_assert_element(selector, by="css selector", timeout=None, fs=False)

# 断言元素存在于HTML中(不需要此元素可见)
self.deferred_assert_element_present(selector, by="css selector", timeout=None, fs=False)

# 延迟断言必须断言最后,加上下面的方法
self.process_deferred_asserts(print_only=False)

  1. 切换
# 切换到指定框架,frame=frame名称、ID、索引或选择器
self.switch_to_frame(frame, timeout=None)

# 从框架中退出
self.switch_to_default_content()

# 多个嵌套框架时,切换到所在框架的父框架
self.switch_to_parent_frame()

# 打开新的标签页,默认焦点切换到新标签页
self.open_new_window(switch_to=True)

# 多个标签页时,切换到指定查,window=0表示第1个标签页,1表示第2个标签页,以此类推,此值也可以是 self.driver.window_handles 中的列表项
self.switch_to_window(window, timeout=None)

# 切换到弹窗
self.switch_to_alert(timeout=None)

跳过测试

如果需要跳过某项测试,可直接使用Pytest的相关方法,更多使用可直接查阅Pytest跳过的相关方法,如:

# 无条件跳过
@pytest.mark.skip(reason="跳过这个测试")
def test_demo_site(self):
    ......  # 省略

# 有条件跳过
@pytest.mark.skipif(sys.version_info < (3,6), reason="Python版本小于3.6时,跳过这个测试")
def test_demo_site(self):
    ......  # 省略

失败重试

失败重试,可以单独测试重试,也可以全局重试

from seleniumbase.common.decorators import retry_on_exception

# 此测试失败重试
@retry_on_exception(3)  # 失败重试3次,默认6次
def test_demo_site(self):
    ......  # 省略

# 全局的重试,用启动命令参数
pytest test_suite.py --reruns=3  # 多次重新运行失败的测试(重试3次)

语法格式

一般常用的语法格式为下面这样,更多语法格式,见这里

  1. 直接继承BaseCase
from seleniumbase import BaseCase  # 必须的
BaseCase.main(__name__, __file__)  # 必须的

class MyTestClass(BaseCase):  # 必须的
    def test_demo_site(self):  # 测试用例
        self.open("https://seleniumbase.io/demo_page")  # 调用API
        self.type("#myTextInput", "This is Automated")
        self.click("#myButton")
        self.assert_element("tbody#tbodyId")
        self.assert_text("Automation Practice", "h3")
  1. 继承BaseCase的子类
from seleniumbase import BaseCase  # 必须的
BaseCase.main(__name__, __file__)  # 必须的

class BaseTestCase(BaseCase):  # 必须的
    def setUp(self, **kwargs):  # 非必须的
        super().setUp(**kwargs)
        # 此处添加你的代码

    def tearDown(self):  # 非必须的
        # 此处添加你的代码
        super().tearDown()

    def login(self):  # 自己的登录方法
        pass

class MyTests(BaseTestCase):  # 必须的
    def test_example(self):  # 测试用例
        self.login()  # 自己的登录方法
        self.type("input", "Name")  # 调用API
        self.click("form button")

  1. 使用pytest夹具的方式,SeleniumBase提供固定的夹具名sb,出于兼容性,不能简单的应用于类中
# 直接使用,没有类时(注意:此时IDE无法代码补全)
def test_sb_fixture_with_no_class(sb):
    sb.open("seleniumbase.io/help_docs/install/")
    sb.type('input[aria-label="Search"]', "GUI Commander")
    sb.click('mark:contains("Commander")')
    sb.assert_title_contains("GUI / Commander")


# 有类时,应用于类方法(注意:此时IDE无法代码补全)
class Test_SB_Fixture:
    def test_sb_fixture_inside_class(self, sb):
        sb.open("seleniumbase.io/help_docs/install/")
        sb.type('input[aria-label="Search"]', "GUI Commander")
        sb.click('mark:contains("Commander")')
        sb.assert_title_contains("GUI / Commander")


# 存在类继承时(注意:此时IDE可代码补全)
from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)

class LoginPage:
    def login_to_swag_labs(self, sb, username):
        sb.open("https://www.saucedemo.com")
        sb.type("#user-name", username)
        sb.type("#password", "secret_sauce")
        sb.click('input[type="submit"]')

class MyTests(BaseCase):
    def test_swag_labs_login(self):
        LoginPage().login_to_swag_labs(self, "standard_user")  # 注意此句,必须将 self 参数传递给外部,否则无法使用 SeleniumBase 的方法
        self.assert_element("div.inventory_list")
        self.assert_element('div:contains("Sauce Labs Backpack")')

常用命令

一般主要用的为下面这些命令,更多命令,见这里

pytest my_first_test.py # 直接运行测试(默认Chrome浏览器)

--firefox  # 切换浏览器运行测试(Firefox)
--headless  # 无头模式(默认Chrome浏览器)
--rs  # 对所有测试重用浏览器会话
--reruns=1  # 多次重新运行失败的测试(重试1次)
-n4  # 使用 [n] 个线程运行多线程测试(此处4个)
--html=report.html  # 测试完成后创建 pytest html 报告(报告文件名:report.html)
--maximize  # 浏览器窗口最大化
--window-size=WIDTH,HEIGHT  # 设置浏览器的起始窗口大小

--pdb -s  # 失败时激活调试模式(“c”继续)
--trace -s  # 直接用调试模式运行(“n”:下一步。“c”:继续)
--slow  # 以稍慢的速度执行
-x  # 第一次失败后就停止运行
--mobile  # 启用手机模式
--metrics=STRING  # 设置手机参数 "CSSWidth,CSSHeight,PixelRatio"

--settings-file=FILE  # 覆盖默认的 SeleniumBase 设置,默认设置文件见:seleniumbase/config/settings.py


使用场景举例

  1. 场景举例,下方测试使用直接继承,有1个登录,以及3个登录后才能进行的测试,则此时直接使用此命令即可pytest .\my_first_test.py --rs启用会话模式
from seleniumbase import BaseCase

BaseCase.main(__name__, __file__)


class MyTestClass(BaseCase):

    def test_00_login(self):
        # 登录
        self.open("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.assert_text("Products", "span.title")

    def test_01_swag_labs(self):
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_text("Your Cart", "span.title")
        self.assert_text("Backpack", "div.cart_item")

    def test_02_swag_labs(self):
        self.click("button#checkout")
        self.type("#first-name", "SeleniumBase")
        self.type("#last-name", "Automation")
        self.type("#postal-code", "77123")
        self.click("input#continue")
        self.assert_text("Checkout: Overview")
        self.assert_text("Backpack", "div.cart_item")

    def test_03_swag_labs(self):
        self.click("button#finish")
        self.assert_exact_text("Thank you for your order!", "h2")
        self.assert_element('img[alt="Pony Express"]')
        self.js_click("a#logout_sidebar_link")
        self.assert_element("div#login_button_container")
  1. 场景举例,下方测试使用BaseCase子类继承,有1个登录,以及3个登录后才能进行的测试,则此时直接使用此命令即可pytest .\my_first_test.py --rs启用会话模式
from seleniumbase import BaseCase

BaseCase.main(__name__, __file__)


class MyTestClass(BaseCase):
    def setUp(self, **kwargs):
        super().setUp(**kwargs)
        self.refresh()  # 刷新(F5)

    def login(self):
        # 登录
        self.open("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.assert_text("Products", "span.title")


class MyTestClass2(MyTestClass):
    def test_00_login(self):
        self.login()


class MyTestClass3(MyTestClass):
    def test_01_swag_labs(self):
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_text("Your Cart", "span.title")
        self.assert_text("Backpack", "div.cart_item")

    def test_02_swag_labs(self):
        self.click("button#checkout")
        self.type("#first-name", "SeleniumBase")
        self.type("#last-name", "Automation")
        self.type("#postal-code", "77123")
        self.click("input#continue")
        self.assert_text("Checkout: Overview")
        self.assert_text("Backpack", "div.cart_item")

    def test_03_swag_labs(self):
        self.click("button#finish")
        self.assert_exact_text("Thank you for your order!", "h2")
        self.assert_element('img[alt="Pony Express"]')
        self.js_click("a#logout_sidebar_link")
        self.assert_element("div#login_button_container")

GitHub SeleniumBase
本文章的原文地址
GitHub主页

posted @ 2024-04-08 16:34  星尘的博客  阅读(687)  评论(7编辑  收藏  举报