TDD 방법론과 JS의 Jest 사용하기

수현·2023년 10월 29일
0

Tools

목록 보기
6/6

TDD란 Test Driven Development의 약자로 '테스트 주도 개발'이다. 반복 테스트를 이용한 소프트웨어 방법론으로 즉, 테스트 코드를 작성하고 이에 따라 개발을 진행하고, 다시 테스트 코드를 작성하는 것을 반복한다.

먼저 테스트에 대해 알아보고 TDD는 어떻게 진행되는지 알아보자!

소프트웨어 테스트

소프트웨어 테스트란 다음과 같다.

  • 프로그램 테스트는 오류가 존재함을 보일 수 있지만, 오류가 없음을 증명할 수 없다.
  • 테스트는 프로그램이나 시스템 자신이 해야 되는 일을 수행하는 믿음을 주는 과정이다.
  • 컴퓨터 소프트웨어를 실행하여 그 결과가 올바른지 판단하는 과정이다.
  • 에러를 발견하는 목적으로 프로그램을 실행하는 과정이다.
  • 테스트는 소프트웨어 품질을 측정하고 개선하기 위한 테스트웨어를 공학해서 사용하고 유지하기 위한, 또 다른 라이프사이클 프로세스이다.

소프트웨어 테스트 분류

  • 단위 테스트 Unit test
    : 응용 프로그램이 설계된 대로 작동하는지 확인하는 것으로 unit은 소프트웨어의 최소단위, 보통 함수를 가리킴

  • 통합 테스트 Integration test
    : 단위 기능이 합쳐진 기능에 대한 테스트로 모듈/기능 간의 인터페이스 결함을 찾기 위해 설계

  • 시스템 테스트 System test
    : 위 내용보다 더 큰 개념, 전체 시스템에 대한 동작 테스트

  • 인수 테스트 Acceptance Test
    : 시스템이 릴리스 준비가 되었는지 확인하기 위한, 고객이 ok할 수 있는지 판단하기 위한 테스트

그리고 이와 별개로 아래 두가지 테스트가 있다.

  • UI test : FE나 모바일 분야에서 UI 기능 단위로 진행하는 테스트. 보통 Unit test와 system test 사이라고 볼 수 있다.
  • E2E test : End-to-end 테스트. 이 역시 UI 테스트와 같이 말하는 경우도 있고, 전체 시스템 관점에서의 테스트로 보는 경우도 있다.

이 중 중요한 단위 테스트에 대해 더 알아보겠다.

단위 테스트 Unit Test

단위 테스트는 빠르게 수행하고, 격리된 방식(다른 테스트에 영향을 주지 않아야 함)으로, 작은 코드 조각(단위)을 검증하고, 자동화된 진짜 코드이다.

  • 테스트 환경

    • 화이트박스 테스트 : 코드 내부를 들여다보고 테스트(구문/조건/분기 커버리지)하는 것

    • 블랙박스 테스트(권장) : 내부를 모르는 상태에서 입/출력 테스트를 하는 것, 경계값 분석, 동등 클래스 분할 테스트 등

  • A-A-A 테스트 (Arrange-Act-Assert)

    • Arrange : 테스트 대상을 검증하기 위해 필요한 것 준비(가짜 데이터, 객체 생성, API 호출 등)
    • Act : 테스트 대상 코드를 실행
    • Assert(단언) : 실행한 코드가 기대했던 예상대로 동작하는지 확인
  • 테스트해야 하는 것!! Right - BICEP

    • Right : 결과가 올바른가
    • B(boundary) : 모든 경계 조건이 correct한가
    • I(inverse) : 역관계를 확인할 수 있나
    • C(cross-check) : 다른 수단을 사용해서 결과를 교차 확인 할 수 있나 ex) sort를 버블정렬, 선택정렬로 따로 했을 때 결과 확인해보기
    • E(error condition) : 에러 조건을 강제로 만들 수 있나
    • P(performance) : 성능 특성이 한도 내에 있나
  • 좋은 테스트란? A-TRIP

    • Automatic : 단위 테스트는 실행과 결과에 대한 확인이 자동화되어야 한다.
    • Through : 해당 기능의 문제가 될 경우의 수를 모두 철저하게 테스트한다.
    • Repeatable : 순서 상관없이 반복 실행 가능하며, 반복해서 같은 결과가 나와야 한다.
    • Independent : 다른 테스트 / 외부 환경에 독립적이어야 한다.
    • Professional : 테스트 코드도 진짜 코드이니 전문적으로 잘 짜기

TDD 개발 주기

  1. Red 단계 : 실패하는 테스트 코드를 먼저 작성한다.
  2. Green 단계 : 테스트 코드를 성공시키기 위한 실제 코드(프로덕션 코드)를 작성한다.
  3. Yellow 단계 : 중복 코드 제거, 일반화 등의 리팩토링을 수행한다.

중요한 것은 실패하는 테스트 코드를 먼저 작성하고, 이에 맞게 실제 프로덕션 코드를 작성한다는 것이다!
이렇게 했을 경우 어떤 장단점이 있을까?

TDD의 장점

