端到端测试编写入门指南
本教程将指导您为 GitLab Community Edition 和 GitLab Enterprise Edition 创建端到端(e2e)测试。
完成本教程后,您将能够:
- 判断是否需要编写端到端测试。
- 理解
qa/目录下的目录结构。 - 编写验证登录功能的基本端到端测试。
- 开发任何缺失的 page object 库。
编写测试前
在编写测试之前,您的 GitLab Development Kit (GDK) 必须配置为运行测试规范。端到端测试:
确定是否需要端到端测试
在为 GitLab 项目编写端到端测试之前,请检查特定功能的代码覆盖率。在单元、功能或集成级别是否有足够的测试覆盖率?如果答案是 是,那么您 不需要 端到端测试。
有关 GitLab 中各测试级别分布的信息,请参阅 Testing Levels。
- 查看 Testing levels 文档中的 How to test at the correct level? 部分。
- 评估功能变更的频率。如果功能已经由较低级别的测试覆盖,且变更不频繁,那么可能不值得使用端到端测试来覆盖。
- 最后,与实现该功能和编写较低级别测试的开发人员讨论建议的测试方案。
检查 GitLab 覆盖率项目中是否已有针对此功能的测试。要分析代码覆盖率,您必须了解哪些应用程序文件实现了特定功能。
在本教程中,我们将编写登录端到端测试,尽管它已被较低级别的测试充分覆盖,因为它是大多数端到端流程的第一步,且最容易理解。
识别 DevOps 阶段
GitLab QA 端到端测试按照 DevOps 生命周期中的不同阶段 组织。通过 stage 确定测试应放置的位置,确定测试所属的功能,然后将其放置在阶段下的子目录中。
如果测试仅适用于企业版,则测试创建在 features/ee 目录中,但遵循相同的 DevOps 生命周期格式。
创建骨架测试
在本教程的第一部分,我们测试登录功能,它属于管理阶段。在 qa/specs/features/browser_ui/1_manage/login 目录下,创建一个 basic_login_spec.rb 文件。
外部 context 块
外部 context 已被弃用,以遵循 RSpec 4.0 规范。请使用 RSpec.describe 替代。
外部 RSpec.describe 块
测试规范有一个外部的 RSpec.describe,表示 DevOps 阶段。
# frozen_string_literal: true
module QA
RSpec.describe 'Manage' do
end
enddescribe 块
在我们的外部 RSpec.describe 内部,描述要测试的功能。在这里是 Login。
# frozen_string_literal: true
module QA
RSpec.describe 'Manage' do
describe 'Login' do
end
end
endproduct_group 元数据
分配 product_group 元数据,并指定此测试属于哪个产品组。在这里是 authentication_and_authorization。
# frozen_string_literal: true
module QA
RSpec.describe 'Manage' do
describe 'Login', product_group: :authentication do
end
end
endit 块(示例)
每个测试套件至少包含一个 it 块(示例)。编写端到端测试的一个好方法是编写测试用例描述作为 it 块:
module QA
RSpec.describe 'Manage' do
describe 'Login', product_group: :authentication do
it 'can login' do
end
it 'can logout' do
end
end
end
end编写测试
一个重要的问题是"我们测试什么?",更重要的是"我们如何测试?"
首先从登录开始。
# frozen_string_literal: true
module QA
RSpec.describe 'Manage' do
describe 'Login', product_group: :authentication do
it 'can login' do
Flow::Login.sign_in
end
it 'can logout' do
Flow::Login.sign_in
end
end
end
end有关 Flows 的更多信息,请参阅 Flows
在 运行规范 后,我们的测试应该登录并结束;然后我们应该回答"我们测试什么?“这个问题。
# frozen_string_literal: true
module QA
RSpec.describe 'Manage' do
describe 'Login', product_group: :authentication do
it 'can login' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
expect(menu).to be_signed_in
end
end
it 'can logout' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
menu.sign_out
expect(menu).not_to be_signed_in
end
end
end
end
end我们测试什么?
- 我们可以登录吗?
- 我们可以登出吗?
我们如何测试?
- 检查用户头像是否出现在左侧边栏。
- 检查用户头像 不 出现在左侧边栏。
在幕后,be_signed_in 是一个 predicate matcher,它 实现了检查用户头像。
去除代码重复
重构您的测试,使用 before 块进行测试设置,因为它重复调用了 sign_in。
# frozen_string_literal: true
module QA
RSpec.describe 'Manage' do
describe 'Login', product_group: :authentication do
before do
Flow::Login.sign_in
end
it 'can login' do
Page::Main::Menu.perform do |menu|
expect(menu).to be_signed_in
end
end
it 'can logout' do
Page::Main::Menu.perform do |menu|
menu.sign_out
expect(menu).not_to be_signed_in
end
end
end
end
endbefore 块本质上是 before(:each),在每个示例运行之前执行,确保我们现在在每个测试开始时都登录。
使用资源和页面对象进行测试设置
接下来,让我们测试登录以外的功能。让我们测试问题(Issues),它属于计划阶段和项目管理组,因此在 创建文件 到 qa/specs/features/browser_ui/2_plan/issue 目录下,命名为 issues_spec.rb。
# frozen_string_literal: true
module QA
RSpec.describe 'Plan' do
describe 'Issues', product_group: :project_management do
let(:issue) { create(:issue) }
before do
Flow::Login.sign_in
issue.visit!
end
it 'can close an issue' do
Page::Project::Issue::Show.perform do |show|
show.click_close_issue_button
expect(show).to be_closed
end
end
end
end
end注意以下重要点:
- 在我们的示例开始时,我们位于
page/issue/show.rb页面。 - 我们的测试只按需创建所需内容。
- 问题通过 API 创建以节省时间。
- GitLab 偏好使用
let()而不是实例变量。请参阅 最佳实践。 be_closed尚未在page/project/issue/show.rb中实现,但在下一步中实现。
问题被创建为 Resource,这是您可以通过 UI 或 API 创建的 GitLab 实体。其他示例包括:
编写页面对象
Page Object 是我们套件中的一个类,代表 GitLab 中的一个页面。登录页面就是一个例子。由于我们的 问题详情 页面的页面对象已经存在,添加 closed? 方法。
module Page::Project::Issue
class Show
view 'app/views/projects/issues/show.html.haml' do
element 'closed-status-box'
end
def closed?
has_element?('closed-status-box')
end
end
end接下来,在您的视图中定义 closed-status-box 元素,以便您的页面对象可以识别它。
-#=> app/views/projects/issues/show.html.haml
.issuable-status-box.status-box.status-box-issue-closed{ ..., data: { testid: 'closed-status-box' } }运行规范
在运行规范之前,请确保:
- 已安装 GDK。
- GDK 在本地端口 3000 上运行。
- 没有应用额外的 RSpec 元数据标签。
- 您的工作目录是 GDK GitLab 安装中的
qa/。 - 您的 GitLab 实例级设置为默认值。如果您更改了默认设置,某些测试可能会产生意外结果。
- 因为 GDK 首次登录需要更改密码,您必须包含
root用户的 GDK 密码
要运行规范,请执行以下命令:
GITLAB_PASSWORD=<GDK root password> bundle exec rspec <test_file>其中 <test_file> 是:
- 运行登录示例时,使用
qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb。 - 运行问题示例时,使用
qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb。
有关测试执行和可能选项的更多信息,请参阅 “QA framework README”
准备代码审查
在提交测试进行代码审查之前,有几个清理工作要做:
- 确保测试名称遵循推荐的 命名约定。
- 确保规范 链接到测试用例。
- 确保规范具有正确的
product_group元数据。有关组的完整列表,请参阅 Product sections, stages, groups, and categories。 - 确保将相关的 RSpec 元数据 添加到规范中。
- 确保页面对象元素按照 推荐的命名约定 命名。
端到端测试合并请求模板
提交新的端到端测试时,使用 “New End to End Test” 合并请求描述模板,了解成功合并前所需的额外步骤。