杰瑞科技汇

Python Selenium断言如何实现?

好的好的,我们来详细讲解一下在 Python Selenium 中进行断言的各种方法和最佳实践。

断言是自动化测试的核心,它的作用不是简单地判断脚本是否运行成功,而是验证被测网页的某个状态是否符合你的预期,如果断言失败,测试就会明确地标记为失败,并停止执行后续的检查,让你能快速定位问题。


为什么断言如此重要?

想象一下,你的自动化脚本成功打开了登录页面并点击了“登录”按钮,然后脚本执行完毕并返回“Pass”,但如果登录后页面根本没有跳转到主页,只是停留在登录页并显示“用户名或密码错误”,你的脚本也会因为所有命令都执行完毕而返回“Pass”,这就是没有断言的可怕之处。

断言能确保:

  • 验证关键功能:确认元素是否存在、文本是否正确、URL是否跳转等。
  • 提供清晰的失败信息:当断言失败时,你会知道具体是哪个预期没有满足。
  • 提高测试报告的准确性:让测试报告真正反映系统的质量。

Selenium 中的断言方法

Selenium 本身不提供专门的 assert 方法,而是通过获取实际值,然后使用 Python 自身的 assert 语句或 unittest/pytest 等测试框架的断言方法来进行比较。

1 核心思路:获取实际值 vs. 预期值

所有断言都遵循这个模式:

  1. 获取实际值:使用 Selenium 提供的方法从浏览器中获取当前信息。
  2. 定义预期值:在代码中写明你期望的正确信息。
  3. 进行比较:使用 assert 或测试框架的断言方法,将实际值与预期值进行比较。

2 常用的断言场景和代码示例

断言页面标题

这是最常见的断言之一,用于验证是否跳转到了正确的页面。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# 初始化 WebDriver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
try:
    # 1. 打开目标网页
    driver.get("https://www.example.com")
    # 2. 获取实际页面标题
    actual_title = driver.title
    # 3. 定义预期标题
    expected_title = "Example Domain"
    # 4. 使用 assert 进行断言
    # actual_title 不等于 expected_title,程序会抛出 AssertionError
    assert actual_title == expected_title, f"页面标题断言失败!预期: '{expected_title}', 实际: '{actual_title}'"
    print("页面标题断言成功!")
except AssertionError as e:
    print(f"测试失败: {e}")
finally:
    # 5. 关闭浏览器
    driver.quit()

断言页面 URL

用于验证重定向或链接跳转是否正确。

# ... (driver 初始化代码) ...
driver.get("https://www.google.com")
# 假设我们点击了一个链接,它会跳转到 example.com
# driver.find_element(By.LINK_TEXT, "Example").click() 
# time.sleep(2) # 等待跳转,实际项目中最好用显式等待
actual_url = driver.current_url
expected_url = "https://www.example.com/"
# assert actual_url == expected_url
# 更健壮的断言,可以忽略 URL 末尾的斜杠差异
assert actual_url.rstrip('/') == expected_url.rstrip('/')
print("URL 断言成功!")

断言元素是否存在

验证某个关键元素(如登录成功后的用户名)是否出现在页面上。

from selenium.common.exceptions import NoSuchElementException
# ... (driver 初始化代码) ...
driver.get("https://example.com/login")
# ... (执行登录操作) ...
# driver.find_element(By.ID, "username").send_keys("test_user")
# driver.find_element(By.ID, "password").send_keys("password123")
# driver.find_element(By.ID, "login-btn").click()
# 定义要查找的元素
element_locator = (By.ID, "welcome-message") # 假设登录成功后会出现这个元素
try:
    # 尝试查找元素
    welcome_element = driver.find_element(*element_locator)
    # find_element 没有抛出异常,说明元素存在
    assert welcome_element.is_displayed(), "元素存在但未显示"
    print("元素存在且可见,断言成功!")
except NoSuchElementException:
    # 如果捕获到异常,说明元素不存在
    assert False, f"断言失败:未能在页面上找到元素 {element_locator}"

注意:直接 assert driver.find_element(...) 并不好,因为它会抛出 NoSuchElementException,而不是一个清晰的断言错误,上面的 try-except 结构是更规范的做法。

断言元素的文本内容

验证按钮、标签、消息提示等文本是否正确。

