Career/웹
Javascript TDD
wood.forest
2020. 12. 6. 10:19
JS TDD 개론
TDD? Test-Driven-Development 테스트 주도 개발
테스트 케이스 생성→테스트→개발의 짧은 개발 사이클을 반복적으로 수행하며 소프트웨어를 개발하는 프로세스.
Red-Green Refactor 라고도 한다.
- 테스트 케이스 작성
- 테스트 케이스를 통과하기 위한 최소한의 코드 작성
- 표준에 맞도록 리팩토링
Uncle Bob describes TDD with three rules:
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
Why?
기존의 개발 프로세스
TDD 프로세스
- 설계 수정 시간 단축
- 디버깅 및 버그 수정 시간 단축
- 문제 발생 시 모듈별 테스트를 통해 문제 지점을 빠르게 파악 가능
- Production 레벨에서 버그를 수정하는 것은 Software development lifecycle (SDLC)에서 버그를 수정하는 것보다 훨씬 큰 비용과 시간을 소모
- Refactoring을 통해 Clean code를 유지
- 객체지향적인 코드 개발
- 세부 비즈니스 로직을 객체 내부로 숨겨 변경에 대응
- 유지보수 및 재사용에 용이
단점
- 테스트 코드를 작성, 유지하기 위한 비용과 시간
How?
- Mock객체를 생성하여 테스트
- 변경할 수 없는 객체, 프레임워크, 외부 라이브러리는 Mock하지 않는다
- ex. Jest에서 기본적으로 제공하는 mock functions
const myMockFunc = jest.fn().mockName("myMockFunc"); const myExampleModule = jest.mock("./exampleModule");
- Private객체의 테스트는?
- Public 객체에서 커버되는 경우 테스트하지 않는다.
- 리팩토링 고려. 해당 객체가 불필요한 책임을 가졌을 수 있다.
- 접근 제한을 Public으로 변경 후 @VisibleForTesting 추가
- 하나의 테스트에는 하나의 기능만 테스트한다
- 대상 코드의 의도 표현
- 데이터가 아닌 행위를 테스트한다 given-when-then
- 테스트하기 어려운 코드가 있다면 어떻게 하면 테스트할 수 있을까 가 아닌, 왜 테스트하기 어려울까를 고민
종류
- Unit Testing: 가장 작은 단위 테스트(함수)
- Integration Testing: 시스템 모델링에서 실제 기능, 퍼포먼스, 의존성, DB 데이터 등을 테스트
- UI Testing (E2E): 사용자 관점 테스트(UI)
Unit Test 단위 테스트
- 가장 작은 단위
- 단위 테스트이므로 다른 Unit과 의존성이 있어서는 안된다.
- 툴은 Mocha, Jasmine, Chai, Jest, Tape, Enzyme, Karma, Selenium, phantomjs 등 다양하며, 조합해서 사용할 수 있다.
Jest
예제 with- npm init -y 으로 package.json을 생성한다.
- npm i -D jest 로 development 모드로 jest를 실행한다.
- package.json의 test를 수정한다. (test를 입력했을 때 jest를 실행하겠다는 의미)
"scripts": { "test": "jest" },
- 테스트를 진행할 파일 unit.test.js를 생성한다.
- .test.js suffix를 사용해야 한다.
const add = (a, b) => { return 1; };
test('solution', () => { expect(add(1, 1)).toBe(2); });
- 영어 문법과 비슷: expect ~ toBe (보통 value) / expect ~ toEqual (array 등의 object)
- 테스트 npm test ./unit.test.js 결과는 반드시 실패한다. (Red)
- 성공하는 테스트 코드를 작성한다. (Green)
const add = (a, b) => {
const num1 = a;
const num2 = b;
return num1 + num2;
};
test('solution', () => { expect(add(1, 1)).toBe(2); });
- 성공 확인 후 리팩토링한다. (Refactor)
const add = (a, b) => { return a+b; };
test('solution', () => { expect(add(1, 1)).toBe(2); });
통합 테스트 Integration Test
- 앞서 unit테스트한 각각의 module들이 통합되었을 때 올바르게 동작하는지 확인하기 위함
- 주요 목적은 module들 간의 인터페이스 동작 테스트
- db, platform, environment등이 포함되어 테스트되므로 복잡해질 수 있음
Jest
Integration Test with- Unit test 방법과 거의 동일하며, 여기에서 샘플 코드 일부를 가져왔다.
import { calculateTopEmployee } from './top-employee-provider';
import { get } from './api-wrapper';
jest.mock('./api-wrapper');
test('returns the top-performing employee', async () => {
mockApiResponse('/employees', [
{name: 'foo', numOfSales: 1 },
{name: 'bar', numOfSales: 2 }
]);
const topEmployee = await calculateTopEmployee();
expect(topEmployee).toEqual({ name: 'bar', numOfSales: 2 });
});
function mockApiResponse(endpoint, payload) {
const successfulPromise = new Promise(resolve => process.nextTick(() => resolve(payload)));
get.mockImplementationOnce(e => e === endpoint ? successfulPromise : Promise.reject());
}
E2E테스트 (End to End Test)
- 사용자 입장 (환경 Latency, 관점 Workflow 등)에서의 테스트를 통해 사용자 경험 증대
- Web, App 등에서의 시나리오, 기능 확인
- 가장 확실하고 가장 필요한 테스트
Cypress
E2E with- 여기에 자세한 예제가 나와있어 일부 사진과 기능만을 가져왔다.
- Cypress는 다양한 helper를 지원하여 사용자 action에 따른 테스트가 가능하다.
- 현재는 Chrome과 Electron만 지원한다.
- Visit
describe('My First Test', function() {
it('Visits page', function() {
cy.visit('https://example.cypress.io')
})
})
- Interact
cy.contains('type').click()
- Debug
- 코드상에서 멈추고 싶은 위치에 cy.pause()를 삽입하여 디버깅할 수 있다.
- cy.debug()를 삽입하면 개발자 도구에서 Args등의 로그를 추가로 확인할 수 있다.
Reference
- https://m.blog.naver.com/PostView.nhn?blogId=suresofttech&logNo=221569611618&proxyReferer=https:%2F%2Fwww.google.com%2F
- https://medium.com/hbsmith/e2e-test-알아보기-3c524862469d
- https://velog.io/@rosewwross/unit-test
- https://www.slideshare.net/koreakihoon/tdd-112099012
- https://docs.reactioncommerce.com/docs/testing-reaction
- https://www.softwaretestinghelp.com/what-is-integration-testing/
- https://gist.github.com/cowchimp/0158efe57df3b845927e450fc2b87eeb
- https://softchris.github.io/pages/cypress.html
728x90
반응형