End-to-end testing Best Practices
原文:https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html
- Prefer API over UI
 - Avoid superfluous expectations
 - Prefer to split tests across multiple files
 - Limit the use of the UI in 
before(:context)andafterhooks - Ensure tests do not leave the browser logged in
 - Tag tests that require Administrator access
 - Prefer 
Commitresource overProjectPush 
End-to-end testing Best Practices
注意:这是测试指南中最佳实践的量身定制的扩展.
Prefer API over UI
端到端测试框架能够根据具体情况来构造其资源. 应尽可能通过 API 来构造资源.
通过 API 构造测试所需的资源,我们可以节省时间和金钱.
Learn more about resources.
Avoid superfluous expectations
为了使测试保持精简,重要的是我们仅测试需要测试的内容.
确保不添加任何与需要测试的内容无关的expect()语句.
例如:
#=> Good
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
  expect(menu).to be_signed_in
end
#=> Bad
Flow::Login.sign_in(as: user)
Page::Main::Menu.perform do |menu|
  expect(menu).to be_signed_in
  expect(page).to have_content(user.name) #=>  we already validated being signed in. redundant.
  expect(menu).to have_element(:nav_bar) #=> likely unnecessary. already validated in lower-level. test doesn't call for validating this.
end
#=> Good
issue = Resource::Issue.fabricate_via_api! do |issue|
  issue.name = 'issue-name'
end
Project::Issues::Index.perform do |index|
  expect(index).to have_issue(issue)
end
#=> Bad
issue = Resource::Issue.fabricate_via_api! do |issue|
  issue.name = 'issue-name'
end
Project::Issues::Index.perform do |index|
  expect(index).to have_issue(issue)
  expect(page).to have_content(issue.name) #=> page content check is redundant as the issue was already validated in the line above.
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 功能),请确保在该块的末尾注销.
after(:all) do
  login unless Page::Main::Menu.perform(&:signed_in?)
  # Do something while logged in
  Page::Main::Menu.perform(&:sign_out)
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 请求.
# Using a commit resource
Resource::Commit.fabricate_via_api! do |commit|
  commit.commit_message = 'Initial commit'
  commit.add_files([
    {file_path: 'README.md', content: 'Hello, GitLab'}
  ])
end
# Using a ProjectPush
Resource::Repository::ProjectPush.fabricate! do |push|
  push.commit_message = 'Initial commit'
  push.file_name = 'README.md'
  push.file_content = 'Hello, GitLab'
end 
注意:当您的测试要求测试 SSH 集成或使用 Git CLI 时,使用ProjectPush会出现一些例外.