[MGS 3기 - 37일차] 어플리케이션 테스트

박철연·2022년 6월 7일
0

MGS STFE 3기

목록 보기
34/35
post-thumbnail

지난 토요일과 이번 주에 걸쳐서 학습한 테스팅에 대한 부분을 요약했습니다. 기본적인 애플리케이션 테스트의 개념을 살펴보고, 테스트 도구와 기법도 정리했습니다.

어플리케이션 테스트

테스트의 개념

컴퓨터 공학에서 말하는 테스트는, 특정 조건을 조성한 뒤 시스템 또는 구성 요소가 실행되고, 결과가 관찰 또는 기록되며, 평가가 이루어지는 일련의 활동을 뜻합니다.

이러한 테스트를 시행하는 데에는 여러 가지 이유가 있습니다.

먼저, 이번 작업이 잘 작동하는가를 검증하기 위해서입니다. 어찌보면 당연한 부분입니다.

지금까지 작업한 결과물이 개발자들의 의도에 부합하는지, 프로젝트의 요구 사항을 충족하는 지 확인하기 위해서입니다.

또한, 기존 작업에 대한 side effect 검사를 하기 위해서이기도 합니다. 기존 작업에 대한 리뷰를 진행한다고 볼 수도 있겠습니다.

마지막으로, 테스트를 거치면서 누적된 데이터와 가이드라인은 리뷰어/후임 개발자를 위한 지침으로 작용할 수 있습니다.

Unit Test (단위 테스트)

테스트에는 프로세스의 진행 정도에 따라 다양한 종류의 테스트가 존재합니다. 그 중에서도 이번 글에서는 Unit Test(단위 테스트)와 Integration Test (통합 테스트)에 대해서 알아보겠습니다.

Unit Test(단위 테스트)는 함수나 컴포넌트 단위의 테스트를 작성하여 작은 단위 내에서 테스트를 진행하는 것입니다.

지금까지 학습해 온 것과 같이, 오늘날의 웹 개발은 컴포넌트, 함수 단위로 프로그래밍하는 경우가 많은데, 이를 그대로 테스팅에 도입하여, 독립적인 기능/동작을 시험해보기 위함입니다.

props 등 다른 컴포넌트의 영향을 받는 경우 직접 주입하여 테스트를 진행합니다. 함수 역시 외부 인자가 필요하다면 직접 인자를 주입하는 식으로 진행할 수 있습니다.

