6_ 테스트 주도 개발 (TDD)

1. 테스트 주도 개발이란?

개발을 할 때 바로 소스코드를 작성 하지 않고, 테스트 코드를 작성한다. 테스트 코드를 다 만든 후, 코드를 하나씩 통과 해 나가면서 개발하는 것.
물론, TDD 를 사용하면 개발 시간이 많이 걸린다.
But, 실제 만든 프로젝트를 유지보수 하는 시점에 가면 TDD로 개발한 것이 큰 효과를 발휘한다.
소스코드를 개발 하는 시간 보다 유지보수 하는 시간이 더 오래 걸린다.
But, TDD 로 개발을 하면 유지보수 하는 시간이 줄어든다.

이 강의 전체의 목표

  1. nodejs를 이용해서 API서버를 만든다.
  2. TDD 주도 개발 방법을 익힌다.

node에서는 TDD를 위해서 이 3가지 라이브러리를 사용한다.

mocha, should, superTest

2. Mocha

• mochajs.org : 설치하는 방법 ~ 시작하는 방법까지 사용법!!
• 모카(mocha)는 테스트 코드를 돌려주는 테스트 러너
• 모카(mocha)의 2가지 part
-> 1) 테스트 수트: 테스트 코드를 작성 할 때, 테스트 환경을 꾸며주는 것이며 이는 describe() 함수로 구현한다
-> 2) 테스트 케이스: 실제 테스트를 만드는 역할. 모카에서는 it() 함수로 테스트 코드를 구현한다

1) 테스트 할 코드 == utils.js / utils.js 를 모듈로 사용하여 테스트 한다.

< utils.js >

function capitialize(str) {
  return str;
}


module.exports = {
  capitialize: capitialize
}

2) utils.spec.js

spec.js 파일은 전부 test 코드라고 보면 된다.

specification(명세) ; 보통 테스트 코드가 그 테스트 대상의 명세서, 요구사항 이다

< utils.spec.js >

  • describe(); 테스트 코드 작성
describe('utils.js모듈의 capitalize()함수는 ', () => {
  it('문자열의 첫번째 문자를 대문자로 반환한다.', () => {
  })
}) 

1) describe() : 테스트 환경을 만듬 /test 대상을 서술식으로 표현함.
2) 첫번째 파라미터 : 어떤 테스트 케이스인지 설명하는 문자열을 넣어줌.
3) 두번째 파라미터 : 콜백 / 실제 테스트할 테스트 코드 작성

  • 테스트 할 모듈 가져옴.
const utils = require("./utils.js/capitialize")

3) test 코드 작성.

// specification(명세) ; 보통 테스트 코드가 그 테스트 대상의 명세서, 요구사항 이다

const utils = require('./utils')
const assert = require('assert') // 맞냐 안맞냐 검증하는 모듈 ( node의 기본 모듈 ) 

// 테스트 환경을 만듬. 
describe('utils.js모듈의 capitalize()함수는 ', () => {
  it('문자열의 첫번째 문자를 대문자로 반환한다.', () => {
    // 두번째 파라미터 : 콜백 / 실제 테스트할 테스트 코드 작성
    const result = utils.capitalize('hello')
    assert.equal(result, 'Hello') // 두 인자가 같은지 검증
  })
  // 첫번째 파라미터 : 어떤 테스트 케이스인지 설명하는 문자열을 넣어줌.

}) // test 대상을 서술식으로 표현함.

3. Should

Node 공식 문서 : "Test 에서는 노드 assert 말고 서드파티 라이브러리를 사용하라"
• 실제 test 코드에서 슈드(should)는 검증(assertion) 라이브러리로 사용 된다
• 가독성 높은 테스트 코드를 만들 수 있다
Should.js 문서 링크: https://github.com/tj/should.js/
( 공식 문서보다는 이 깃헙 페이지가 보기가 더 좋아 추천함. )

1) should 모듈 설치

$ npm install should --save -dev

2) should 로 코드 변경.

