🎉 berenickt 블로그에 온 걸 환영합니다. 🎉
Front
프론트엔드 테스트

1. 프론트엔드 테스트란?

  • 소프트웨어 테스트: 소프트웨어 개발에서 사용자 인터페이스(UI) 및 사용자 경험(UX)를 검증하는 과정
    • 전반적으로 소프트웨어가 기대된 대로 작동하는지 확인하고, 잠재적인 버그를 찾아내어 개선하는 프로세스
  • 소프트웨어 테스트의 중요성:
    • 사용자에게 안정적이고 오류가 적은 제품을 제공
    • 개발 주기 초기에 버그를 찾아내어 수정함으로써 프로젝트 비용을 절감하고 개발 속도를 향상
  • 테스트 종류: 유닛 테스트(unit testing), 통합 테스트(integration testing), E2E(End-to-End) 테스트 등
  • 왜 테스트를 해야할까?
    • 버그와 에러의 조기 발견, 코드 변경의 안전성, 사용자 경험 향상, 유지보수의 편의성, 자동화를 통한 효율성 증대 등
    • 적절한 테스트 전략과 도구를 활용하여 안정적이고 신뢰성 있는 소프트웨어를 개발하는 것이 중요

1.1 프론트엔드 테스트의 필요성

  • 신뢰성 확보: 테스트를 통해 코드의 예상치 못한 버그를 사전에 찾아내어 소프트웨어의 신뢰성을 높일 수 있음
    • e.g. 통합 테스트를 통해 컴포넌트 간의 상호 작용에서 발생할 수 있는 문제를 사전에 식별
  • 유지보수성 향상: 변경된 코드가 기존의 기능에 영향을 미치지 않음을 확인하여 유지보수성을 향상
    • e.g. 유닛 테스트로 기능의 핵심 로직이 정확하게 동작하는지 검증하고, 통합 테스트로 여러 모듈 간의 호환성 을 확인할 수 있음
  • 개발 생산성 향상: 테스트를 통해 안전하게 리팩토링을 수행하거나 새로운 기능을 추가할 수 있음
  • 버전 관리 및 협업의 용이성: 협업 시 버그의 원인을 더 쉽게 파악할 수 있도록 도와주며, 버전 간의 변경 사항을 추 적하는 데 도움
  • 사용자 경험 향상: 성능 및 E2E(End-to-End) 테스트를 통해 사용자 경험을 향상시키고, 안정적인 애플리케이션 을 제공

1.2 프론트엔드 테스트 종류

  • 유닛 테스트(Unit Testing): 개별 컴포넌트, 함수, 또는 모듈과 같은 코드 단위를 격리하여 테스트
  • 통합 테스트(Integration Testing): 여러 컴포넌트나 모듈 간의 상호작용을 테스트하여 전체 시스템이 예상대로 통합되는지 확인하는 것
  • e2e 테스트(End-to-End Testing): 사용자의 관점에서 애플리케이션의 전체적인 동작을 테스트하는 것
  • Snapshot 테스트: 렌더링된 컴포넌트의 스냅샷(이전에 캡처된 렌더 결과)을 저장하고, 변경 여부를 검사
  • 성능 테스트: 애플리케이션의 성능을 측정하고, 특히 로딩 시간, 응답 시간, 자원 사용량 등을 테스트

1.2.1 Unit 테스트

1
// main.js
2
function add(a, b) {
3
return a + b
4
}
5
6
// math.test.js
7
const math = require('./math')
8
9
test('adds 1 + 2 to equal 3', () => {
10
expect(math.add(1, 2)).toBe(3)
11
})
  • 유닛 테스트: 유닛 테스트란 소프트웨어의 가장 작은 단위인 “유닛”에 대한 테스트.
    • 이때, 유닛은 주로 함수, 메서 드, 또는 모듈과 같은 개별적인 코드 조각을 의미
  • 유닛 테스트 수행 도구: Jest, Mocha 등
  • 테스트 작성 방법: 라이브러리 설치 → 테스트 슈트 작성 → 테스트 케이스 작성 → 테스트 실행
  • 유닛 테스트은 언제 사용할까: 대규모 프로젝트, CI/CD, 새로운 기능 추가 및 리팩토링

유닛 테스트를 작성할 때는 아래와같은 FIRST 원칙을 따른다:

  • Fast: 테스트는 빠르게 실행되어야 합니다. 느린 테스트는 개발자의 피드백을 늦추고 생산성을 저하
  • Isolated/Independent: 각 테스트는 독립적이어야 하며, 다른 테스트의 실행 결과에 영향을 받지 않아야 함
  • Repeatable: 테스트는 어떤 환경에서도 반복 가능해야 함
  • Self-validating: 테스트는 자체적으로 검증 가능하며, 성공 또는 실패 여부를 명확히 알려줘야 함
  • Timely: 테스트는 적절한 시점에 작성되어야 하며, 개발 초기부터 지속적으로 유지보수되어야 함

1.2.2 Integration 테스트