TDD로 개발을 했을 때 기존에 본인이 하던 개발 방식을 바꿔야 하고, 중간중간 테스트 코드를 작성하는 시간이 들어 생산성이 떨어진다고 생각할 수 있다. 그럼에도 불구하고 TDD 방법론을 사용해야 하는 이유를 알아보자.

  1. 디버깅 시간 단축
    유닛 테스트의 가장 큰 이점으로, 어떤 부분에서 에러가 발생했는지 바로 파악할 수 있다.

  2. 깔끔한 코드 작성
    테스트 코드를 작성 한 후 실제 코드를 작성하므로 테스트 코드에 맞게 깔끔하게 작성할 수 있다.

  3. 불안정성 개선
    작성한 코드를 지속적으로 테스트함으로써 코드가 가지는 불안정성을 개선할 수 있다.

  4. 재설계 시간 단축
    테스트 코드를 먼저 작성하기 때문에 개발자가 지금 무엇을 해야하는지 분명히 정의하고 개발을 시작하게 된다.

  5. 추가 구현 용이
    개발이 완료된 소프트웨어에 어떤 기능을 추가할 때 추가하는 기능이 기존 코드에 어떤 영향을 미칠지 모르지만, TDD의 경우에 유닛 테스트를 자동으로 실행하므로 시간을 단축시킬 수 있다.

TDD 방식을 사용했을 때와 그렇지 않을 때의 effort에 대한 그래프이다. TDD 방식이 처음에는 노력이 더 필요하지만 시간이 지나 프로젝트가 진행되었을 때는 TDD 방식이 더 효율적이다. 각자의 상황에 맞게 TDD를 사용하면 되겠다.


Jest 사용하기

Jest는 페이스북에서 만든 테스팅 라이브러리이다. 사용법을 알아보자!

Jest 설치 및 세팅

  1. jest 설치 및 setting

    npm install --save-dev jest
    // package.json
    {
      "scripts": {
        "test": "jest"
      }
    }

    위와 같이 jest를 dev dependencies로 설치하고, package.json test 설정을 해준다.

  2. babel 설치

    npm install --save-dev babel-jest @babel/core @babel/preset-env

    Babel은 JavaScript 코드의 변환 및 호환성을 향상시키는 도구로 JavaScript 버전 간 호환성을 유지하고 코드를 변환하는 과정에서 최적화하는 등의 기능을 한다. 이러한 babel과 관련된 모듈을 설치한다.

  3. babel config 설정

    // babel.config.json
    {
        "presets": [
            ["@babel/preset-env", { "targets": { "node": "current" } }],
        ]
    }

    babel.config.json 파일을 만들고 위와 같이 설정 코드를 입력한다.

  4. typescript 관련 설정

    npm install --save-dev @babel/preset-typescript
    // babel.config.json
    {
        "presets": [
            ["@babel/preset-env", { "targets": { "node": "current" } }],
            "@babel/preset-typescript",
        ]
    }

    나는 프로젝트에 typescript를 사용하고 있어 babel의 typescript 관련 모듈과 세팅을 추가해주었다.

    npm install --save-dev @jest/globals 

    그리고 typescript로 작성된 파일에 jest의 APIs를 사용하기 위해 위의 모듈을 설치해주었다. 사용할 때는 다음과 같이 import하여 사용할 수 있다.

    import {describe, expect, test} from '@jest/globals';

Jest 사용 방법

테스트 코드를 작성할 파일은 file_name.test.js, file_name.test.ts로 네이밍을 한 후 원하는 테스트 코드를 작성한다. 이후 테스트할 때 npm test 명령어로 모든 테스트 파일을 실행할 수 있다.

아래에서 Matcher를 이용하여 테스트 코드를 작성하는 방법을 알아보자.

기본 Macher

  • 기본 문법

    test(*'explanation'*, () => {
      expect(*'input'*).Matcher(*'output'*);
    });
    
    // describe를 사용하면 안에 test 함수를 여러 개 묶을 수 있다.
    describe('sign up', () => {
        test('adds 1 + 2 to equal 3', () => {
            expect(isUniqueUser('sw92522@naver.com')).toBe(3);
        });
    });
  • toBe() : 정확하게 동일한지(주소값) 확인

  • toEqual() : object의 값만 같은지 확인 ⇒ 약간 js의 ‘===’와 ‘==’의 느낌

    test("object lastDirectory", () => {
      expect(path.lastDirectory).toBe("day12");
    })
    
    test("object components", () => {
      expect(path.components).toEqual(["/", "home", "user", "boost", "camp", "challenge", "day12", "problem.md"]);
    })

Truthiness

  • not : matcher 앞에 사용 가능 ex) not.toBe(), .not.toEqual()

  • toBeNull : matches only null

  • toBeUndefined : matches only undefined

  • toBeDefined : is the opposite of toBeUndefined

  • toBeTruthy : matches anything that an if statement treats as true

  • toBeFalsy : matches anything that an if statement treats as false

Number

  • toBeGreaterThan

  • toBeGreaterThanOrEqual

  • toBeLessThan

  • toBeLessThanOrEqual

Strings

  • toMatch : 정규식과 매치되는지 확인

    test('but there is a "stop" in Christoph', () => {
      expect('Christoph').toMatch(/stop/);
    });

Arrays and iterables

  • toContain : array or iterable contains에 특정 아이템 포함여부 확인

    const shoppingList = [
      'diapers',
      'kleenex',
      'trash bags',
      'paper towels',
      'milk',
    ];
    
    test('the shopping list has milk on it', () => {
      expect(shoppingList).toContain('milk');
      expect(new Set(shoppingList)).toContain('milk');
    });

Exceptions

  • toThrow : 예외 발생 확인
    test("create object include special letters", () => {
      expect(() => new Path('C:\\home\\user\\boost\\camp*\\day8\\문제.md')).toThrow();
    })

참고 자료

https://wooaoe.tistory.com/33
https://media.fastcampus.co.kr/knowledge/dev/tdd/
https://inpa.tistory.com/entry/QA-%F0%9F%93%9A-TDD-%EB%B0%A9%EB%B2%95%EB%A1%A0-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A3%BC%EB%8F%84-%EA%B0%9C%EB%B0%9C
https://semaphoreci.com/blog/economics-of-tdd
https://jestjs.io/docs/getting-started

profile
실패와 성장을 기록합니다 🎞️

0개의 댓글