# ... (driver 初始化代码) ...
driver.get("https://example.com")
# 获取页面上的主标题文本
header_text = driver.find_element(By.TAG_NAME, "h1").text
expected_text = "Example Domain"
assert header_text == expected_text, f"文本断言失败!预期: '{expected_text}', 实际: '{header_text}'"
print("文本内容断言成功!")

断言元素属性

验证元素的属性,如 hrefclassid 等。

# ... (driver 初始化代码) ...
driver.get("https://www.example.com")
# 找到 "More information..." 这个链接
link = driver.find_element(By.XPATH, "//a[text()='More information...']")
# 获取 href 属性的实际值
actual_href = link.get_attribute("href")
# 定义预期的 href 值
expected_href = "https://www.iana.org/domains/example"
assert actual_href == expected_href, f"链接 href 断言失败!预期: '{expected_href}', 实际: '{actual_href}'"
print("链接属性断言成功!")

断言元素是否被选中

常用于复选框或单选框。

# ... (driver 初始化代码) ...
# driver.get("https://example.com/form") # 假设有一个表单页面
checkbox = driver.find_element(By.ID, "terms-checkbox")
# checkbox.click() # 假设我们勾选了它
# 断言复选框是否被选中
assert checkbox.is_selected() == True, "复选框未被选中,断言失败!"
print("复选框选中状态断言成功!")

结合测试框架进行断言(强烈推荐)

在实际项目中,我们通常使用 unittestpytest 框架,它们提供了更丰富的断言方法和更好的测试报告。

使用 unittest 框架

unittest 提供了 self.assertEqual(), self.assertTrue(), self.assertIn() 等方法,失败时会提供更详细的报告。

import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
class TestExamplePage(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        """在所有测试开始前执行,用于初始化 WebDriver"""
        cls.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
        cls.driver.implicitly_wait(10) # 隐式等待
    @classmethod
    def tearDownClass(cls):
        """在所有测试结束后执行,用于关闭 WebDriver"""
        cls.driver.quit()
    def test_page_title(self):
        """测试页面标题"""
        self.driver.get("https://www.example.com")
        self.assertEqual(self.driver.title, "Example Domain", "页面标题不正确")
    def test_paragraph_text(self):
        """测试段落文本"""
        self.driver.get("https://www.example.com")
        paragraph_element = self.driver.find_element(By.TAG_NAME, "p")
        self.assertEqual(paragraph_element.text, "This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.", "段落文本不正确")
if __name__ == '__main__':
    unittest.main()

使用 pytest 框架

pytest 更简洁、灵活,是当前非常流行的测试框架,你可以直接使用 Python 原生的 assert 语句。

import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# 使用 fixture 来管理 WebDriver 的生命周期
@pytest.fixture(scope="function")
def driver():
    """为每个测试函数提供一个 driver 实例"""
    my_driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
    my_driver.implicitly_wait(10)
    yield my_driver
    my_driver.quit()
def test_page_title(driver):
    """测试页面标题"""
    driver.get("https://www.example.com")
    assert driver.title == "Example Domain"
def test_paragraph_text(driver):
    """测试段落文本"""
    driver.get("https://www.example.com")
    paragraph_element = driver.find_element(By.TAG_NAME, "p")
    expected_text = "This domain is for use in illustrative examples in documents..."
    assert expected_text in paragraph_element.text

最佳实践

  1. 优先使用显式等待:不要用 time.sleep(),显式等待 (WebDriverWait) 只会等待元素出现或满足条件,超时后才会报错,使你的测试更稳定、更快。

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    # 等待最多10秒,直到ID为 'myDynamicElement' 的元素可见
    element = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.ID, "myDynamicElement"))
    )
  2. 断言关键业务流程:不要在每个小步骤都断言,在业务流程的关键节点(如登录后、下单后、支付后)进行断言,验证最终结果。

  3. 编写清晰的断言信息:在 assert 语句中提供清晰的错误信息,assert actual == expected, f"Expected {expected}, but got {actual}",当测试失败时,这能帮你快速定位问题。

  4. 结合测试框架:强烈建议使用 pytestunittest,它们能更好地组织测试用例、生成报告、管理测试固件。

  5. 断言要具体:不要只断言 assert True,要断言具体的值,assert "欢迎, 张三" in welcome_message.text,这比 assert welcome_message.is_displayed() 提供了更多信息。

分享:
扫描分享到社交APP
上一篇
下一篇