[Jest] 테스트 코드와 Jest란?

cabbage·2023년 2월 23일
0

기타

목록 보기
12/26

테스트 코드

작성한 코드가 제대로 동작하는지 확인하기 위해 작성하는 코드를 테스트 코드라고 한다.

업데이트 배포 과정에서 어떤 기능을 추가하였는데, 기존에 잘 동작하던 기능들이 잘 동작하지 않는 경우가 발생할 수 있다. 업데이트 배포 과정에서 이런 경우를 방지하려면 기존의 기능들과 새롭게 추가하려는 기능들까지 모두 처음부터 다시 테스트해야 한다.

하지만 배포를 할 때마다 모든 기능이 의도대로 잘 동작하는지를 확인하는 것은 어렵고 비효율적이다. 이런 경우 배포하기 전에 테스트 코드를 작성하여 기능을 추가할 때마다 기능 테스트를 진행하여 기능이 정상 동작하는지를 확인하는 것이 좋다.

결국 어떤 API 기능을 구현했다면 반드시 테스트 코드를 작성하여 기능이 정상 동작하는지를 확인해야 한다.

테스트의 종류

unit test - 단위 테스트

  • 애플리케이션에서 함수처럼 가장 작은 단위를 테스트하는 것

integration test - 통합 테스트

  • 유닛(단위)들을 모아서 함께 테스트하는 것
  • 서버 애플리케이션의 경우, 서버를 구성하는 요소들이 함께 잘 동작하는지를 테스트하는 것

e2e(end-to-end) test - 엔드투엔드 테스트

  • 유저 입장에서 유저의 모든 상황에 대해 올바르게 작동하는지 테스트하는 것
  • 유저의 예상 행동과 시나리오들로 테스트를 진행한다.

Jest

Jest는 페이스북에서 개발한, 자바스크립트 코드의 정확성을 테스트할 수 있도록 테스트 코드 작성을 도와주는 자바스크립트 테스트 프레임워크이다.

  • Node 환경이나 브라우저 환경에서 실행되는 자바스크립트의 테스트 코드를 작성하는 플랫폼을 제공한다.
  • npm 또는 yarn을 사용하는 Node.js 프로젝트에서 의존성 설치가 가능하다.

Jest 사용 이유

  • Jest 등장 이전에는 여러 자바스크립트 테스팅 라이브러리들을 조합해서 사용하였다.
    • Test Runner - Mocha, Jasmin
    • Test Matcher - Chai, Expect
    • Test Mock - Sinon, Testdouble
  • Jest는 Test Runner, Test Matcher, Test Mock 라이브러리를 모두 제공하는 테스트 프레임워크이다.
  • 때문에 Jest를 사용하면 여러 테스트 라이브러리들을 조합하지 않고 편리하게 코드를 테스트할 수 있다.
  • Jest의 테스트 코드는 직관적이고 문서화가 잘 되어 있다.
  • 여러 상황을 설정하고 그 상황에 맞는 로직에 대한 결과가 잘 나오는지를 자동 테스트한다.

Jest 파일 구조

NestJS 프로젝트를 생성하면 기본적으로 spec 이라는 이름이 들어간 파일을 Jest의 테스트 파일로 읽는다. (testRegex 확인)

app.controller.spec.ts 파일의 기본 구조는 아래와 같다.

  • describe - 여러 테스트를 모아 놓은 그룹 단위
  • beforeEach - test(it) 이전에 실행되는 부분으로 각각의 test(it)를 실행하기 전에 매번 실행하고 초기화를 반복한다.
  • test(it) - 하나의 테스트 단위

파일의 기본 구조에서 beforeAll도 존재하는데, beforeAll은 모든 test(it)를 실행하기 전에 딱 한번만 실행된다.

NestJS Jest 간단 사용법

NestJS 프로젝트에서 app.controller.ts의 기본 API에 대한 테스트 코드를 작성해서 테스팅하는 방법에 대해 알아보자.

기본 app.service.ts와 app.controller.ts 파일은 아래와 같다.

// app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}
// app.controller.ts
import { Controller, Get, Post } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService, // AppService 의존성 주입
  ) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

Jest로 테스트 코드를 작성하기 위해 spec 파일을 생성하고 아래와 같이 코드를 작성한다.

// aaa2.spec.ts

import { AppController } from './app.controller';
import { AppService } from './app.service';

describe('AppController', () => { // AppController 테스트 그룹
  let appService: AppService;
  let appController: AppController;

  beforeEach(() => { // test 시작 전 초기화
    appService = new AppService();
    appController = new AppController(appService);
  });

  describe('getHello', () => {
    it('이 테스트의 검증 결과는 Hello World를 리턴해야함!!!', () => { // 실제 테스트 실행
      expect(appController.getHello()).toBe('Hello World!');
    });
  });
});
  • describe에 테스트할 AppService, AppController를 위한 변수 선언
  • beforeEach에서 AppService, AppController 인스턴스를 생성
    • beforeEach는 각 테스트 시작 전마다 실행된다.

yarn test 명령어로 테스트 코드를 실행하여 API 기능 테스트를 진행한다.

  • PASS 문구를 통해 AppControllergetHello() API 기능이 잘 동작하는 것을 확인할 수 있다.

NestJS 테스팅 모듈

NestJS에서 제공하는 @nestjs/testing을 사용하면 테스트에 사용하는 종속성만 선언해서 모듈을 만들고 해당 모듈로 servicerepository를 가져올 수 있다. 위에서 살펴본 테스트 코드를 종속성을 선언해서 생성한 테스팅 모듈을 사용하는 방식으로 변경하면 아래와 같다.

// aaa3.spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';

describe('AppController', () => { // AppController 테스트 그룹
  let appController: AppController; // AppController를 가져오기 위한 변수

  beforeEach(async () => {
    // 테스트에 사용하는 의존성만 선언하여 테스팅 모듈 생성
    const app: TestingModule = await Test.createTestingModule({
      controllers: [AppController], // 1️⃣ AppController에
      providers: [AppService],      // 2️⃣ AppService 의존성 주입
    }).compile();

    appController = app.get<AppController>(AppController); // 테스팅 모듈을 통해 AppController 가져오기
  });

  describe('getHello', () => { // AppController의 getHello API 테스트 그룹
    it('이 테스트의 검증 결과는 Hello World를 리턴해야함!!!', () => { // AppController의 getHello API 테스트 실행
      expect(appController.getHello()).toBe('Hello World!');
    });
  });
});
  • beforeEach에서 app이라는 테스팅 모듈을 생성한다.
    • 테스팅 모듈에서 의존성을 주입하기 위해 controllersproviders에 각각 AppController와 AppService를 넣는다.
  • .get<AppController>(AppController)app 테스팅 모듈을 통해 AppController를 가져온다.
  • 가져온 AppControllerappController 변수에 할당해 테스팅 모듈에 연결한다.

참고

profile
캐비지 개발 블로그입니다. :)

0개의 댓글