TDD?? JEST?? 뭔데?

0
post-thumbnail

1. TDD(Test Driven Development)

  • 테스트 주도 개발이라고도 한다.
  • 기능을 업그레이드 할때마다 다른 것도 테스트를 다시 해봐야한다.
  • 이런 문제를 해결하기 위해 테스트 코드가 필요하다.(검증코드)
  • 각 기능마다 테스트 코드가 필요하다 => 단점으로는 시간이 많이 걸린다. 왜냐하면, 기능 만들때 마다 각각의 테스트 코드를 만들어야 하기 때문이다.
  • 오픈예정 : 기능이 모두 다 작동하는지 확인을 해봐야하기 때문에 기능을 다 뽑아도 된다. 만약 오픈을 하게 되면, 오픈을 알리는 동안에 개발자들은 추가기능을 업그레이드하고, 기존 기능에 대해서 테스트코드를 작성한다.
  • 운영중 : 운영 중에는 테스트코드를 만들면서 테스트를 진행해야 한다. 그래서, 시간이 오래 걸린다.
  • 결국은 업그레이드 하는 요소가 기존 기능에 영향을 끼칠수 있기 때문에 테스트코드가 필요하다.

2. 테스트 종류

  • 단위테스트 : 버튼 클릭과 같은 개별 기능
  • 통합테스트 : 여러기능 한꺼번에
  • E2E테스트 : 접속해서 로그인하고 구매하는 등 시나리오가 있음(끝에서 끝까지 테스트) / end to end

3. 실제 테스트 코드 구현 & 방법(실습)

  • 테스트 코드 구현 전 필요한 것들!
    1. Jest
  • new nest 33-01-test로 새로운 nest폴더를 만듬
  • nest에 .git이 남아있기 때문에 rm -rf .git을 통해서 삭제!

  • Test코드 파일 : xxx.spec.ts 이런식으로 파일을 만들어줘야 한다.
it('더하기 테스트', () => {
  // it 안에 테스트 이름 적기
  const a = 1;
  const b = 2;

  expect(a + b).toBe(3); // expect: 기대한다.
});
  • 한개 테스트하기 // 위 예제 테스트를 실행해보면,

  • 위 사진처럼 결과가 나온다.
  • 이번에는 여러 묶음으로 테스트할거다.
describe('나의 멋진 테스트 그룹', () => {
  it('더하기 테스트', () => {
    // it 안에 테스트 이름 적기
    const a = 1;
    const b = 2;

    expect(a + b).toBe(3); // expect: 기대한다.
  });

  it('곱하기 테스트', () => {
    // it 안에 테스트 이름 적기
    const a = 1;
    const b = 2;

    expect(a * b).toBe(2); // expect: 기대한다.
  });
});

  • 이런식으로 여러묶음으로도 테스트가 가능하다.
  • 근데 얼마나 디테일하게 만들어야 할지 고민이다... => 처음부터 빈틈없이 완벽하게 만들지 말고, 점점 크게 그리고 디테일 하게 만든다!
  • 테스트에도 순서가 있다!!

  • 처음부분은 it이 아니라 beforeEach를 써서 위 사진처럼 작성을 한다.
  • decribe 부분이 하나의 API라고 보면 된다.
import { AppController } from './app.controller';
import { AppService } from './app.service';

describe('AppController', () => {
  let appController: AppController;
  let appService: AppService;

  beforeEach(() => {
    appService = new AppService(); // return 값을 쓰기 위해 AppService를 임포트해옴
    appController = new AppController(appService); // Class AppController를 넣은거다.
  });

  describe('getHello', () => {
    it('이 테스트의 검증 결과는 Hello World를 리턴해야 함!!!', () => {
      const result = appController.getHello();
      expect(result).toBe('Hello World!');
    });
  });
});
  • 밖에 appController를 만들어 놓음으로써 아무곳에서나 쓸 수 있다.
  • Controller나 Service를 직접 만들어서 쓰는 방식

  • Test를 import해서 직접 모듈을 불러와서 주입하는 방법도 있다.
  • 실무에서도 이 방법을 제일 많이 쓴다고 한다.
  • 원래 기본적으로 만들어진 app.controller.spec.ts와 같아졌다.

  • 이번에는 원본 appService말고 가짜 서비스를 만들어서 넣어 볼거다.
  • 첫번째는 하면 안된다! => 말이안된다..
  • 두번째는 꽤 많이 쓰인다! => Test를 돌릴때마다 DB에 계속 접근해야 하기 때문에 시간이 너무 오래 걸린다.
  • 세번째는 배열을 만들고, 거기에 push해서 넣는 방법이다. 이 방법이 가장 많이 쓰인다!

  • 세번째 방법 하기!
  • 주입하는 것을 바꾸는 것이지 그 뒤에 있는 소스코드를 바꾸는 것은 아니다!
  • Mock이라는 가짜 서비스를 직접 만들어야 한다.
  • Test할때만 Mock으로 바꿔서 Test를 한다.
import { Test } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';

class MockAppService {
  getHello() {
    return 'Hello World!';
  }
}

describe('AppController', () => {
  let appController: AppController;
  // let appService: AppService;

  beforeEach(async () => {
    const appModule = await Test.createTestingModule({
      controllers: [AppController],
      providers: [
        {
          provide: AppService, // AppService를 주입하지 말고, MockAppService를 사용 해줘.
          useClass: MockAppService,
        },
      ], 
    }).compile(); 

    appController = appModule.get<AppController>(AppController); 
  });

  describe('getHello', () => {
    it('이 테스트의 검증 결과는 Hello World를 리턴해야 함!!!', () => {
      const result = appController.getHello();
      expect(result).toBe('Hello World!');
    });
  });
});

마무리

=> TDD,Jest를 사용해보면서 여기에는 왜 이 명령어를 써야하는지를 꼼꼼히 공부해봐야 할거 같다.

profile
끝날때 까지 끝난게 아니야. 결국 내가 이겨!

0개의 댓글