E2E Testing 완벽 마스터

E2E Testing의 핵심 개념과 실전 활용법

JavaScript중급
6시간
3개 항목
학습 진행률0 / 3 (0%)

학습 항목

1. JavaScript
중급
Cypress|실무|활용|팁
퀴즈튜토리얼
2. JavaScript
중급
Cypress|트러블슈팅|가이드|실전
퀴즈튜토리얼
3. React
중급
React|Native|테스트|전략|완벽|가이드
퀴즈튜토리얼
1 / 3

이미지 로딩 중...

Cypress 실무 활용 팁 - 슬라이드 1/13

Cypress 실무 활용 팁

Cypress를 실무 프로젝트에서 효과적으로 활용하기 위한 핵심 팁들을 소개합니다. 테스트 안정성 향상, 재사용 가능한 커맨드 작성, API 목킹 등 실전에서 바로 적용할 수 있는 베스트 프랙티스를 다룹니다.


카테고리:JavaScript
언어:JavaScript
난이도:intermediate
메인 태그:#Cypress
서브 태그:
#E2E Testing#Custom Commands#API Mocking#Test Automation

들어가며

이 글에서는 Cypress 실무 활용 팁에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. Custom_Commands로_재사용성_높이기
  2. Data_Attribute로_안정적인_선택자_사용
  3. cy.intercept로_API_응답_목킹
  4. fixture를_활용한_테스트_데이터_관리
  5. 조건부_테스트_처리하기
  6. 환경_변수로_다양한_환경_테스트
  7. before와_beforeEach로_효율적인_설정
  8. 암시적_대기로_비동기_처리
  9. 파일_업로드_테스트하기
  10. 페이지_객체_패턴으로_구조화
  11. 실패_시_스크린샷과_비디오_활용
  12. 테스트_격리로_독립성_보장

1. Custom_Commands로_재사용성_높이기

개요

반복되는 테스트 로직을 커스텀 커맨드로 만들어 코드 중복을 줄이고 유지보수성을 높일 수 있습니다.

코드 예제

// cypress/support/commands.js
Cypress.Commands.add('login', (email, password) => {
  cy.visit('/login')
  cy.get('[data-testid="email"]').type(email)
  cy.get('[data-testid="password"]').type(password)
  cy.get('[data-testid="submit"]').click()
})

// 테스트에서 사용
cy.login('user@test.com', 'password123')

설명

cy.login() 커맨드를 만들어 모든 테스트에서 간단하게 로그인 과정을 재사용할 수 있습니다.


2. Data_Attribute로_안정적인_선택자_사용

개요

CSS 클래스나 ID 대신 data-testid 속성을 사용하면 UI 변경에도 테스트가 깨지지 않습니다.

코드 예제

// ❌ 불안정한 방법
cy.get('.btn-primary').click()

// ✅ 안정적인 방법
cy.get('[data-testid="submit-button"]').click()

// ✅ 더 간결한 방법
cy.get('[data-cy="submit-button"]').click()

설명

data-testid나 data-cy 속성은 테스트 전용 선택자로, 스타일 변경에 영향받지 않아 테스트가 안정적입니다.


3. cy.intercept로_API_응답_목킹

개요

실제 API 호출 없이 네트워크 요청을 가로채서 원하는 응답을 반환할 수 있습니다.

코드 예제

cy.intercept('GET', '/api/users', {
  statusCode: 200,
  body: [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Smith' }
  ]
}).as('getUsers')

cy.visit('/users')
cy.wait('@getUsers')

설명

cy.intercept로 API 응답을 제어하여 다양한 시나리오를 테스트하고 백엔드 의존성을 제거합니다.


4. fixture를_활용한_테스트_데이터_관리

개요

테스트 데이터를 별도 파일로 관리하여 테스트 코드를 깔끔하게 유지할 수 있습니다.

코드 예제

// cypress/fixtures/users.json
{
  "admin": { "email": "admin@test.com", "password": "admin123" },
  "user": { "email": "user@test.com", "password": "user123" }
}

// 테스트에서 사용
cy.fixture('users').then((users) => {
  cy.login(users.admin.email, users.admin.password)
})

설명

fixture 파일로 테스트 데이터를 중앙화하여 여러 테스트에서 일관되게 사용할 수 있습니다.


5. 조건부_테스트_처리하기

개요

요소의 존재 여부에 따라 다르게 동작하는 조건부 로직을 안전하게 구현할 수 있습니다.

코드 예제

cy.get('body').then($body => {
  if ($body.find('[data-cy="modal"]').length > 0) {
    cy.get('[data-cy="close-modal"]').click()
  }
})

// 또는 should로 확인
cy.get('[data-cy="notification"]')
  .should('exist')
  .and('be.visible')

설명

jQuery 메서드를 사용하여 요소 존재를 확인하고, 조건에 따라 다른 액션을 수행할 수 있습니다.


