Gerkin+unittest(python)实现自动化
因为SAP推崇BDD思想 最近写UI自动化用的unittest 跟大家分享下Gerkin+unittest框架 实现自动化的方式。
以下是几种实现方式,从推荐到不推荐排列,可以选择自己喜欢的去试试
目录
方法一:使用 behave库(最推荐、最正宗)
1. 安装 behave
2. 项目目录结构
3. 编写 Gherkin 文件 (login.feature)
4. 实现步骤定义 (login_steps.py)
5. 配置环境 (environment.py)
6. 运行测试
方法二:使用 pytest-bdd并兼容 unittest风格
方法三:纯 unittest + 文档字符串(不推荐,仅作了解)
总结与推荐
方法一:使用 behave
库(最推荐、最正宗)
这是最经典、最正宗的方式。behave
是一个纯 BDD 框架,它可以与 unittest
风格的断言和项目结构很好地共存。你不需要扭曲 unittest
,而是让 behave
负责 BDD 层,底层仍然可以调用 unittest
的断言或组织方式。
1. 安装 behave
pip install behave
2. 项目目录结构
behave
要求一个特定的目录结构:
project_root/
│
├── features/ # 必须叫 features/
│ ├── login.feature # Gherkin 特性文件
│ └── environment.py # 全局设置和销毁 (类似 setup/teardown)
│
├── steps/ # 必须叫 steps/
│ └── login_steps.py # 步骤定义实现文件
│
└── pages/ # (可选)Page Object 目录└── login_page.py
3. 编写 Gherkin 文件 (login.feature
)
# features/login.feature
Feature: User LoginAs a user, I want to log in to the system so that I can access my personal content.Scenario: Successful login with valid credentialsGiven I am on the login pageWhen I enter a valid username "testuser" and password "Pass123"And I click the login buttonThen I should be redirected to the dashboard pageAnd I should see a welcome message containing "Welcome"
4. 实现步骤定义 (login_steps.py
)
在步骤定义中,你可以自由地使用 unittest
的 self.assert*
方法。通常我们会定义一个上下文类,或者直接使用 context
对象。
# steps/login_steps.py
from behave import given, when, then
from pages.login_page import LoginPage # 导入你的Page Object或工具类
import unittest# 创建一个unittest.TestCase的实例来使用其断言方法
# 更常见的做法是直接使用Python自带的assert,但这里展示如何结合unittest
assertion = unittest.TestCase()@given("I am on the login page")
def step_impl(context):context.login_page = LoginPage(context.driver) # context.driver 需要在environment.py中设置context.login_page.load()@when('I enter a valid username "{username}" and password "{password}"')
def step_impl(context, username, password):context.login_page.enter_username(username)context.login_page.enter_password(password)@when("I click the login button")
def step_impl(context):context.login_page.click_login()@then("I should be redirected to the dashboard page")
def step_impl(context):# 使用 unittest 的断言assertion.assertEqual(context.driver.current_url, "https://example.com/dashboard")# 或者使用Python自带断言: assert "dashboard" in context.driver.current_url@then('I should see a welcome message containing "{text}"')
def step_impl(context, text):welcome_text = context.login_page.get_welcome_message()# 使用 unittest 的断言assertion.assertIn(text, welcome_text)
5. 配置环境 (environment.py
)
这个文件用于在所有测试之前之后执行代码,非常适合初始化和关闭浏览器。
# features/environment.py
from selenium import webdriverdef before_all(context):# 在所有场景开始之前执行一次context.driver = webdriver.Chrome()context.driver.implicitly_wait(10)def after_all(context):# 在所有场景结束之后执行一次context.driver.quit()def before_scenario(context, scenario):# 在每个场景开始之前执行passdef after_scenario(context, scenario):# 在每个场景结束之后执行,比如清理cookie,回到首页context.driver.delete_all_cookies()
6. 运行测试
在项目根目录下直接运行命令:
behave
方法二:使用 pytest-bdd
并兼容 unittest
风格
如果你的项目强制要求使用 unittest
的运行器或格式,但你仍想用 Gherkin,可以这样操作。pytest-bdd
本身兼容 unittest.TestCase
风格的类。
安装:
pip install pytest pytest-bdd
编写测试:
# test_login_bdd.py
import unittest
from pytest_bdd import scenarios, given, when, then, parsers
from pages.login_page import LoginPage# 指定feature文件路径
scenarios('../features/login.feature')class TestLoginBDD(unittest.TestCase): # 继承 unittest.TestCase@given("I am on the login page")def i_am_on_login_page(self):self.login_page = LoginPage(self.driver) # 假设self.driver在setUp中定义self.login_page.load()@when(parsers.parse('I enter a valid username "{username}" and password "{password}"'))def enter_credentials(self, username, password):self.login_page.enter_username(username)self.login_page.enter_password(password)@when("I click the login button")def click_login(self):self.login_page.click_login()@then("I should be redirected to the dashboard page")def check_redirection(self):# 使用 unittest 经典的断言方法self.assertIn("dashboard", self.driver.current_url)@then(parsers.parse('I should see a welcome message containing "{text}"'))def check_welcome_message(self, text):welcome_text = self.login_page.get_welcome_message()self.assertIn(text, welcome_text)
你需要用 pytest
命令来运行这个文件,因为它使用了 pytest-bdd
的装饰器。
方法三:纯 unittest + 文档字符串(不推荐,仅作了解)
这是一种“山寨”BDD,它保留了 BDD 的“描述性”但失去了“可执行规范”和“活文档”的核心优势。
# test_login.py
import unittest
from selenium import webdriver
from pages.login_page import LoginPageclass TestLogin(unittest.TestCase):def setUp(self):self.driver = webdriver.Chrome()self.login_page = LoginPage(self.driver)def test_successful_login_with_valid_credentials(self):"""Scenario: Successful login with valid credentialsGiven I am on the login pageWhen I enter a valid username and passwordAnd I click the login buttonThen I should be redirected to the dashboard pageAnd I should see a welcome message"""# Givenself.login_page.load()# Whenself.login_page.enter_credentials("testuser", "Pass123")self.login_page.click_login()# Thenself.assertIn("dashboard", self.driver.current_url)self.assertIn("Welcome", self.login_page.get_welcome_message())def tearDown(self):self.driver.quit()if __name__ == '__main__':unittest.main(verbosity=2) # 高 verbosity 会打印文档字符串
运行后,输出会显示文档字符串,看起来有点像 BDD 场景,但它不是真正的 Gherkin,无法与产品经理共享和讨论。
总结与推荐
方法 | 优点 | 缺点 | 推荐度 |
---|---|---|---|
| 最正宗,社区成熟,结构清晰,与 | 需要遵守其目录结构,学习一套新的命令 | ⭐⭐⭐⭐⭐ |
| 功能强大,与 | 本质上还是 | ⭐⭐⭐⭐ |
纯 unittest | 无需引入新库,利用现有框架 | 不是真正的 BDD,无法生成活文档,失去了 BDD 的最大价值 | ⭐ |
强烈推荐使用 behave
。它是在 Python 中实践 BDD 的事实标准,能让你真正收获 BDD 带来的沟通和协作好处,而不是仅仅在代码风格上做样子。