Help us learn about your current experience with the documentation. Take the survey.

使用功能开关进行测试

要运行启用了特定功能开关的测试,你可以使用 QA::Runtime::Feature 类来启用和禁用功能开关(通过 API)。

请注意,更改功能开关需要管理员权限。只要通过 GITLAB_QA_ADMIN_ACCESS_TOKEN(推荐)提供适当的访问令牌,或者提供 GITLAB_ADMIN_USERNAMEGITLAB_ADMIN_PASSWORDQA::Runtime::Feature 就会自动以管理员身份进行身份验证。

feature_flag RSpec 标签

请务必包含 feature_flag 标签,以便在适当的环境中跳过该测试。

必需的元数据

name

  • 格式:feature_flag: { name: 'feature_flag_name' }
  • 用于信息目的。应包含此元数据以确定正在测试哪个功能开关。

可选元数据

scope

  • 格式:feature_flag: { name: 'feature_flag_name', scope: :project }
  • scope 设置为 :global 时,测试将在所有线上 .com 环境中被跳过。这是为了避免功能开关的更改影响该环境上的其他测试或用户。
  • scope 设置为任何其他值(例如 :project:group:user),或者未指定 scope 时,测试将仅在 canary、production 和 pre-production 环境中被跳过。这是因为这些地方没有管理员访问权限。

我们强烈建议您首先尝试仅为某个群组、项目或用户启用功能开关,或功能组

  • 如果必须使用全局功能开关,强烈建议在 feature_flag 元数据中应用 scope: :global。但是,风险的级别由 SET(软件测试工程师)自行判断决定。
    • 例如,一个测试使用了一个只影响应用程序小部分区域的全局功能开关,并且还需要在上线环境中检查关键问题。在这种情况下,跳过运行测试的风险会更高。对于这类情况,可以不在元数据中设置 scope,这样它仍然可以在具有管理员访问权限的上线环境中运行,例如 staging 环境。

requires_admin 的注意事项:如果测试中还有其他需要管理员权限的操作,且这些操作与更新功能开关无关(例如通过 API 创建用户),则仍应应用此标签。

下面的代码将为测试创建的项目启用一个名为 :feature_flag_name 的功能开关:

RSpec.describe "with feature flag enabled", feature_flag: {
  name: 'feature_flag_name',
  scope: :project
  } do

  let(:project) { Resource::Project.fabricate_via_api! }

  around do |example|
    Runtime::Feature.enable(:feature_flag_name, project: project)
    example.run
    Runtime::Feature.disable(:feature_flag_name, project: project)
  end

  it "feature flag test" do
    # 在启用功能开关的情况下执行测试。
    # 它只会影响此测试中创建的项目。
  end
end

请注意,enabledisable 方法会先设置开关,然后检查 API 是否返回更新后的值。

同样,您可以为群组、用户或功能组启用功能:

group = Resource::Group.fabricate_via_api!
Runtime::Feature.enable(:feature_flag_name, group: group)

user = Resource::User.fabricate_via_api!
Runtime::Feature.enable(:feature_flag_name, user: user)

feature_group = "a_feature_group"
Runtime::Feature.enable(:feature_flag_name, feature_group: feature_group)

如果没有提供作用域,功能开关将在整个实例范围内设置:

# 这将影响所有用户!
Runtime::Feature.enable(:feature_flag_name)

与选择器协同工作

新功能通常会用新的 Vue 组件或 HAML 文件替换旧的。在大多数情况下,新的文件或组件只有在启用功能开关后才能访问。当测试必须在启用和未启用功能开关两种情况下都通过时,这种方法就会带来问题。为确保测试在这两种场景下都能通过:

  1. 在新的组件或文件中创建另一个选择器。
  2. 给它起一个与旧选择器相同的名字。

选择器在页面对象中与特定的前端文件关联,并在我们的 qa:selectors 测试中检查其可用性。如果该前端文件中缺少提到的选择器,测试就会失败。为确保选择器在启用或禁用功能开关时都可用,请将新选择器添加到页面对象中,同时保留旧选择器。这样,测试会使用正确的选择器,并且仍然能检测到缺失的选择器。

如果新功能更改了一个已有选择器的前端文件,您可以添加一个同名的新选择器。但是,页面上只会显示其中一个选择器。您应该:

  1. 使用功能开关禁用另一个选择器。
  2. 在前端文件中添加注释,说明在移除功能开关时,应从前端文件和页面对象文件中删除旧选择器。

