Unit Test
: 단위 테스트는 함수나 모듈 등 가장 작은 단위를 테스트한다. 특정 기능이 예상대로 작동하는지 확인하는데 중점을 둔다. 빠르고 간단하며, 의존성이 적어 독립적으로 실행할 수 있다.
Integration Test
: 통합 테스트는 여러 모듈이 함께 작동하는 방식을 테스트한다. 모듈 간 의존성과 상호작용을 검증할 수 있다.
End-To-End Test
: E2E 테스트는 전체 흐름을 테스트한다. 브저우저 환경에서 실제 사용자가 경험하는 것과 동일한 방식으로 테스트를 수행한다. UI 요소와 사용자 상호작용을 포함한 전체 시스템을 테스트할 수 있지만, 가장 느리고 복잡하다.
End-To-End Testing은 실제 상황에서 애플리케이션의 기능을 처음부터 끝까지 테스트하는 방법이다.
E2E는 사용자 관점에서 상호작용한다. 버튼 클릭, 폼 제출 등을 자동화된 스크립트를 통해 수행하게 된다. 사용자 로그인, 제품 검색, 구매 등의 실제 사용 과정을 시뮬레이션할 수 있다.
프론트엔드, 백엔드, 데이터베이스를 포함한 모든 애클리케이션의 구성 요소가 올바르게 동작하는지 확인할 수 있다.
사용자의 실제 경험을 기반으로 하여 신뢰성이 높다. 시스템 간의 상호작용에서 발생하는 문제를 찾아낼 수 있다.
테스트 스크립트로 반복 실행할 수 있어 테스트 과정을 자동화할 수 있다.
Cypress
, Selenium
, Puppeteer
, Playwright
등이 있다.
Playwright
는 Microsoft에서 개발한 오픈 소스 자동화 테스트 도구이다. 브라우저를 자동으로 제어하여 사용자가 수행할 수 있는 모든 동작을 스크립트로 작성할 수 있다.
이미 광범위하게 사용되고 있는 E2E 도구 Cypress
가 있지만, 그럼에도 Playwright
에 주목하는 이유는 다음과 같다.
Playwright Test for VSCode
을 지원한다. 훨씬 편리하게 테스트할 수 있다.Playwright API reference
공식문서를 참고해 기본적인 내용을 정리했다.
사용 방법은 다음과 같다.
test(title, body)
test(title, details, body)
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://playwright.dev/');
// ...
});
테스트 진행 후엔 /playwright-report/index.html
에서 테스트 보고서를 확인할 수 있다.
아래는 details
에 넣을 수 있는 두 가지 옵션이다. 테스트 보고서에 반영된다.
@symbol
을 활용한 태그 지정test('basic test', {
tag: '@smoke',
}, async ({ page }) => {
await page.goto('https://playwright.dev/');
// ...
});
test('another test @smoke', async ({ page }) => {
await page.goto('https://playwright.dev/');
// ...
});
annotation
를 활용한 주석 달기test('basic test', {
annotation: {
type: 'issue',
description: 'https://github.com/microsoft/playwright/issues/23180',
},
}, async ({ page }) => {
await page.goto('https://playwright.dev/');
// ...
});
afterAll
훅은 파일의 모든 테스트가 끝난 후에 실행되고, afterEach
훅은 각 테스트가 끝날 때마다 실행된다. title
로 제목을 지정해줄 수도 있다.
test.afterAll(async () => {
console.log('Done with tests');
// ...
});
test.afterEach('Status check', async ({ page }) => {
if (test.info().status !== test.info().expectedStatus)
console.log(`Did not run as expected, ended up at ${page.url()}`);
});
beforeAll
훅은 모든 테스트 전에 한 번 실행되고, beforeEach
훅은 각 테스트가 시작하기 전에 실행된다. title
로 제목을 지정해줄 수도 있다.
test.beforeAll('Setup', async () => {
console.log('Before tests');
});
test.beforeEach('Open start URL', async ({ page }) => {
console.log(`Running ${test.info().title}`);
await page.goto('https://my.start.url/');
});
describe
는 테스트의 그룹을 선언한다. title
없이 선언하는 것도 가능하며, details
로 태그나 주석을 달 수도 있다.
test.describe('two tagged tests', {
tag: '@smoke',
}, () => {
test('one', async ({ page }) => {
// ...
});
test('two', async ({ page }) => {
// ...
});
});
describe.configure
를 통해 테스트 실행 방식을 지정할 수 있다.
mode
엔 default
, parallel
, serial
가 있다.
test.describe.configure({ mode: 'parallel' });
test.describe('A, runs in parallel with B', () => {
test.describe.configure({ mode: 'default' });
// ...
});
test.describe('B, runs in parallel with A', () => {
test.describe.configure({ mode: 'default' });
// ...
});
mode
에 따라, 위 코드에서 A와 B는 병렬로 실행되지만, A와 B 내부의 테스트는 순서대로 실행될 것이다.
setTimeout
을 통해 테스트의 최대 실행시간을 설정할 수 있다. beforeAll
이나 afterAll
과 함께 사용하여 테스트가 아닌 훅의 타임아웃에 영향을 미칠 수도 있다.
test('very slow test', async ({ page }) => {
test.setTimeout(120000);
// ...
});
test.beforeAll(async () => {
// Set timeout for this hook.
test.setTimeout(60000);
});
skip
과 fixme
는 해당 테스트를 실행하지 않고 건너뛰게 한다.
test.skip('never run', async ({ page }) => {
// ...
});
test.fixme('to be fixed', async ({ page }) => {
// ...
});
test.describe.fixme(() => {
// ...
});
페이지와 상호작용하기 위한 메서드를 제공한다.
해당 페이지로 이동한다.
await page.goto("https://playwright.dev/");
await page.goBack();
await page.goForward();
해당 텍스트가 포함된 요소를 찾는다. 이외에도 여러 메서드가 있다.
<div>Hello world</div>
<img alt='Playwright logo'>
<input type="email" placeholder="name@example.com" />
await page.getByText('Hello world');
await page.getByAltText('Playwright logo').click();
await page
.getByPlaceholder('name@example.com')
.fill('playwright@microsoft.com');
더 다양한 방법은 Locators에서 확인하자.
await page.keyboard.type('Hello World!');
await page.keyboard.press('ArrowLeft');
테스트가 성공했는지 검증을 위해 사용한다.
test("has title", async ({ page }) => {
await page.goto("https://playwright.dev/");
await expect(page).toHaveTitle(/Playwright/);
});