End-to-end testing Best Practices

原文:https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html

End-to-end testing Best Practices

注意:这是测试指南中最佳实践的量身定制的扩展.

Prefer API over UI

端到端测试框架能够根据具体情况来构造其资源. 应尽可能通过 API 来构造资源.

通过 API 构造测试所需的资源,我们可以节省时间和金钱.

Learn more about resources.

Avoid superfluous expectations

为了使测试保持精简,重要的是我们仅测试需要测试的内容.

确保不添加任何与需要测试的内容无关的expect()语句.

例如:

  1. #=> Good
  2. Flow::Login.sign_in
  3. Page::Main::Menu.perform do |menu|
  4. expect(menu).to be_signed_in
  5. end
  6. #=> Bad
  7. Flow::Login.sign_in(as: user)
  8. Page::Main::Menu.perform do |menu|
  9. expect(menu).to be_signed_in
  10. expect(page).to have_content(user.name) #=> we already validated being signed in. redundant.
  11. expect(menu).to have_element(:nav_bar) #=> likely unnecessary. already validated in lower-level. test doesn't call for validating this.
  12. end
  13. #=> Good
  14. issue = Resource::Issue.fabricate_via_api! do |issue|
  15. issue.name = 'issue-name'
  16. end
  17. Project::Issues::Index.perform do |index|
  18. expect(index).to have_issue(issue)
  19. end
  20. #=> Bad
  21. issue = Resource::Issue.fabricate_via_api! do |issue|
  22. issue.name = 'issue-name'
  23. end
  24. Project::Issues::Index.perform do |index|
  25. expect(index).to have_issue(issue)
  26. expect(page).to have_content(issue.name) #=> page content check is redundant as the issue was already validated in the line above.
  27. end

Prefer to split tests across multiple files

我们的框架包括几个并行化机制,这些机制通过并行执行 spec 文件来工作.

但是,由于测试是通过 spec 文件而不是通过 test / example 并行化的,因此如果将新测试添加到现有文件中,我们将无法实现更大的并行化.

尽管如此,可能还有其他原因要向现有文件添加新测试.

例如,如果测试共享状态的设置成本很高,则即使执行一次使用该设置的测试无法并行化,执行一次设置可能会更有效.

综上所述:

  • 可以 :将测试拆分到单独的文件中,除非测试共享昂贵的设置.
  • 不要 :在不考虑对并行化的影响的情况下,将新测试放在现有文件中.

Limit the use of the UI in before(:context) and after hooks

限制使用before(:context)挂钩仅通过 API 调用,非 UI 操作或基本 UI 操作(例如登录before(:context)来执行设置任务.

我们使用capybara-screenshot库自动保存失败时的屏幕截图.

capybara-screenshot 将屏幕 capybara-screenshot 保存在 RSpec 的after hook 中 . 如果before(:context)失败,则不会调用after挂钩 ,因此不会保存屏幕截图.

鉴于这一事实,我们应该将before(:context)使用仅限于不需要屏幕快照的那些操作.

同样, after钩子仅应用于非 UI 操作. 测试文件中after hook 中的任何 UI 操作都将在获取屏幕快照的after hook 之前执行. 这将导致 UI 状态从故障点移开,因此无法在正确的时刻捕获屏幕截图.

Ensure tests do not leave the browser logged in

所有测试都希望能够在测试开始时登录.

有关示例,请参见: https : //gitlab.com/gitlab-org/gitlab/-/issues/34736

理想情况下,在after(:context) (或before(:context) )块中执行的任何动作都可以通过 API 执行. 但是,如果有必要通过 UI 进行操作(例如,如果不存在 API 功能),请确保在该块的末尾注销.

  1. after(:all) do
  2. login unless Page::Main::Menu.perform(&:signed_in?)
  3. # Do something while logged in
  4. Page::Main::Menu.perform(&:sign_out)
  5. end

Tag tests that require Administrator access

我们不会运行需要管理员对生产环境进行访问的测试.

当您添加需要管理员访问权限的新测试时,请应用 RSpec 元数据:requires_admin以使该测试不会包含在针对生产环境和我们不想在其上运行这些测试的其他环境执行的测试套件中.

注意:在本地运行测试或配置管道时,可以将环境变量QA_CAN_TEST_ADMIN_FEATURES设置为false以跳过带有:requires_admin标记的测试.

Prefer Commit resource over ProjectPush

使用 API​​一致 ,请尽可能使用Commit资源.

ProjectPush通过 Git 命令行界面(CLI)使用原始 Shell 命令,而Commit资源则发出 HTTP 请求.

  1. # Using a commit resource
  2. Resource::Commit.fabricate_via_api! do |commit|
  3. commit.commit_message = 'Initial commit'
  4. commit.add_files([
  5. {file_path: 'README.md', content: 'Hello, GitLab'}
  6. ])
  7. end
  8. # Using a ProjectPush
  9. Resource::Repository::ProjectPush.fabricate! do |push|
  10. push.commit_message = 'Initial commit'
  11. push.file_name = 'README.md'
  12. push.file_content = 'Hello, GitLab'
  13. end

注意:当您的测试要求测试 SSH 集成或使用 Git CLI 时,使用ProjectPush会出现一些例外.