// 장바구니에 상품 추가
fireEvent.click(item1Button);
fireEvent.click(item2Button);
expect(cartItems).toHaveLength(2);
// 장바구니에서 상품 제거
const removeButton = cartItems[0].querySelector('button');
fireEvent.click(removeButton);
expect(cartItems).toHaveLength(1);
// 상품을 구매하고, 영수증 출력
fireEvent.click(checkoutButton);
expect(receiptItems).toHaveLength(1);
expect(receiptItems[0]).toHaveTextContent('Item 2 - 12000원');
expect(total).toHaveTextContent('Total: 16000원');
});
});
### E2E 테스트(End-To-End Test) [tool : Cypress, Puppeteer]
- E2E 테스트는 시스템의 **시작부터 끝까지의 전체 흐름을 확인**하는 테스트 유형
- 시스템이 예상대로 작동하고 **사용자의 요구 사항을 충족하는지 확인하기 위해 모든 구성 요소와 해당 구성 요소의 상호 작용을 테스트**하는 것이 포함된다.
- 사용자의 입장에서 전체 Flow가 정상적으로 동작하는지 확인
> 1. 고객이 카카오 로그인
> 2. 상품을 선택하여 장바구니에 추가
> 3. 상품 구매
> 4. 결제 방식 선택
> 5. 구매 완료
> 6. 구매 영수증을 고객 메일로 전송
```js
const puppeteer = require('puppeteer');
describe('Shopping', () => {
let browser;
let page;
beforeAll(async () => {
// 테스트 환경 설정
browser = await puppeteer.launch();
page = await browser.newPage();
await page.goto('http://localhost:3000');
await page.type('[data-testid="login-email"]', 'user@example.com');
await page.type('[data-testid="login-password"]', 'password');
await page.click('[data-testid="login-button"]');
await page.waitForNavigation();
});
afterAll(async () => {
// 브라우저 종료
await browser.close();
});
it('should allow a user to buy an item and receive a receipt', async () => {
// 상품을 장바구니에 추가
await page.click('[data-testid="item-123"]');
await page.click('[data-testid="add-to-cart-button"]');
await page.click('[data-testid="cart-icon"]');
// 장바구니의 추가된 상품 체크
const cartItem = await page.waitForSelector('[data-testid="cart-item"]');
expect(await cartItem.evaluate(el => el.innerText)).toContain('Item 1');
// 아이템 구매
await page.click('[data-testid="checkout-button"]');
await page.click('[data-testid="confirm-purchase-button"]');
await page.waitForSelector('[data-testid="receipt"]');
// 영수증 화면 출력
const receiptItems = await page.$eval('[data-testid="receipt-items"]', el => el.innerText);
expect(receiptItems).toContain('Item 1');
expect(receiptItems).toContain('12000 원');
const receiptTotal = await page.$eval('[data-testid="receipt-total"]', el => el.innerText);
expect(receiptTotal).toContain('Total: 16000 원');
// 영수증을 고객 메일로 전송
await page.click('[data-testid="send-receipt-button"]');
const receiptSent = await page.waitForSelector('[data-testid="receipt-sent"]');
expect(await receiptSent.evaluate(el => el.innerText)).toContain('Receipt sent to user@example.com');
});
});
E2E 테스트(최종 테스트) 만 하면 안되나?
사실 Unit, Integration에서 테스트 했던 내용들은 E2E 테스트로 확인할 수 있고, 테스트가 중복되는 경우가 많다.
하지만, Unit이 E2E보다 테스트 실행 시간이 훨씬 빠르다. 그리고 세분화 할수록 어떤 에러가 발생했는지도 빠르게 체크 할 수 있다.
TDD (Test-Driven Development)
실제 코드를 작성하기 전에 테스트 코드를 먼저 작성하는 개발 프로세스.
TDD의 이점
테스트 종류
단위 테스트(Unit Test) [tool : Jesmine, Jest, Karma, Mocha]
통합 테스트(Integration Test) [tool : Jest, Testing Library]
describe('Shop', () => { it('should display receipt after checkout', () => { render( );
const item1Button = screen.getByText('Item 1');
const item2Button = screen.getByText('Item 2');
const cartItems = screen.getAllByTestId('cart-item');
const checkoutButton = screen.getByText('Checkout');
const receiptItems = screen.getAllByTestId('receipt-item');
const total = screen.getByTestId('receipt-total');
// 장바구니에 상품 추가 fireEvent.click(item1Button); fireEvent.click(item2Button); expect(cartItems).toHaveLength(2);
// 장바구니에서 상품 제거 const removeButton = cartItems[0].querySelector('button'); fireEvent.click(removeButton); expect(cartItems).toHaveLength(1);
// 상품을 구매하고, 영수증 출력 fireEvent.click(checkoutButton); expect(receiptItems).toHaveLength(1); expect(receiptItems[0]).toHaveTextContent('Item 2 - 12000원'); expect(total).toHaveTextContent('Total: 16000원'); }); });
E2E 테스트(최종 테스트) 만 하면 안되나?
사실 Unit, Integration에서 테스트 했던 내용들은 E2E 테스트로 확인할 수 있고, 테스트가 중복되는 경우가 많다. 하지만, Unit이 E2E보다 테스트 실행 시간이 훨씬 빠르다. 그리고 세분화 할수록 어떤 에러가 발생했는지도 빠르게 체크 할 수 있다.
E2E만 사용할 경우(세분화가 낮을수록)
E2E, Integration, Unit을 사용 할 경우 (세분화가 높을 수록)