1
// src/components/ExampleComponent.test.tsx
2
import { render, screen } from '@testing-library/react'
3
import ExampleComponent from './ExampleComponent'
4
5
test('ExampleComponent renders properly', () => {
6
render(<ExampleComponent />)
7
8
// 검증
9
expect(screen.getByText('Hello, World')).toBeInTheDocument()
10
})
  • 통합 테스트: 여러 컴포넌트가 상호 작용하는 상황에서 전체 애플리케이션이 예상대로 작동하는지 확인하는 테스트.
    • 주로 컴포넌트 간의 통합이 원활하게 이뤄지는지, 데이터 플로우가 제대로 동작하는지를 검증
  • 통합 테스트 툴: React Testing Library 프론트엔드 테스트 종류 및 필요성 알아보기
  • 통합 테스트 방법: 라이브러리 설치 → 테스트 환경 설정 -> 테스트 코드 작성
  • 언제 통합 테스트를 사용해야할까?
    • 컴포넌트 간의 통합이 중요한 프로젝트, 비즈니스 로직이 복잡한 프로젝트, 데이터 플로우가 중요한 프로젝트

1.2.3 E2E 테스트

1
// cypress/integration/example_spec.ts
2
describe('E2E Example Test', () => {
3
it('Visits the app root url', () => {
4
cy.visit('https://your-app-url')
5
6
// 예제 : 로그인 테스트
7
cy.get('#username').type('your-username')
8
cy.get('#password').type('your-password')
9
cy.get('#login-button').click()
10
11
// 검증
12
cy.url().should('include', '/dashboard')
13
cy.get('.welcom-message').should('contain', 'Hello World!')
14
})
15
})
  • E2E 테스트 (End-to-End Testing): 사용자 시점에서 애플리케이션의 전체적인 흐름을 시뮬레이션하여,
    • 애플리케이션이 예상대로 동작하는지 확인하는 테스트
  • E2E 테스트 툴 Cypress: 강력한 E2E 테스트 도구 중 하나로, 사용이 간편하면서도 다양한 기능 제공.
    • 시각적으로 풍부한 테스트 결과를 제공하여 디버깅을 용이
  • 언제 E2E 테스트를 사용해야할까?
    • 사용자 경험이 중요한 웹 애플리케이션, 복잡한 비즈니스 프로세스를 갖는 애플리케이션, 다양한 통합 시스템을 가진 애플리케이션

1.2.4 Snapshot 테스트

1
// Component.test.js
2
import React from 'react'
3
import { render } from '@testing-library/react'
4
import '@testing-library/jest-dom'
5
import MyComponent from './Component'
6
7
test('renders correctly', () => {
8
const (asFragment) = render(<MyComponent />)
9
expect(asFragment()).toMatchSnapshot()
10
})
  • 스냅샷 테스트: 컴포넌트 렌더링 결과물이 예상대로 유지되고 있는지 확인하기 위한 테스트 방법.

    • 테스트시점에서 컴포넌트의 렌더링 결과를 캡처하고, 이후 테스트에서 캡처한 결과와 비교하여 변경사항을 감지
  • 스냅샷 툴 예시: Jest, React Testing Library

  • 언제 스냅샷 테스트를 사용해야할까?

    • 컴포넌트 렌더링이 자주 변경되는 프로젝트, 디자인 시스템을 사용하는 프로젝트, 다양한 환경에서 사용되는 프로젝트

1.2.5 성능 테스트

  • 성능 테스트: 소프트웨어 시스템이나 컴포넌트의 성능을 측정하고, 특정 부분에서 혹은 전체 시스템에서 발생할 수 있는 성능 이슈를 식별하는 프로세스
    • 성능 테스트는 주로 응답 시간, 처리량, 확장성, 안정성 등을 평가하여 사용자 경험을 향상시키고 소프트웨어의 안정성을 보장
  • 성능 테스트 툴 예시: Lighthouse, 크롬 개발자 도구의 네트워크 탭
  • 성능 테스트의 장점: 성능 최적화, 사용자 경험 향상, 비용 절감
  • 성능 테스트가 필요한 프로젝트?
    • 대규모 트래픽을 처리하는 서비스, 이미지나 동영상을 다루는 플랫폼, SPA(Single Page Application)등의
    • 현대적인 웹 애플리케이션등 모든 종류의 웹 애플리케이션에 적용될 수 있음

1.3 소프트웨어 테스트 7가지 원칙

ISTQB (International Software Testing Qualifications Board)의 기본 원칙들을 반영:

  1. 결함 존재를 보여주는 테스팅 (Testing shows presence of defects)
  2. 철저한 테스팅은 불가능 (Exhaustive testing is impossible)
  3. 조기 테스팅 (Early testing)
  4. 결함 클러스터링 (Defect clustering)
  5. 살충제 역설 (Pesticide paradox)
  6. 테스팅은 맥락에 따라 다름 (Testing is context dependent)
  7. 결함 부재의 오류 논리 (Absence-of-errors fallacy)

2. 테스트 주도 개발(TDD)

Test Driven Development(TDD)

  • 실제 코드를 작성하기 전에 테스트 코드를 먼저 작성
  • 테스트 코드를 작성한 후 그 테스트 코드를 Pass 할 수 있는 실제 코드를 작성

2.1 TDD 장점

  • TDD를 하면, 코드에 안정감이 부여
  • 개발하는데 많은 시간이 소요되는 부분은 디버깅 부분이라서, TDD를 사용하면 디버깅 시간이 줄어들고 개발 시간도 줄어듬
  • 소스 코드 하나하나를 더욱 신중하게 짤 수 있기 때문에 깨끗한 코드가 나올 확률이 높음