E2E 테스트는 사용자의 실제 사용 시나리오를 시뮬레이터에서 자동으로 검증합니다. Detox는 React Native 최적화된 E2E 프레임워크입니다.


설치

BASH
npm install -D detox @types/detox jest-circus
# macOS에서 iOS 테스트를 위해
brew tap wix/brew && brew install applesimutils

설정

JS
// .detoxrc.js
module.exports = {
  testRunner: {
    args: { $0: 'jest', config: 'e2e/jest.config.js' },
    jest: { setupTimeout: 120000 },
  },
  apps: {
    'ios.debug': {
      type: 'ios.app',
      binaryPath: 'ios/build/MyApp.app',
      build: 'xcodebuild -workspace ios/MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
    },
    'android.debug': {
      type: 'android.apk',
      binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
      build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
    },
  },
  devices: {
    simulator: { type: 'ios.simulator', device: { type: 'iPhone 15' } },
    emulator: { type: 'android.emulator', device: { avdName: 'Pixel_4_API_34' } },
  },
  configurations: {
    'ios.sim.debug': { device: 'simulator', app: 'ios.debug' },
    'android.emu.debug': { device: 'emulator', app: 'android.debug' },
  },
};

E2E 테스트 작성

TSX
// e2e/login.test.ts
describe('로그인 플로우', () => {
  beforeAll(async () => {
    await device.launchApp();
  });

  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('이메일과 비밀번호로 로그인할 수 있다', async () => {
    // 이메일 입력
    await element(by.id('email-input')).typeText('test@example.com');
    // 비밀번호 입력
    await element(by.id('password-input')).typeText('password123');
    // 키보드 닫기
    await element(by.id('password-input')).tapReturnKey();
    // 로그인 버튼 탭
    await element(by.id('login-button')).tap();

    // 홈 화면으로 이동 확인
    await waitFor(element(by.id('home-screen')))
      .toBeVisible()
      .withTimeout(5000);
  });

  it('잘못된 비밀번호 입력 시 에러 메시지를 보여준다', async () => {
    await element(by.id('email-input')).typeText('test@example.com');
    await element(by.id('password-input')).typeText('wrong');
    await element(by.id('login-button')).tap();

    await waitFor(element(by.text('이메일 또는 비밀번호가 올바르지 않습니다')))
      .toBeVisible()
      .withTimeout(3000);
  });
});

주요 API

TSX
// 요소 찾기
element(by.id('testID'))           // testID로 찾기
element(by.text('텍스트'))          // 텍스트로 찾기
element(by.label('접근성 라벨'))    // 접근성 라벨로 찾기

// 액션
await element(by.id('btn')).tap();            // 탭
await element(by.id('input')).typeText('hello'); // 텍스트 입력
await element(by.id('input')).clearText();    // 텍스트 지우기
await element(by.id('list')).scroll(200, 'down'); // 스크롤
await element(by.id('item')).swipe('left');   // 스와이프

// 어설션
await expect(element(by.id('title'))).toBeVisible();
await expect(element(by.id('title'))).toHaveText('홈');
await expect(element(by.id('title'))).not.toExist();

// 대기
await waitFor(element(by.id('content')))
  .toBeVisible()
  .withTimeout(5000);

실행

BASH
# 빌드
npx detox build --configuration ios.sim.debug

# 테스트 실행
npx detox test --configuration ios.sim.debug

# 특정 테스트만 실행
npx detox test --configuration ios.sim.debug e2e/login.test.ts

정리

  • Detox 는 실제 시뮬레이터/에뮬레이터에서 앱을 실행하여 사용자 시나리오를 검증합니다
  • testID를 컴포넌트에 미리 부여해두면 E2E 테스트 작성이 수월합니다
  • waitFor비동기 UI 변화를 안전하게 대기 하세요
  • CI 파이프라인에서 빌드 후 자동 E2E 테스트를 실행하면 회귀 버그를 잡을 수 있습니다
  • 핵심 플로우(로그인, 결제, 회원가입)에 집중하여 E2E 테스트를 작성하세요
댓글 로딩 중...