const utils = require('./utils')
const should = require('should') // 검증 3rdparty 모듈 : should

// 테스트 환경을 만듬. 
describe('utils.js모듈의 capitalize()함수는 ', () => {
  it('문자열의 첫번째 문자를 대문자로 반환한다.', () => {
    const result = utils.capitalize('hello')
    result.should.be.equal('Hello');
    // 아까보다 더 영어문장을 읽는 느낌
    // 즉, 테스트 코드의 가독성이 높아짐. 
  })

})

3) 결과 화면.

4. Super Test

  • 테스트 종류 2가지.
    • 단위 테스트: 함수의 기능 테스트 : Mocha
    • 통합 테스트: API의 기능 테스트 : Super Test

• 슈퍼 테스트는 익스프레스 통합 테스트용 라이브러리다
• 내부적으로 익스프레스 서버를 구동시켜 실제 요청을 보낸
뒤 결과를 검증한다
• 슈퍼테스트 코드 저장소 링크: https://github.com/visionmedia/supertest

문서의 Example 분석.

https://github.com/visionmedia/supertest

< Example 코드 >

const request = require('supertest');
const express = require('express');

const app = express();

app.get('/user', function(req, res) {
  res.status(200).json({ name: 'john' });
  // res객체의 status Code : 200 , json객체의 name를 'john'으로 주겠다. 
  
});

request(app) // request 모듈 : supertTest의 모듈!
// request 모듈 안에 위에서 만든 express객체를 넣어주면, superTest는 내부적으로 서버를 구동한다. 

	// 시나리오를 구성
    // get 메서드의 /user 경로를 가지고 있는 request를 서버로 날린다. 
  .get('/user')
  	// 이 밑에서부터 겁증 
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
  });

첫 API를 테스트 코드로 만들기.

• 성공
• 유저 객체를 담은 배열로 응답한다
• 최대 limit 갯수만큼 응답한다
• 실패
• limit이 숫자형이 아니면 400을 응답한다
• offset이 숫자형이 아니면 400을 응답한다

1) index.spec.js 파일 생성

: index.js 파일을 테스트하는 테스트 코드 파일을 생성한다.

2) index 모듈 가져오기.

< index. spec.js >

const app = require('./index') // 테스트 하는 파일

3) index.js에서 모듈 내보내기.

< index.js >

// 지금까지는 객체를 할당하였으나, 변수를 할당하여도 괜찮음!
module.exports = app;

4) superTest 모듈 사용.

<index.spec.js > 모듈 가져오기.

const request = require('supertest') // supertest 모듈 가져옴

< superTest 모듈 설치 >

$ npm i supertest --save -dev

5) index.spec.js 에 테스트 코드 작성

const app = require('./index') // 테스트 하는 파일
const request = require('supertest') // supertest 모듈 가져옴



// test 코드 작성
// test suit : describe
describe('GET /users는', () => {
  //test case : it
  it('...', (done) => { // 비동기의 해결로, 콜백함수에 파라미터로 done이라는 콜백함수를 넣어준다. 
    // it의 첫번째 인자 : test 코드 설명
    // 콜백 : supersTest 실행 / 실제 test 코드
    request(app)
      .get('/users') // get으로 요청을 실제 보냄. 
      .end((err, res) => { // end 콜백함수로 결과 확인. 
        console.log(res.body) // 실제 데이터 - 배열이 찍히는지. 
        done() // done이라는  콜백함수 호출
      })
  })
})

* 참고자료 : index.js


const express = require('express')
const app = express()
const morgan = require('morgan')
const port = 3000
const users = [
  { id: 1, name: 'bek' },
  { id: 2, name: 'alice' },
  { id: 3, name: 'chris' },
]
// DB가 없으므로, 일단 배열을 넣어봄. 

app.use(morgan('dev'))

app.get('/users', (req, res) => {
  res.json(users)
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

// 지금까지는 객체를 할당하였으나, 변수를 할당하여도 괜찮음!
module.exports = app;

6) 결과 화면

좋은 웹페이지 즐겨찾기