推荐的组织方式

存放 feature 的方式

  1. features
  2. ├──frontend
  3. └──auth
  4. └──login.feature
  5. └──backend
  6. └──auth
  7. └──login.feature

存放测试文件的方式

  1. tests
  2. └──functional
  3. └──test_auth.py
  4. """Authentication tests."""
  5. from pytest_bdd import scenario
  6. @scenario('frontend/auth/login.feature')
  7. def test_logging_in_frontend():
  8. pass
  9. @scenario('backend/auth/login.feature')
  10. def test_logging_in_backend():
  11. pass

灵魂拷问

  • 如何指定运行哪些 features 或者 scenarios 呢?
  • 使用标记,和 @pytest.mark 差不多的原理

标记 🌰

mark.feature

  1. # 给 Feature 标记
  2. @article
  3. Feature: Resource owner
  4. # 给 Scenario 标记
  5. @author
  6. Scenario: I'm the author
  7. Given I'm an author
  8. And I have an article
  9. @admin
  10. Scenario: I'm the admin
  11. Given I'm the admin
  12. And there's an article

test_mark.py

  1. from pytest_bdd import given, scenarios
  2. # scenario
  3. scenarios('mark.feature')
  4. @given("I'm an author", target_fixture="author")
  5. def author():
  6. print("I'm an author")
  7. return dict(username="polo")
  8. @given("I'm the admin", target_fixture="author")
  9. def admin():
  10. print("I'm an admin")
  11. return dict(username="admin")
  12. @given("I have an article")
  13. @given("there's an article")
  14. def article(author):
  15. print("two given")
  16. return author

命令行运行

  1. # 选择 Feature 级别的标记
  2. pytest -m "article"
  3. # 选择 Scenario 级别的标记
  4. pytest -m "author"
  5. # 多个 Scenario 级别的标记
  6. pytest -m "author or admin"
  7. # Feature + Scenario
  8. pytest -m "article and admin"

hook

可以通过实现 pytest_bdd_apply_tag 钩子并从中返回 True 来自定义标签如何转换为 pytest 标记

在测试用例目录下创建 conftest.py

添加以下代码

  1. import pytest
  2. def pytest_bdd_apply_tag(tag, function):
  3. if tag == 'article':
  4. print(function)
  5. marker = pytest.mark.skip(reason="Not implemented yet")
  6. marker(function)
  7. return True
  8. else:
  9. return False

再次命令行运行

  1. pytest -sq -m "article"

运行结果

  1. <function _get_scenario_decorator.<locals>.decorator.<locals>.scenario_wrapper at 0x10b1d1750>
  2. <function _get_scenario_decorator.<locals>.decorator.<locals>.scenario_wrapper at 0x10b1d1870>
  3. 15 deselected in 0.02s

刚刚会运行的两条测试用例这次不会运行了,因为通过 hook 标记为 skip