테스트 실험

RSpec로 테스트 실험하기

실험 작업 중에는 내장된 RSpec 도구를 사용하고 싶을 수 있습니다. 이는 spec/experiments의 파일에 대해 자동으로 발생하지만, 이를 포함하고자 하는 다른 파일 및 스펙에 대해서는 :experiment 유형을 지정할 수 있습니다:

it "실험을 잘 테스트합니다", :experiment do
end

스텁 헬퍼

stub_experiments를 사용하여 실험을 스텁할 수 있습니다. 실험 이름을 키로 하고, 각 실험이 해결될 변수를 값으로 하는 해시를 전달하세요:

# `:example` 및 `:example2`라는 이름의 실험이 모두 "활성화"되어 있고
# 각 실험이 주어진 변형(`:my_variant` 및 `:control`)으로 해결된다는 것을 보장합니다.
stub_experiments(example: :my_variant, example2: :control)

experiment(:example) do |e|
  e.enabled? # => true
  e.assigned.name # => 'my_variant'
end

experiment(:example2) do |e|
  e.enabled? # => true
  e.assigned.name # => 'control'
end

배제, 세분화 및 행동 매처

등록된 행동, 배제 및 세분화를 매처를 사용하여 테스트할 수도 있습니다.

class ExampleExperiment < ApplicationExperiment
  control { }
  candidate { '_candidate_' }

  exclude { context.actor.first_name == 'Richard' }
  segment(variant: :candidate) { context.actor.username == 'jejacks0n' }
end

excluded = double(username: 'rdiggitty', first_name: 'Richard')
segmented = double(username: 'jejacks0n', first_name: 'Jeremy')

# register_behavior 매처
expect(experiment(:example)).to register_behavior(:control)
expect(experiment(:example)).to register_behavior(:candidate).with('_candidate_')

# exclude 매처
expect(experiment(:example)).to exclude(actor: excluded)
expect(experiment(:example)).not_to exclude(actor: segmented)

# segment 매처
expect(experiment(:example)).to segment(actor: segmented).into(:candidate)
expect(experiment(:example)).not_to segment(actor: excluded)

추적 매처

추적 이벤트는 실험의 주요 요소입니다. 추적 호출이 커버되도록 유연한 방법을 제공하려고 합니다.

이 작업은 인스턴스 수준이나 “모든 인스턴스” 수준에서 수행할 수 있습니다:

subject = experiment(:example)

expect(subject).to track(:my_event)

subject.track(:my_event)

on_next_instance 체인 메서드를 사용하여 다음 인스턴스에서 발생하도록 지정할 수 있습니다. 이는 experiment(:example).track을 하위에서 호출할 때 도움이 됩니다:

expect(experiment(:example)).to track(:my_event).on_next_instance

experiment(:example).track(:my_event)

track 매처에 연결할 수 있는 메서드의 전체 예시입니다:

expect(experiment(:example)).to track(:my_event, value: 1, property: '_property_')
  .on_next_instance
  .with_context(foo: :bar)
  .for(:variant_name)

experiment(:example, :variant_name, foo: :bar).track(:my_event, value: 1, property: '_property_')

Jest로 테스트하기

스텁 헬퍼

spec/frontend/__helpers__/experimentation_helper.js에 정의된 stubExperiments 헬퍼를 사용하여 실험을 스텁할 수 있습니다.

import { stubExperiments } from 'helpers/experimentation_helper';
import { getExperimentData } from '~/experimentation/utils';

describe('내 실험이 활성화되었을 때', () => {
  beforeEach(() => {
    stubExperiments({ my_experiment: 'candidate' });
  });

  it('올바른 데이터를 설정합니다', () => {
    expect(getExperimentData('my_experiment')).toEqual({ experiment: 'my_experiment', variant: 'candidate' });
  });
});

참고:

이 방법으로 Jest 스펙에서 스텁한 실험은 테스트가 끝날 때 자동으로 복구되지 않습니다. 우리는 스텁된 실험을 window.gl의 모든 다른 글로벌 데이터와 병합합니다. 테스트 후 스텁된 실험을 제거하거나 테스트 전에 깨끗한 글로벌 객체를 보장해야 하는 경우, 글로벌 객체를 직접 관리해야 합니다:

describe('글로벌 상태에 관심 있는 테스트', () => {
  const originalObjects = [];

  beforeEach(() => {
    // 역호환성을 위해 지금은 window.gon 및 window.gl을 사용하고 있습니다.
    originalObjects.push(window.gon, window.gl);
  });

  afterEach(() => {
    [window.gon, window.gl] = originalObjects;
  });

  it('신선한 글로벌 상태에서 실험을 스텁합니다', () => {
    stubExperiment({ my_experiment: 'candidate' });
    // ...
  });
})