const ShowName = (props) => { 
  return <div>{props.name}</div> 

위와 같은 컴포넌트가 있다면, "ShowName컴포넌트에 { name: 'asdf'} 를 prop으로 넘기면 'asdf'가 렌더되어야 한다"로 테스트를 작성하면 되는 것입니다.

Integration Test (통합 테스트)

Integration Test (통합 테스트)는 단위모듈이 결합되어있는 형태를 테스트합니다. 위에서 언급한 단위 테스트들이 끝나면 해당 단위들이 잘 결합되는지 테스트하는 것입니다.

const ShowName = (props) => { 
  return <div>{props.name}</div> 
} 
const Show = (props) => ( 
  <ShowName name={props.name}> 

ShowName은 단위테스트가 이미 완료되었기 때문에, "Show컴포넌트에 { name: 'asdf'} 를 prop으로 넘기면 ShowName name={props.name} 이 렌더되어야 한다"를 테스트로 작성할 수 있겠습니다.

Jest

Jest 소개

테스팅의 이론적인 부분에 대해서 살펴보았으니, 실제 테스팅에 사용되는 도구에 대해 알아보아야 할 것입니다.

Jest는 유닛/통합 테스트 작성 및 실행, 결과출력을 도와주는 테스팅 프레임워크로, 오늘날 웹 개발 테스팅에 있어서 광범위하게 사용되고 있습니다.

Jest는 간단하게 npm 명령어로 설치 가능합니다.

$ npm install --save-dev jest

또한 React 프로젝트를 구축할 때는 보통 CRA를 많이 사용하는데, CRA로 프로젝트를 구성하면 Jest가 같이 설치된 채로 프로젝트가 구성됩니다.

CRA 작업 후, package.json의 scripts 부분을 확인하면 Jest 테스팅과 관련된 명령어도 확인할 수 있습니다.

Jest 문법 알아보기

이제 실제 코드를 참고하여 Jest 문법들을 간략하게 알아보겠습니다. Jest의 대표적인 문법은 expect입니다.

expect는 영어 단어 뜻 그대로, 개발자가 의도하는 결과가 나오는지 확인하기 위한 문법입니다.

expect 안에 무언가를 넣으면 다양한 메소드 이용 가능하기 때문에, 유연한 테스팅 코드를 작성할 수 있습니다.

test('1 + 3은 4이다', () => { 
  expect(1 + 3).toBe(4); 

위의 예시에서는 expect와 toBe, test 등의 다양한 함수가 사용된 것을 확인할 수 있을 것입니다.

CRA 프로젝트에서는 기본적으로 테스팅과 관련된 babel 설정까지 모두 제공해주기 때문에, 위 함수들을 import 작업없이도 자유롭게 사용할 수 있습니다.

react-testing-library

CRA에서는 Jest와 함께 테스팅을 더욱 효율적으로 할 수 있도록 react-testing-library를 제공합니다.

이와 Jest 문법을 조화하여 상황에 따라 필요한 테스트 코드를 작성할 수 있게 됩니다.

해당 라이브러리에서는 react 컴포넌트를 테스트할 수 있도록 renderer등 다양한 함수 제공합니다.

당연하게도 CRA에서는 기본적으로 제공되는 라이브러리입니다.

querybyText

render를 통해 리액트 컴포넌트를 렌더(실행)하는 메서드입니다.

실제로 컴포넌트를 그리는 것이 아닌 javascript 객체 상태에서 함수를 테스트하는 작업입니다.

참고로 render는 react-testing-library의 함수이므로 import 문법으로 들여오기를 해주어야 합니다.

import React from 'react'; 
import { render } from '@testing-library/react'; 
import App from './App'; 
test('App이 render된 경우 Hello World가 출력되어야한다', () => { 
  const { queryByText } = render(<App />); 
  const helloWorld = queryByText('Hello World'); 
  expect(helloWorld).toBeInTheDocument(); 
});

container

container는 render를 통해 생성된 트리의 최상위(부모) DOM을 가리킵니다.

일반적으로 자바스크립트에서 다루는 HTMLElement 객체이므로, querySelector 등의 메소드 사용 가능합니다.

test('App이 render된 경우 div가 출력되어야 한다', () => {
	const { contaier } = render(<App />);
    const div = container.querySelector('div');
  	expect(div).toBeInTheDocument();
})

Cypress

E2E Test

E2E Test는 End to End 테스트를 뜻하는 것으로, 일반적인 소프트웨어/어플리케이션의 동작을 시작부터 끝까지 돌면서 완전체 테스트를 진행하는 것입니다.

실제 브라우저에 페이지를 렌더하고, 사용자의 입장에서 어떤 결과가 나오는지를 검증하는 과정이라고 볼 수 있습니다.

이러한 E2E Test를 사용할 때에는 다양한 라이브러리들의 도움을 받는 경우가 많습니다. 그 중에서도, E2E Test에 가장 널리 사용되는 Cypress를 한 번 알아보겠습니다.

Cypress의 주요 문법

visit

visit은 현재 프로젝트가 개발 서버로 실행이 되었을 때, 특정 url 경로로 진입하는지를 체크하기 위한 문법입니다.

it('successfully loads', () => { 
  cy.visit('http://localhost:3000'); 

cypress의 경우도 jest와 마찬가지로, CRA 프로젝트가 관련 babel 설정을 미리 제공합니다. 따라서 별도의 import 문법을 필요없을 것입니다.

또한 cypress로 작성한 모든 테스팅들은 npm run cypress를 통해 확인할 수 있습니다.

get

get은 렌더링 될 특정 컴포넌트/엘리먼트를 가져오는 문법입니다. 아래의 예시 코드를 참고해 보세요.

it('has root div', () => { 
  cy.get('#root').should('exist'); 
  cy.get('#root').contains('Hello'); 
}) 
profile
Frontend Developer

0개의 댓글