6. 환경_변수로_다양한_환경_테스트

개요

cypress.config.js에서 환경 변수를 설정하여 개발, 스테이징, 프로덕션 환경을 쉽게 전환할 수 있습니다.

코드 예제

// cypress.config.js
module.exports = {
  env: {
    apiUrl: 'https://api.dev.example.com',
    timeout: 10000
  }
}

// 테스트에서 사용
cy.visit(Cypress.env('apiUrl') + '/users')
cy.wait(Cypress.env('timeout'))

설명

env 설정으로 환경별 URL이나 설정값을 관리하여 유연하게 테스트를 실행할 수 있습니다.


7. before와_beforeEach로_효율적인_설정

개요

테스트 전에 공통 설정을 수행하여 테스트 코드의 중복을 줄이고 실행 속도를 높일 수 있습니다.

코드 예제

describe('User Dashboard', () => {
  before(() => {
    cy.clearCookies()
  })

  beforeEach(() => {
    cy.login('user@test.com', 'password')
    cy.visit('/dashboard')
  })

  it('shows user profile', () => {
    cy.get('[data-cy="profile"]').should('be.visible')
  })
})

설명

before는 한 번만, beforeEach는 각 테스트마다 실행되어 테스트 환경을 효율적으로 준비합니다.


8. 암시적_대기로_비동기_처리

개요

Cypress는 자동으로 요소를 기다리지만, cy.wait()를 명시적으로 사용하여 특정 조건을 기다릴 수 있습니다.

코드 예제

// API 요청 기다리기
cy.intercept('POST', '/api/save').as('saveData')
cy.get('[data-cy="save-btn"]').click()
cy.wait('@saveData')
cy.contains('저장되었습니다').should('be.visible')

// 시간 기반 대기 (비추천)
// cy.wait(3000)

설명

네트워크 요청에 별칭을 지정하고 cy.wait()로 완료를 기다려 테스트 안정성을 높입니다.


9. 파일_업로드_테스트하기

개요

cypress-file-upload 플러그인을 사용하여 파일 업로드 기능을 간단하게 테스트할 수 있습니다.

코드 예제

// cypress/support/commands.js에서 설정
import 'cypress-file-upload'

// 테스트에서 사용
cy.get('[data-cy="file-input"]')
  .attachFile('example.jpg')

cy.get('[data-cy="upload-btn"]').click()
cy.contains('업로드 완료').should('be.visible')

설명

attachFile 커맨드로 fixtures 폴더의 파일을 input 요소에 첨부하여 업로드를 테스트합니다.


10. 페이지_객체_패턴으로_구조화

개요

페이지별로 선택자와 액션을 클래스로 캡슐화하여 테스트 코드의 가독성과 유지보수성을 높입니다.

코드 예제

// cypress/pages/LoginPage.js
class LoginPage {
  visit() { cy.visit('/login') }
  fillEmail(email) { cy.get('[data-cy="email"]').type(email) }
  fillPassword(pwd) { cy.get('[data-cy="password"]').type(pwd) }
  submit() { cy.get('[data-cy="submit"]').click() }
}
export default new LoginPage()

// 테스트에서 사용
import LoginPage from '../pages/LoginPage'
LoginPage.visit()
LoginPage.fillEmail('user@test.com')

설명

페이지 객체 패턴으로 UI 변경 시 한 곳만 수정하면 되어 유지보수가 쉬워집니다.


11. 실패_시_스크린샷과_비디오_활용

개요

Cypress는 실패한 테스트의 스크린샷과 비디오를 자동으로 캡처하여 디버깅을 쉽게 만듭니다.

코드 예제

// cypress.config.js
module.exports = {
  video: true,
  screenshotOnRunFailure: true,
  videosFolder: 'cypress/videos',
  screenshotsFolder: 'cypress/screenshots'
}

// 수동 스크린샷
cy.screenshot('my-screenshot')

설명

실패한 테스트의 스크린샷과 비디오가 자동 저장되어 CI/CD에서 문제를 빠르게 파악할 수 있습니다.


12. 테스트_격리로_독립성_보장

개요

각 테스트가 독립적으로 실행되도록 쿠키, 로컬 스토리지, 세션을 정리합니다.

코드 예제

beforeEach(() => {
  cy.clearCookies()
  cy.clearLocalStorage()
  cy.window().then((win) => {
    win.sessionStorage.clear()
  })
})

// 특정 쿠키만 유지
cy.clearCookies({ except: ['session_id'] })

설명

테스트 간 상태를 격리하여 이전 테스트의 영향을 받지 않고 독립적으로 실행되도록 합니다.


마치며

이번 글에서는 Cypress 실무 활용 팁에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#Cypress #E2E Testing #Custom Commands #API Mocking #Test Automation

#Cypress#E2E Testing#Custom Commands#API Mocking#Test Automation#JavaScript