Jest๋ฅผ ์ ํํ๊ธฐ ๊น์ง
๊ฐ์ฅ ์์ ์ ์ด๊ณ ๋๋ฆฌ ์๋ ค์ง Mocha์์ ์ฑ๋ฅ์ฐจ์ด๋ฅผ ๋น๊ตํ ๊ฐ์ด๋ฐ, ํ ์คํ ์๋ ๋ํ ์๊ฒฌ์ด ๋ถ๋ถ ํ์์ต๋๋ค. ์ฌ์ค ์ ํฌ ํ๋ก์ ํธ์ ๋ง๋ ๊ฒฐ์ ์ ์์ธ์ด ๋ด๋ ค์ง์ง ์์์ต๋๋ค. ์ ์ ์จ์ ํ์ธ ํ, JEST๊ฐ ๋์ ๊ฐ์ด๋ฐ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๊ฐ๋ฐ์ ๋ฐ ํ๋ก์ ํธ์ ํน์ฑ์ ๊ณ ๋ คํ์ฌ ์ป์ ์ ์๋ ์ด์ ์ผ๋ก ์ ํํ์์ต๋๋ค. (ํน์ ๊ฒฝํ์ด ์์ผ์๊ฑฐ๋ ๊ณ ๋ คํ ์ฌํญ๋ค์ด ์๋ค๋ฉด ์๋ ค์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค!)
- ํ ์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ๋ฉด์ cli์์ ๋ด์ฅ๋ ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ํ์ธํ ์ ์๋ค๋ ์ .
- Playwright ์ปค๋ฎค๋ํฐ์์ jest์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ํ๋ ์์ํฌ ์ง์
- Jest ๋ํ Typescript ๋ฅผ ์ง์
- ํ ์คํธ๋ฅผ ์คํํ๋ ํ์ผ/๋๋ ํ ๋ฆฌ์ ๋ํ ์ง์ ์ด ์ ๋์ (์คํํ๋ ค๋ ํ์ผ์ regex๋ก ๊ตฌ๋ถํ๋ฏ๋ก ํตํฉํ ์คํธ๋, ์น ์ ๊ทผ์ฑ ํ ์คํธ ์ ๊ตฌ๋ณํ์ฌ ๋ฐ๋ก ํ ์คํธ ์คํ ๊ฐ๋ฅ)
- ํ ์คํธ์ผ์ด์ค๋ฅผ ๋ณ๋ ฌ๋ก ์คํ (๊ฐ์ฅ ๋๋ฆฐ ํ ์คํธ๋ฅผ ๋จผ์ ์คํ) -> ํจ์จ์ .
์ด๋ฏธ์ง ๋ฐ์ท : npmtrends
ํ์ฌ ๋ฒ์
jest 27.0
1. ํ์ ์คํฌ๋ฆฝํธ ์ค์น
npm install -D typescript
2. Jest Playwright ์ค์น (Jest ๋ฐ Playwright ๊ด๋ จ ํจํค์ง)
npm install -D jest jest-playwright-preset playwright
ts-jest @types/jest
jest-playwright-preset
: Playwright๋ก ์ ์ด๋๋ ๋ธ๋ผ์ฐ์ (headless browser)์์ Jest๋ก ํ ์คํธ๋ฅผ ์คํํ ์ ์๋๋ก ํ์ํ ํ๋ฌ๊ทธ์ธ๋ค๋ก ๊ตฌ์ฑ๋์ด ์๋ preset์ ๋๋ค.ts-jest
: Jest๋ ํ ์คํธ๊ฐ ์คํ ๋ ๋ type-check์ ํ์ง ์๊ธฐ ๋๋ฌธ์, type-check์ ํ๊ธฐ ์ํด์ ts-jest๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ tsc๋ฅผ ๋ณ๋๋ก ์คํํ ์ ์์ต๋๋ค. ์กฐ๊ธ ๋ ์์ํ๊ฒ ํ๋๋ก ts-jest๋ฅผ ์ฌ์ฉํ์ต๋๋ค. https://github.com/kulshekhar/ts-jest@types/jest
: jest๋ฅผ ์ํ ํ์ ์ด ์ ์ ๋์ด ์๋ ํจํค์ง ์ ๋๋ค. types์ ๋ํ ์์ธํ ์ค๋ช
NOTE : @types/ ๋ชจ๋๋ค์ ๊ด๋ จ์๋ ๋ชจ๋๊ณผ ๋ฒ์ ์ ์ผ์น ์ํค๋ ๊ฒ์ ๊ถ๊ณ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด 26.4.0 ๋ฒ์ ์ jest๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, 26.4.์ @types /jest๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. (์ฆ ๋ฉ์ด์ ๋ฒ์ ๊ณผ ๋ง์ด๋ ๋ฒ์ ์ ๊ฐ๋ฅํ ๋งค์น ํด์ผํฉ๋๋ค.) ์ถ์ฒ: JEST ๊ณต์๋ฌธ์
3. JEST configuration
Jest ์ ํ๊ฒฝ์ค์ ์ package.json
๋๋ jest.config.ts ์ฒ๋ผ ํ์ผ์ root ๋๋ ํ ๋ฆฌ ๋ด์ ์์ฑํด๋ ๋ฉ๋๋ค.
configuration ๊ณต์๋ฌธ์ ์ฐธ์กฐ
์ ๋ ์ข ๋ ๋ค์ํ ํ๊ฒฝ์ค์ ์ด ํ์ํ ๊ฒ ๊ฐ์ ํ์ผ์ ๋ฐ๋ก ์์ฑํ์์ต๋๋ค.
module.exports = {
preset: 'jest-playwright-preset',
testTimeout: 20000,
transform: {
'^.+\\.ts$': 'ts-jest',
},
testEnvironmentOptions: {
'jest-playwright': {
// Options...
browsers: ['chromium'], //์ฌ์ฉํ ๋ธ๋ผ์ฐ์ ์ง์ , ["chromium","firefox","safari"] ๋ชจ๋ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ณ๋ ฌ๋ก ์คํ
launchOptions: {
headless: false, //๋ธ๋ผ์ฐ์ ๋ฅผ ์คํฌ๋ฆฐ์์ ๋ณด์ฌ์ค ๊ฒ์ธ์ง false- ๋ณด์ฌ์ค
slowMo: 100, // ๋ธ๋ผ์ฐ์ ์ ์งํ์๋
},
},
},
}
transform
: Jest๋ ํ๋ก์ ํธ ์ฝ๋๋ฅผ JavaScript๋ก ์คํํ์ง๋ง Node.js์์ ์ง์ํ์ง ์๋ ์ ํ๋ค (Typescript, Vue)์ ๊ฒฝ์ฐ transform์ ๊ตฌ์ฑ ์ต์ ์ ํตํด JavaScirpt๋ก ๋ณํํฉ๋๋ค.testTimeout
: playwright-jest ์์ playwright ์ ์คํํ๋๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์, 5์ด์์ 15์ด ์ ๋๋ฅผ ๊ธฐ์กด์ jest์ค์ ์ ์ฌ์ ์ ํ๋๋ฐtestTimeout
์ผ๋ก ๋ค์ ์ค์ ํ ์ ์๋ค๊ณ ํฉ๋๋ค. jest-playwright ์ฐธ์กฐ- ์ ๊ฐ ์ค์ ๊ฒช์
BeforeAll
์์ ํ ์คํธ๋ฅผ running ํ์ง ๋ชปํ๊ณ timeout์ด ๋๋ ๊ฒฝ์ฐ๊ฐ ์์์ต๋๋ค.thrown: "Exceeded timeout of 15000 ms for a hook. Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
- ์ ๊ฐ ์ค์ ๊ฒช์
launchOptions
healess
:false
์ผ ๊ฒฝ์ฐ, browser๋ฅผ ์คํํ์ฌ ์คํฌ๋ฆฝํธ๋๋ก ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.true
์ผ ๋๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋์ฐ๋ ๋น์ฉ์ด ๋ค์ง ์๋ ๋งํผ ๋น ๋ฅธ ํ ์คํ ์๋๋ฅผ ๋ ๋๋ค.slowMo
:headless
๊ฐfalse
์ผ ๋, ms ๋จ์๋ก ๋ธ๋ผ์ฐ์ ์ ์ด๋ฒคํธ๋ค์ด ์ฒ์ฒํ ์ผ์ด๋ฉ๋๋ค. ๋๋ฒ๊น ์ ๊ฐ ์ด๋ฒคํธ๋ง๋ค ์ด๋ป๊ฒ ์ผ์ด๋๋์ง ๋ณผ ๋ ์ ์ฉํฉ๋๋ค.
slowMo:0 (default)
vsslowMo:250
headful ๋ธ๋ผ์ฐ์ ๊ฐ wikipedia์์ javascript ํ ์คํธ๋ฅผ ์ ๋ ฅํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด ๋ณด์์ต๋๋ค.
๊ฐ๋ฐ ๋ชจ๋์์๋ headless:false
์ slowMo
๋ฅผ ์ฌ์ฉํ๋, ํ๋ก๋์
๋ชจ๋์์๋ headless:true
์ค์ ์ผ๋ก ๋น ๋ฅธ ์คํ ์๋๋ฅผ ๊ฐ์ง๋๊ฒ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
4. TypeScript Configuration
์ต์ํ์ ์ค์ ์ ๋ด์ tsconfig.json ์ ๋๋ค.
{
"compilerOptions": {
"target": "ESNext",
"module": "commonjs",
"strict": true,
"forceConsistentCasingInFileNames": true,
"types": [
"@types/jest",
"jest-playwright-preset",
// "expect-playwright",
]
"rootDir": "src",
"outDir": "lib",
"lib": [ "es2017", "DOM","DOM.iterable" ]
},
"files": []
}
strict์ ๋ํ ์ดํํฐ๋ธ ํ์ ์ค๋ฆฝํธ ์ ๋ฆฌ ๊ธ
5. package.json
{
...,
"scripts": {
"test": "jest",
},
...
}
๋๋ฒ๊น ๋ฐฉ๋ฒ
1. Run in headed mode
await chromium.launch({ headless: false, slowMo: 100 }) // or firefox, webkit
2. Playwright Inspector
์ ๊ฐ์ ๊ฒฝ์ฐ๋ selector์ ๋ง์ด ํ ์ ํ๊ธฐ ๋๋ฌธ์ inspector๋ฅผ ํตํด ์ฐพ๊ฑฐ๋ ๊ฐ๋จํ ์คํฌ๋ฆฝํธ ์์ฑ์ผ๋ก ์ด์ฉ ํ์์ต๋๋ค.
2-1. ์คํฌ๋ฆฝํธ์์ breakpoint๋ฅผ ์ฌ์ฉํ๋ฏ์ด await page.pause();
์ํ๋ ๋ผ์ธ์ ํธ์ถํฉ๋๋ค.
describe('GitHub', () => {
it('should show the microsoft/Playwright project in the search if you search for Playwright', async () => {
await page.goto('https://github.com')
await page.pause()
await page.type('input[name="q"]', 'Playwright')
await page.press('input[name="q"]', 'Enter')
await expect(page).toMatchText('.repo-list-item', 'microsoft/playwright')
})
})
2-2. PWDEBUG=1
ํ๊ฒฝ๋ณ์ ์ฌ์ฉ
PWDEBUG=1
ํ๊ฒฝ๋ณ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด, await page.pause()
์ ์์น์ ์๊ด์์ด ์ค๋จ์ ์ด ์คํฌ๋ฆฝํธ์ ๋งจ ์ฒซ์ค์์ ํธ๋ฆฌ๊ฑฐ ๋ฉ๋๋ค.
# Linux/macOS
PWDEBUG=1 npm run test
# Windows with cmd.exe
set PWDEBUG=1
npm run test
# Windows with PowerShell
$env:PWDEBUG=1
npm run test
๋ํ inspector์์๋ ๋ธ๋ผ์ฐ์ ๋ด์์ ์ผ์ด๋๋ ๋ชจ๋ ์ด๋ฒคํธ์ ์ฝ๋๋ฅผ ์์ฑ ํด์ค๋๋ค.
์๋ฅผ ๋ค์ด,
jest.setTimeout(1000000)
describe('GitHub', () => {
it('should show the microsoft/Playwright project in the search if you search for Playwright', async () => {
await page.goto('https://wikipedia.org')
await page.pause()
})
})
์์ ์คํฌ๋ฆฝํธ์ ํจ๊ป PWDEBUG=1 npm run test
์ ์คํ์ํจ ํ,
Record ๋ฒํผ์ ๋๋ฅด๊ฒ ๋๋ฉด, ๋
นํ๋ชจ๋๋ก ์คํฌ๋ฆฝํธ๊ฐ ์๋ก ๋ง๋ค์ด์ง๋๋ค.
์ค๋ฅธ์ชฝ์ ๋ธ๋ผ์ฐ์ ์์ ์ํ๋ ์ด๋ฒคํธ๋ฅผ ํ๊ฒ ๋๋ฉด ์ฝ๋๊ฐ ์์ฑ๋ฉ๋๋ค.
์ด ๋ถ๋ถ์ด ์ ์ฉํ๋ค๊ณ ๋๋์ ์, ์ ๊ฐ ์ด๊ฒ์ ์ฌ์ฉํ๊ธฐ ์ ๊น์ง promise race condition ๋ถ๋ถ์ ์ฒ๋ฆฌํ๋๋ผ ์ฝ๋๋ฅผ vscode ๋๋ฒ๊น ์ ๋๋ฆฌ๊ณ , promise return ๊ฐ์ ํ์ธํ๊ณ ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑ ํด์ผ ํ์๋๋ฐ, Promise.all๋ก ์๋ ์์ฑํ์ฌ race condition์ด ์ผ์ด๋๋ ๊ฒฝ์ฐ์ ์๋ฅผ ์ค์ฌ์ค ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด์ ๊ฐ๋ฐ ํ๊ฒฝ ์ค์ ๋ฐ ๋๋ฒ๊น ํธ์ด์์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