ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 기초
    테스팅/JEST 2019. 10. 18. 14:47

    JEST는 자바스크립트로 작성된 프로젝트의 테스트 자동화를 위해 사용되는 테스팅 프레임워크다.

    React를 만든 페이스북 팀에서 Jasmine 기반으로 만들었으며, JEST는 프레임워크에 상관없이 자바스크립트 기반 언어라면 모두 사용할 수 있다는 장점이 있다.

    * Jasmine : 테스팅 프레임워크다.

    https://en.wikipedia.org/wiki/Jasmine_(JavaScript_testing_framework)

     

    Jasmine (JavaScript testing framework) - Wikipedia

    Jasmine is an open source testing framework for JavaScript.[4] It aims to run on any JavaScript-enabled platform, to not intrude on the application nor the IDE, and to have easy-to-read syntax. It is heavily influenced by other unit testing frameworks, suc

    en.wikipedia.org

     

    * JEST : Jasmine 기반으로 만들어진 테스팅 프레임워크다.

    https://jestjs.io/docs/en/getting-started.html

     

    Jest · 🃏 Delightful JavaScript Testing

    🃏 Delightful JavaScript Testing

    jestjs.io

     

     

    * 해당 환경은 댜~충 Node.js 기반으로 진행합니다.

     

     

    1. 프로젝트 구성

    1. 프로젝트 폴더를 하나 만들고 npm init으로 자바스크립트 프로젝트 구성을 해주자.

     

    2. jest npm 모듈을 다운로드 받자. 이 때 VSCode의 자동완성을 위해 @types/jest도 설치하자.

     

    2. package.json을 열고 scripts의 test 항목을 jest로 작성해주자.

     

    이제 npm test를 터미널에 입력하면 JEST가 테스트 파일들을 읽어들여 테스트를 진행하게 될 것 이다.

     

     

    2. 테스트 코드 작성 (Hello World!)

    1. 테스트 성공 케이스

    1. app폴더를 하나 만들고 myModule.js 라는 이름의 파일을 하나 만들고 아래의 코드를 작성하자.

    exports.sum = (a, b) => {
        return a + b;
    }

     

    2. 해당 모듈을 테스트하기 위해 test 폴더를 하나 만들고 myModule.test.js 라는 이름의 파일을 하나 만들고 아래의 테스트 코드를 작성하자.

    const myModule = require('../app/sum')
    
    test('5 plus 2', () => {
        expect(myModule.sum(5, 2)).toBe(7);
    })

     

    test() 함수는 새로운 테스트 케이스를 만드는 함수다.

    expect().toBe()는 다음과 같은 의미다.

    "myModule.sum(5,2) 7일 것이다."

    즉 expect()는 조사 역할을 하고, toBe()는 to부정사다. 

     

    toBe()는 expect()의 조건이 내가 생각하는 값이 맞는지 검증하는 기능이다.

    이러한 기능을 하는 함수들을 matchers라고 부르는데, matchers는 특정한 값이 어떠한 조건을 만족하는지, 어떠한 함수가 실행이 되었는지, 에러가 발생했는지 등을 확인하기 위해 사용하는 기능이다.

     

     

    3. 작성한 테스트 코드를 실행시켜 결과를 확인해보자. 

    터미널에 npm test를 입력한다.

    테스트에 성공하게 되면 PASS 문구가 나타난다.

     

    2. 테스트 실패 케이스

    1. '테스트 성공 케이스 - 2'에서 진행한 테스트 코드를 수정하여 테스트 실패를 유도해보자.

    const myModule = require('../app/sum')
    
    test('5 plus 2', () => {
        expect(myModule.sum(5, 2)).toBe(14);
    })

     

    '5 더하기 2는 14일 것이다.'라는 시나리오를 작성하자.

     

     

    2. 다시 한번 test를 진행해보자.

    테스트에 실패하게 되면 FAIL 문구가 나타나며 에러가 발생된 라인의 문제되는 위치를 알려주며, npm ERR를 발생시킨다.

     

     

    3. describe()

    describe()은 데스트를 그룹화(범주)하는 기능을 한다.

    예를 들어 게시판에 관련된 기능을 포함하는 모듈이 있다고 한다면 우리가 테스트 케이스를 작성한다고 가정해보자.

    1. 게시판 기능

    1-1. 게시판 목록 조회

    1-2. 게시판 글 상세보기

    1-3. 게시판 댓글 작성

    1-4. 게시판 글쓰기

    ...

     

    이와 같이 사람이라면 부모-자식 형식으로 묶어서 정리하여 관리하는 특성이 있다.

    테스트 또한 개별적으로 테스트 케이스 제목만 써서 구분하는 것보다 하나의 범주로 묶어서 관리하는 것이 더 편할 것이다.

    적어도 내가 QA팀에서 직무를 맡아 일을 했을 시에는 그랬다.

    테스트 케이스 예시

     

    우리가 테스트 시나리오를 위와 같이 정리하듯 테스트 코드도 최소한 범주로 묶을 수가 있다.

     

    1. myModule 코드를 다음과 같이 작성하자.

    exports.sum = (a, b) => {
        return a + b;
    }
    
    exports.minus = (a, b) => {
        return a - b;
    }
    
    exports.total = (numbers) => {
        let result = 0;
    
        numbers.forEach(n => {
            result += n;
        });
    
        return result;
    }

     

    기존에 두 수를 더하는 sum 기능 외에 두 수를 빼는 minus 기능, 숫자 배열의 총합을 구하는 total 기능이 추가되었다.

    이와 같은 기능들은 모두 'myModule'에 관련된 기능이다.

     

    그럼 이를 'myModule'이라는 범주로 묶어서 테스트를 해보자.

     

     

    2. myModule.test.js를 열고 아래와 같이 코드를 작성해보자.

    describe('myModule 검증 테스트 케이스', () => {
        test('[sum() 함수 검증] 10 + 5 = 15이다.', () => {
            expect(myModule.sum(10, 5)).toBe(15);
        });
    
        test('[minus() 함수 검증] 20 - 2 = 18이다.', () => {
            expect(myModule.minus(20, 2)).toBe(18);
        });
    
        test('[total() 함수 검증] [10, 20, 30, 40, 50]의 모든 합산은 150이다.', () => {
            expect(myModule.total([10, 20, 30, 40, 50])).toBe(150);
        });
    });

     

    describe으로 부모를 만들고, 그 안에 자식 케이스를 추가하여 테스트 코드를 작성할 수가 있다.

     

    이를 실행해보자.

     

     

    테스트 결과 또한 다음과 같은 형식으로 표현된다.

    • (부모) 테스트 범주 제목
      • (자식) 1번 테스트 케이스
      • (자식) 2번 테스트 케이스
      • (자식) 3번 테스트 케이스

     

     

    4. 테스트 코드가 필요한 이유

    그래서 테스트 코드는 왜 필요한가?

    우린 지금까지 이 글을 통해 기능을 만들고, 테스트를 진행하여 성공하는 사례를 경험했다.

     

    만약 기존의 기능을 결과는 동일하되 코드의 처리 방식을 변경한다고 가정해보자.

    우리는 수정한 코드가 동일한 결과를 도출할 것이라고 확신할 수 있는가?

    직접 코드를 돌려보고 결과를 보지 않는 이상 알 수가 없을 것이다.

     

    직접 그 상황을 경험해보자.

     

    1. myMoudule.js의 total 함수의 코드를 아래와 같이 리팩토링하자.

    exports.total = (numbers) => {
        return numbers.reduce((num1, num2) => num1 + num2);
    }

     

    배열의 모든 값을 합산하여 리턴하는 기능은 동일하다.

    reduce() 메소드를 이용해 배열 각각의 요소들을 더하고 그 결과를 리턴하는 코드다.

    과연 이 코드가 정상적으로 돌아갈 수 있을까?

     

    이를 직접 테스트해보는 것이다.

     

     

    2. 다시 터미널에서 npm test를 입력하고 기존의 테스트 코드를 돌려보자.

     

    우린 테스트 코드를 수정하지 않았음에도 동일한 성공 케이스를 확인할 수 있다.

     

     

    위와 같이 동일한 결과를 도출하는 기능을 수정하여 테스트 검증하는 것은 다양한 테스트 방식 중 하나다.

     

    테스트 코드는 분명 필요하다.

     

    특히 리팩토링 측면에서 개발자를 편하게 해주니까.

     

    만약 위와 같이 JEST로 테스트 코드를 짜지 않았다면 해당 기능을 어떻게 검증할 수 있을까?

     

    평소와 같았다면 우린 다음과 같은 스텝들을 진행하여 검증했을 것이다.

    1. 코드 리팩토링
    2. 서버 실행
    3. 해당 URL에 대한 웹 페이지를 접속 
    4. 해당 기능이 작동하는 이벤트를 발생 (혹은 백엔드의 경우 Post Man같은 통신 프로그램을 이용하여 응답 데이터 확인)
    5. 5. 결과 확인

     

    최소한 4~5단계가 필요했다.

    여기서 만약 로그인이 필요한 기능인 경우엔?

    로그인을 하는 과정이 필요하고, 이후 스텝을 진행해야 한다.

     

    물론 간단한 기능일 경우 클릭 몇 번으로 결과를 확인할 수 있으니 몇십 줄이나 되는 테스트 코드를 작성하는 것 보다 더 편할 수도 있다.

     

    하지만 미래에 내가 만든 코드가 유지될 지, 변경될 지는 추측할 수가 없다.

     

    테스트 코드 미리 만들어놓으면 편하잖아.

    '테스팅 > JEST' 카테고리의 다른 글

    Mock Return Value  (0) 2019.10.29
    Mock Property  (0) 2019.10.29
    Mock Function  (0) 2019.10.29
    expect.anything()  (1) 2019.10.21
    expect.extend()  (0) 2019.10.18
Designed by Tistory.