완벽한 어플리케이션을 제작하기 위한 개발자.
우리 프론트엔드 개발자들을 위한 문서입니다.
만약 당신이 프론트엔드 테스팅 기본를 읽지 않았다면 읽고 오시길 바랍니다.
- Playwright 시작하기
- 왜 Playwright를 써야할까?
- Playwright란?
- 참고문서
Playwright는 빠르고, 안정적인 테스트 자동화를 지원하는 Microsoft의 오픈소스 입니다.
대부분의 개발자들은 테스트 코드를 작성해야 하는 것을 너무나 잘 알고있습니다.
그러나 빠듯한 일정에 대부분 도입을 주저합니다.
이에 Playwright는 다양한 기능들을 통해 빠르고 안정적인 테스트 자동화가 이루어 질 수 있도록 지원합니다.
Playwright는 Chrome, Firefox, IPhone등 다양한 사용자 환경을 지원합니다.
자동화된 테스트는 큰 규모, 반복적인 작업 수행하는 데 탁월합니다. URL을 입력하고 웹페이지와 인터랙션을 하면 Playwright는행동에 대한 테스트코드를 작성 해주는 Code generator 기능을 제공합니다.
수동 테스트는 사람의 실수라는 리스크가 있지만, 자동화된 테스트는 미리 정의된 작업을 정확히 수행하므로 일관성과 정확성이 향상됩니다.
예상 결과와 실제 결과를 비교하여 오류를 식별하고 이에 대한 자세한 정보를 제공할 수 있습니다.
자동화된 테스트는 빠른 피드백 제공을 가능하게 합니다.
산출물(테스트 결과와 오류 보고서)이 즉시 생성되어 개발자나 테스터에게 전달되므로 문제를 신속하게 파악하고 수정할 수 있습니다.
이는 개발 초기 단계에서 문제를 발견하고 해결하는 데 도움이 됩니다.
- Playwright는 웹 애플리케이션 테스트 및 자동화를 위한 오픈 소스 도구입니다.
- 브라우저(Chrome, Firefox, Safari 등)를 제어, 사용자의 행동(클릭, 키 입력, 네비게이션 등)에 대한 시뮬레이션, 테스트 기능을 제공합니다.
-
다음 명령어를 사용하여 vue 프로젝트를 생성합니다.
$ git clone [email protected]:socketbear/vue-dev-guide.git
-
$ pnpm dlx create-playwright
를 입력하여 설치합니다.✔ Where to put your end-to-end tests? · test/e2e ✔ Add a GitHub Actions workflow? (y/N) · false ✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · true
-
설치 완료 확인을 위해 파일목록을 확인하세요.
- 추가된 파일
playwright.config.ts: playwright 설정파일 test/e2e/: e2e 예시 파일 tests-examples: 데모 TODO 앱 e2e 테스트 폴더
- 수정된 파일
.gitignore : playwright관련 출력 파일 목록 추가 package.json : "@playwright/test" 패키지 추가 pnpm-lock.yaml
- 추가된 파일
-
vscode 에디터인경우 익스텐션 설치을 설치해야 합니다.
-
package.json 파일의 scripts 프로퍼티에 아래 명령어를 추가 하십시오. 관련문서
"test:e2e": "pnpm exec playwright test", "test:e2e:debug": "pnpm exec playwright test --debug", "test:e2e:report": "pnpm exec playwright show-report", "test:e2e:ui": "pnpm exec playwright test --ui", "test:e2e:gen": "pnpm exec playwright codegen",
-
위사진의 좌측 사이드바의 테스트 케이스 목록을 클릭하여 재생(Run) 버튼을 눌러주세요. 아래와 같이 녹색 체크 표시가 보인다면, 축하합니다 당신은 테스트에 성공했습니다!
모든 테스트 파일이 테스트 사이드바에 로드되어 각 파일, 테스트을 실행, 보기, 디버그할 수 있습니다.
텍스트 또는 @tag 또는 통과, 실패 및 건너뛴 테스트뿐만 아니라.
playwright.config
파일에 설정된 프로젝트(브라우저 환경)별로 테스트를 필터링 할 수 있습니다.
우리는 테스트간 유저 행동의 추적정보(trace)를 확인하고
각 단계에서 무슨 일이 발생했는지 확인하고 DOM 스냅샷을 별도의 창으로 팝업하여 디버깅 환경을 개선할 수 있습니다.
테스트가 진행된 타임라인입니다. 클릭 후 커서이동을 통해 테스트가 어떻게 진행되었는지 UI로 확인 할 수 있습니다.
테스트간 진행된 행동 목록입니다 클릭시, 행동에 대한 추적(trace)정보 가 UI에 표시됩니다.
테스트 액션에 대한 추적 정보를 UI로 표시하는 인터랙티브 뷰어입니다. 뷰어의 특정 엘리먼트를 클릭하여 해당 셀렉터를 복사 할 수 있습니다.
각 행동 또는 테스트전체에 대한 테스트코드, 콘솔로그, 테스트로그, 네트워크 로그를 확인 할 수 있습니다.
playwright는 주어진 URL를 입력하면, 상호 작용 가능한 Window를 제공합니다.
이것을 통해 우리는 앱을 테스트 하고, 상호작용 이력을 테스트코드로 자동 생성 할 수 있습니다.
-
테스트 결과를 엑셀로 표시 할 수 있는 playwright-excel-reporter, xlsx 패키지를 설치합니다.
$ pnpm install -D playwright-excel-reporter xlsx@https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz
-
playwright.config.ts
파일을 열어 아래 코드들을 붙여넣습니다.import { defineConfig, devices } from '@playwright/test' import type { IExcelConfig } from 'playwright-excel-reporter' export default defineConfig({ testDir: './test/e2e', /* 테스트를 병렬로 실행합니다. */ fullyParallel: true, /* CI 환경에서만 실패시 2회 재시도합니다. */ retries: process.env.CI ? 2 : 0, /* 각 프로세스당 할당되는 스레드 수, 워커 단위로 테스트가 실행됩니다. */ workers: process.env.CI ? 1 : undefined, /* 테스트 산출물을 지정 할 수 있습니다. 더 많은 정보는 [관련링크](https://playwright.dev/docs/test-reporters)를 참고하세요 */ reporter: [ ['html', { outputFolder: 'playwright-result-html', outputFile: 'result.html', }], ['playwright-excel-reporter', { // excelInputPath: 'test/asset/unit-test-case.xlsx', // excelStartRow: 5, // caseSheetName: '블라인드', // excelOutputDir: 'excel-reporter-result', // excelOutputFileName: 'result.xlsx', } as Partial<IExcelConfig>], ], /* 모든 프로젝트에 적용될 설정내용입니다. 자세한내용은 링크를 참조하세요. https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL 은 도메인을 입력 하지않았을때 다음과 같이 사용합니다. `await page.goto('/')`. */ baseURL: 'http://localhost:3333', /* trace 테스트가 실패하면 에러관련 정보를 저장합니다. 관련문서: https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', }, /* 테스트 환경을 설정합니다. */ projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, ], })
-
로컬 서버를 실행시킵니다.
$ pnpm run dev
-
새로운 테스트 파일을 생성합니다.
$ touch test/e2e/el-todo.spec.ts
-
다음 코드를 붙여넣습니다.
import { expect, test } from '@playwright/test'
// "Todo CRUD"라는 테스트 그룹과 하위 케이스 "create todo"
const MAIN_ROUTE = 'http://localhost:3333/guide/samp/el-todo'
test.describe('Todo CRUD ', () => {
test('create todo', async ({ page }) => {
await page.goto(MAIN_ROUTE)
await page.screenshot({ path: 'screenshots/todo/before-create.png', fullPage: true })
await page.screenshot({ path: 'screenshots/todo/after-create.png', fullPage: true })
})
})
-
상단 사진의 1, 2번을 차례로 클릭하여 상호작용 가능한 창을 실행시킵니다.
-
테스트 브라우저의 주소창에
http://localhost:3333/guide/samp/el-todo
입력하여 이동합니다. -
페이지에서 todo 항목을 입력하고 추가 버튼을 눌러 데이터 2건 생성을 테스트 해보십시오.
-
code generate 기능을 통해 테스트 코드가 생성되었음을 확인하세요
만약 조금 이상하거나 다르다면 아래 코드를 붙여넣으세요.// test/e2e/ // --| el-todo.spec.ts import { expect, test } from '@playwright/test' test.describe('Todo CRUD ', () => { test('create todo', async ({ page }) => { await page.goto('http://localhost:3333/guide/samp/el-todo') await page.screenshot({ path: 'screenshots/todo/before-create.png', fullPage: true }) await page.getByPlaceholder('TO-DO 항목을 입력해주세요.').click() await page.getByPlaceholder('TO-DO 항목을 입력해주세요.').fill('소금빵을 산다') await page.getByPlaceholder('TO-DO 항목을 입력해주세요.').press('Enter') await page.getByPlaceholder('TO-DO 항목을 입력해주세요.').click() await page.getByPlaceholder('TO-DO 항목을 입력해주세요.').fill('밥을 먹는다.') await page.screenshot({ path: 'screenshots/todo/after-create.png', fullPage: true }) }) })
-
좋습니다. 이제 생성된 2개의 todo목록에 대한 검증을 위한 코드를 16번 라인에 추가하겠습니다.
// 할 일 목록 테이블에 2개의 행이 존재하는지 검증하는 코드
expect((await page.$$('.data-test-row')).length).toEqual(2)
- 테스트 UI를 통해 테스트를 실행합니다.
1.pnpm run test:e2e:ui
2. - 저런 테스트가 실패했습니다! 살펴봅시다. [사진 12]
- 실패한 테스트 목록을 확인 할 수 있습니다.
- 에러메세지를 확인 결과: 행이 2개가 아니라 0개로 잡힙니다.
- 테스트 진행 중 화면을 확인하니 행이 한개가 있습니다.
두 번째 행을 추가하는 테스트 코드 작성과
.data-test-row
class 를 가진 row 목록을 받아오는 코드의 수정이 필요합니다.
- 두 번째 행을 추가하는 테스트 코드 작성
.data-test-row
class 를 가진 row 목록을 받아오는 코드의 수정
테스트에 사용될 selector는 반드시 data-test를 prefix로 가져야 합니다.
즉 변경되지 않으며 JS/Css 와 격리된, 테스트 용도의 속성이어야 합니다.
src/guide/pages/samp/el-todo.vue
파일 -el-table
엘리먼트의 속성을 추가합니다.
<!-- row-class-name="data-test-row 속성 추가 -->
<el-table data-test-id="todo-table" :data="todoList" style="width: 100%" row-class-name="data-test-row">
- 다시 테스트를 진행, 성공을 확인합니다.
- 산출물을 확인합니다.
screenshots
폴더에서 스크린샷을 확인하세요excel-reporter-result
폴더에서 엑셀 파일을 확인하세요
지금까지 가이드를 통해, 우리는 다음과 같은 사실을 알 수 있습니다.
-
우리는 배포/로컬 서버를 통해 테스트 자동화 기능을 개발 할 수 있다.
-
기본적인 테스트 코드들을 playwright 를 통해 자동 생성할 수 있다.
-
테스트 결과, 에러정보를 산출물로 얻을 수 있다.
-
스크린샷 기능을 통해, 테스트 케이스 전 후 비교된 산출물을 얻을 수 있다
Playwright 는 아래 다양한 특징들을 기반으로, 완전 관리형 e2e 환경을 제공합니다.
-
브라우저와 상호작용을 통해 원하는 테스트 코드를 자동생성 할 수 있습니다.
-
TDD 최대 난제 중 하나인 개발비용 단축에 대한 기능이자 핵심기능 중 하나입니다.
아래 명령어를 실행하여, URL 주소에 대한 테스트 생성 기능을 테스트 해보세요. 관련문서
$ npx playwright codegen {URL}
$ npx playwright codegen --viewport-size=800,600 demo.playwright.dev/todomvc
$ npx playwright codegen --device="iPhone 13" demo.playwright.dev/todomvc
테스트 커버리지를 계산, 모든 파일에 대한 테스트 파일 생성을 기대했으나... 실패
playwright는 진행된 테스트에 대한 레포트를 다양한 양식으로 지원합니다.
자세한 내용은 관련문서 에서 확인하세요.
- HTML
- 파일(페이지) - 테스트 그룹 - 테스트 케이스로 분류된 목록
- pass/fail/skip 필터링
- 검색
- Screenshot
- 테스트 코드중 설정에 따라 programmatic 또는 자동 으로 테스트 장면을 저장 가능
- JSON/Custom Reporter
- 엑셀 라이브러리를 이용하여, 커스텀한 엑셀을 생성 및 제공 할 수 있습니다.
- 그 외 고객의 요구사항에 맞게 커스터마이징한 Reporter 를 제공 할 수 있습니다.
vscode 익스텐션이 설치되어 있다면, 테스트 중 아래 기능들을 사용 할 수 있습니다.
- breakpoint등 (builtin)디버깅 기능들을 사용 할 수 있습니다.
- 실시간 브라우저 윈도우 와 IDE 를 비교하며 에러를 수정 할 수 있습니다.
REST API 통신과 관련된 테스트를 제공합니다.
- E2E 와 별도로 API 테스트를 위해서 HTTP 통신을 통해 서버 테스트가 가능합니다.
- E2E 테스트 도중, 혹은 setup/teardown 훅에서 자유롭게 HTTP 통신을 할 수 있습니다.
- playwright는 모든 네트워크 트래픽에 대한 모니터링, 수정이 가능합니다.
const browser = await chromium.launch({
proxy: {
server: 'http://myproxy.com:3128',
username: 'usr',
password: 'pwd'
}
});
어떤 유저인증 전략이든, 유저 인증 정보를 브라우저 혹은 파일로 저장하게 됩니다.
await page.context().storageState({ path: authFile });
우리는 계정정보를 파일로서 관리하고, 로그인 과정에 사용 할 수 있습니다.
await page.goto('https://github.com/login');
await page.getByLabel('Username or email address').fill(account.username);
await page.getByLabel('Password').fill(account.password);
await page.getByRole('button', { name: 'Sign in' }).click();
await page.waitForURL('https://github.com/');
await expect(page.getByRole('button', { name: 'View profile and more' })).toBeVisible();
위 코드는 저장된 계정을 통해 로그인하고, 쿠키가 저장된 상태로 홈페이지로의 리다이렉션을 대기하는 테스트 케이스를 작성 할 수 있습니다.
const context = await browser.newContext({
httpCredentials: {
username: 'bill',
password: 'pa55w0rd',
},
});
const page = await context.newPage();
await page.goto('https://example.com');
Playwright는 테스트 진행 로그들을 zip파일로 저장합니다.
- 인터렉션 로그, 스냅샷(스크린샷),
- 테스트 소스 코드 ,
- 네트워크 로그
- 테스트 사양, 환경
- 관련문서
trace.playwright.dev 링크 혹은 아래 명령어를 사용하여, 정보를 확인 할 수 있습니다.
$ npx playwright show-trace trace.zip
익숙한 Vue Inspector처럼 Playwright 또한 GUI 툴을 제공합니다.
- 클릭등의 인터랙션을 통하여 테스트의 생성, 정지,수정 녹화, 복사, 삭제. 언어변경이가능합니다.
- 브라우저 엘리먼트의 selector를 실시간으로 추출 할 수 있습니다.
- 브라우저 액션에 대한 로그를 확인 할 수 있습니다.
E2E 테스트 라이브러리는 대체로 무겁고, 느립니다.
테스트 브라우저를 설치하고, 매 테스트마다 브라우저 엔진을 재가동, 재 렌더링해야 하기 때문입니다.
이에 Playwright는 cypress 패키지 사이즈 기준 200배 경량화된 용량, 훨씬 빠른 체감속도로, 최적화에 많은 노력을 기울이고 있습니다.
Cypress(4.99 MB) > Nightwatch(webdriver required) > Playwright(24.2 kB)
- 크로미움, 웹킷, 파이어폭스,
- 윈도우, 리눅스, MacOS
- headless, headed, 모바일 emulator(chrome for android, safari for ios)
- 관련 문서
문서 작성일 기준, vite, vue, pinia 에 대한 플러그인, 호환을 지원하지만
아직 실험적 기능이며, 컴포넌트 테스팅을 도입하기 위해서 추가 테스트가 필요합니다.
관련문서
Playwright는 skip
, failures
, fixme
등 관리 가능한 주석 기능을 제공합니다.
관리는 조건 또는 필터를 통한 테스트 실행, 메타 데이터의 관리 가능을 의미합니다.
- 관련문서
- 주석은 테스트 혹은 테스트 그룹 일 수 있습니다.
- 사전설정/조건에 따라 동적으로 적용 가능합니다.
아래 분류 별 예시를 확인하고 상세 내용은 관련문서를 참조 하십시오.
test('skip this test', async ({ page, browserName }) => {
test.skip(browserName === 'firefox', 'Still working on it');
});
slow
태그가 추가된 테스트 케이스를 작성합니다.
test('update todo status @slow', async ({ page }) => {
await createTwoTodo(page)
await page.getByRole('row', { name: '소금빵을 산다' }).getByRole('button', { name: '미완료' }).click()
await expect(page.getByRole('row', { name: '소금빵을 산다' })).not.toContainText(/미완료/)
await expect(page.getByRole('row', { name: '소금빵을 산다' })).toContainText(/완료/)
await page.getByRole('row', { name: '소금빵을 산다 완료' }).getByRole('button', { name: '완료' }).click()
await expect(page.getByRole('row', { name: '소금빵을 산다 미완료' })).toContainText(/미완료/)
})
- 이후 위 태그에 해당하는 테스트만 실행할 수 있습니다.
npx playwright test --grep @slow
메타데이터는 key(type)/value(description) 쌍으로 관리되며
Reporter에서 보여질 수 있습니다.
우린 테스트 항목들에 대한 녹화 기능을 이용할 수 있습니다. 적용 방법은 아래와 같습니다. 용량이 너무 크지 않도록 사이즈를 조절하세요
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: {
mode: 'on-first-retry',
size: { width: 640, height: 480 }
}
},
});
fixture(고정된 상태)은 각 테스트에 필요한 환경을 사전 구성하는 기능입니다.
픽스처는 각 테스트가 진행되기 전 DB를 세팅하는 작업이 될 수도, 공통적으로 사용되는 클래스의 초기화 작업이 될 수도 있습니다.
픽스처는 크게 두가지의 종류로 사용됩니다.
- 여러 테스트에 걸쳐 중복된 데이터 생성이 필요할 때
- 여러 테스트에 사용되는 상태 혹은 helper 메소드를 정의 할 때
Playwright 는 기존 테스트에 사용되던 test 객체에 기능을 추가(extends)/오버라이딩 하는 방법으로 사용 할 수 있습니다.
DOM 요소를 찾아내는 기능으로, 자동대기(auto wait), 재시도(retry)가 적용된 playwright의 querySelector입니다.
API | 설명 | 예제(DOM) | 예제(Selector) |
---|---|---|---|
page.getByRole() | 요소의 역할에 따라 선택 | Sign in |
await page.getByRole('button', { name: 'Sign in' }).click(); |
page.getByLabel() | 라벨 Text 에 따라 선택 | Password |
await page.getByLabel('Password').fill('secret'); |
page.getByPlaceholder() | placeholder Text 에 따라 선택 |
|
await page.getByPlaceholder("[email protected]").fill("[email protected]");
|
page.getByText() | text에 따라 선택(substring, Regex 사용가능) | Welcome, John |
await expect(page.getByText(/welcome, [A-Za-z]+$/i)).toBeVisible();
|
page.getByAltText() | 대부분의 이미지 요소에 사용되는 alt 속성 기준 선택 |
|
await page.getByAltText('playwright logo').click();
|
page.getByTitle() | title 속성 기준 선택 |
25 issues
|
await expect(page.getByTitle('Issues count')).toHaveText('25 issues');
|
page.getByTestId() | data-testid 속성 기준 선택, 테스트 용도로 구별되는 속성으로 일관성을 유지하기 위해 주로 사용합니다. |
방향
|
await page.getByTestId('directions').click();
|
그밖의 더 많은 예제와 자세한 API는 [링크](https://playwright.dev/docs/locators) 를 참조하세요
먼저 vitest, vue3는 unit, component 공식 unit/component 테스트 라이브러리로 vitest를 사용하고 있습니다.
하지만 vite, vue 모두 SPC 를 위한 툴이며, vitest는 SPC, Client-Side Rendering 가 아닌 환경에서는 component 테스팅조차 의도대로 동작하지 않습니다.
이에 nuxt는 nuxt/test-utils 특히 vue는 playwright 전 cypress에 대한 복잡한 세팅과정을 CLI 사전 세팅을 통해 해결하려 했지만 라이브러리 자체의 문제인 진입장벽, 개발비용, 복잡한 셋업 과정을 커버 할 순 없었습니다.
그동안 e2e 테스트는 unit test 보다 앱에대한 자신감을 가질 수 있지만, 훨씬 더 요구되는 개발비용으로 인해 도입이 어려웠었던 것이 현실입니다. 이에 마이크로소프트의 Playwright 는 위 문제들에 대한 대안을 제시합니다.