示例修改前

# 这是旧文件的链接
view 'app/views/devise/passwords/edit.html.haml' do
  # 新选择器应具有相同的名称
  element 'password-field'
  ...
end

示例修改后

view 'app/views/devise/passwords/edit.html.haml' do
  element 'password-field'
  ...
end

# 现在它可以验证选择器是否可用
view 'app/views/devise/passwords/new_edit_behind_ff.html.haml' do
  # 选择器具有相同的名称
  element 'password-field'
end

与资源类协同工作

如果资源类在功能开关激活时需要有不同的行为,请在类内部切换一个与功能开关同名的变量。这个变量和条件确保所有操作都能得到妥善处理。

您可以在 fabricate_via_api 调用中设置此变量。为了保持方法的一致性:

  • 使用已激活的检查,而不是未激活的检查。
  • 在变量名末尾添加 activated 一词。
  • initialize 方法中,设置变量的默认值。

例如:

def initialize
  name_of_the_feature_flag_activated = false
  ...
end

清理

移除功能开关后,请清理资源类并删除该变量。所有方法都应使用现在默认状态的条件处理程序。

管理由缓存引起的不稳定性

所有应用程序设置和所有功能开关都在 GitLab 内部缓存一分钟。在测试期间,所有缓存都被禁用,静态环境除外。

当测试更改功能开关时,如果某些元素只有在功能开关激活时才可见,可能会导致测试行为不稳定。为了规避这种行为,请为功能开关背后的元素添加一个等待。

运行一个启用了功能开关的场景

也可以在不编辑现有测试或编写新测试的情况下,运行一个启用了功能开关的完整场景。

详细信息请参阅 QA README

确认端到端测试在功能开关启用的情况下通过

在功能开关于 Staging 环境或 GitLab.com 上启用之前,端到端测试应在功能开关启用的情况下通过。需要更新的测试应在四重规划过程中被识别出来。相关的对应的软件测试工程师负责更新测试或协助其他工程师完成。然而,如果一项变更没有经过四重规划,并且没有进行必要的测试更新,测试失败可能会阻止部署。

当功能开关定义更改时自动执行测试

有两种方法可以确认端到端测试是否通过:

  • 如果合并请求添加或编辑了功能开关定义文件,则两个 e2e:test-on-gdk 任务(gdk-instancegdk-instance-ff-inverse)会自动包含在合并请求的流水线中。一个任务以默认的功能开关状态运行应用程序,另一个则设置为相反的值。这两个任务执行相同的测试套件,以确认测试在功能开关启用或禁用的情况下都能通过。
  • 在某些情况下,如果端到端测试任务没有自动触发,或者它已经使用默认的功能开关值运行了测试(这可能不是期望的),您可以创建一个启用该功能开关的草稿合并请求,以确保所有端到端测试在功能开关启用和禁用的情况下都能通过。

功能开关启用时端到端测试故障排除

如果启用功能开关导致端到端测试失败,您可以浏览失败流水线中的产物,以查看失败的测试截图。之后,您可以:

  • 识别需要更新的测试,并联系负责更新测试或协助其他工程师完成的对应的软件测试工程师。然而,如果一项变更没有经过四重规划,并且没有进行必要的测试更新,测试失败可能会阻止部署。
  • 启用功能开关的情况下,在本地运行失败的测试。此选项需要相当多的设置工作,但您将能看到浏览器在运行失败测试时的操作,这有助于更快地调试问题。您也可以参考端到端测试故障排除指南以获取对常见障碍的支持。

功能开发期间的测试执行

如果端到端测试启用了功能开关,则可以通过在合并请求流水线中运行 e2e:test-on-omnibus-ee 任务,使用端到端测试套件来测试合并请求中的更改。如果功能开关和相关更改已经合并,您可以确认测试在默认分支上通过。端到端测试每两小时在默认分支上运行一次,结果会发布到测试会话报告中,该报告可在 testcase-sessions 项目中查看

如果相关测试本身没有启用功能开关,您可以通过打开一个通过功能开关定义文件默认启用该功能的草稿合并请求,来检查测试是否需要更新。这将自动执行端到端测试套件。一旦测试通过,该合并请求就可以关闭。如果您需要帮助更新测试,请联系质量部门的稳定对应人,或者如果您的团队没有稳定对应人,则联系任何软件测试工程师。