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)
andafter
hooks - Ensure tests do not leave the browser logged in
- Tag tests that require Administrator access
- Prefer
Commit
resource 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
会出现一些例外.