ใ€Playwrightร—Pythonใ€‘SauceDemo E2E ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ๋ฐฉ๋ฒ•๏ฝœ๋กœ๊ทธ์ธ~์ฃผ๋ฌธ ์™„๋ฃŒ ์ „์ฒด 10์ผ€์ด์Šค

ํ…Œ์ŠคํŠธ ์ž๋™ํ™”

๐Ÿ“Œ ์ด๋Ÿฐ ๋ถ„๊ป˜ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค

  • Playwright๋กœ E2E ํ…Œ์ŠคํŠธ๋ฅผ ์ฒ˜์Œ ๋ฐฐ์šฐ๊ณ  ์‹ถ์€ ๋ถ„
  • ๋กœ๊ทธ์ธ๋ถ€ํ„ฐ ์ฃผ๋ฌธ ์™„๋ฃŒ๊นŒ์ง€์˜ ์ „์ฒด ํ”Œ๋กœ์šฐ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์‹ถ์€ QA ์—”์ง€๋‹ˆ์–ด
  • Selenium์—์„œ Playwright๋กœ์˜ ์ „ํ™˜์„ ๊ฒ€ํ†  ์ค‘์ธ ๋ถ„
  • Python์œผ๋กœ E2E ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ณ  ์‹ถ์€ ๊ฐœ๋ฐœ์žยทํ…Œ์ŠคํŠธ ์—”์ง€๋‹ˆ์–ด

โœ… ์ด ๊ธ€์„ ์ฝ์œผ๋ฉด ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • Playwright์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ Selenium๊ณผ์˜ ์ฐจ์ด์ 
  • E2E ํ…Œ์ŠคํŠธ์˜ ๊ฐœ๋…๊ณผ ์‹ค๋ฌด์—์„œ์˜ ํ™œ์šฉ ๋ฐฉ๋ฒ•
  • Playwright ร— Python ์…‹์—… ๋ฐฉ๋ฒ•
  • ๋กœ๊ทธ์ธ๋ถ€ํ„ฐ ์ฃผ๋ฌธ ์™„๋ฃŒ๊นŒ์ง€ ์ „์ฒด 10๊ฐœ ์ผ€์ด์Šค๋ฅผ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•

๐Ÿ‘จโ€๐Ÿ’ป ์ž‘์„ฑ์ž ์†Œ๊ฐœ

QA ์—”์ง€๋‹ˆ์–ด๋กœ์„œ ์‹ค๋ฌด์—์„œ PlaywrightยทSelenium์„ ํ™œ์šฉํ•œ ์ž๋™ํ™” ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ด๋‹นํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ ๊ธ€์—์„œ ์†Œ๊ฐœํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋Š” GitHub์— ๊ณต๊ฐœ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์‹ค์ œ๋กœ ๋™์ž‘ ํ™•์ธ์ด ์™„๋ฃŒ๋œ ์ฝ”๋“œ๋ฅผ ๊ทธ๋Œ€๋กœ ํ•ด์„คํ•ฉ๋‹ˆ๋‹ค.

E2E ํ…Œ์ŠคํŠธ๋ผ๊ณ  ํ•˜๋ฉด “์–ด๋ ค์šธ ๊ฒƒ ๊ฐ™๋‹ค”, “์„ค์ •์ด ๋ฒˆ๊ฑฐ๋กญ๋‹ค”๊ณ  ๋А๋ผ๋Š” ๋ถ„๋„ ๋งŽ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Playwright๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ € ์„ค์น˜๋ถ€ํ„ฐ ํ…Œ์ŠคํŠธ ์‹คํ–‰๊นŒ์ง€ ๋†€๋ผ์šธ ์ •๋„๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‹คํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ์—ฐ์Šต์šฉ ๋ฐ๋ชจ EC ์‚ฌ์ดํŠธ๋กœ ์œ ๋ช…ํ•œ SauceDemo๋ฅผ ๋Œ€์ƒ์œผ๋กœ, ๋กœ๊ทธ์ธ โ†’ ์ƒํ’ˆ ์ถ”๊ฐ€ โ†’ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํ™•์ธ โ†’ ์ฒดํฌ์•„์›ƒ โ†’ ์ฃผ๋ฌธ ์™„๋ฃŒ โ†’ ๋กœ๊ทธ์•„์›ƒ๊นŒ์ง€์˜ ์ „์ฒด ํ”Œ๋กœ์šฐ๋ฅผ Playwright ร— Python์œผ๋กœ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ดˆ๋ณด์ž๋„ ์‰ฝ๊ฒŒ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์„คํ•ฉ๋‹ˆ๋‹ค.


Playwright๋ž€?

Playwright๋Š” Microsoft๊ฐ€ ๊ฐœ๋ฐœํ•œ ๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ChromiumยทFirefoxยทWebKit์˜ ์„ธ ๊ฐ€์ง€ ๋ธŒ๋ผ์šฐ์ € ์—”์ง„์— ๋Œ€์‘ํ•˜๋ฉฐ, PythonยทJavaScriptยทTypeScriptยทJavaยทC# ๋“ฑ ์—ฌ๋Ÿฌ ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Selenium๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์ง€๋งŒ, ์…‹์—…์ด ์••๋„์ ์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ณ  ๋Œ€๊ธฐ ์ฒ˜๋ฆฌยท๋…นํ™” ๊ธฐ๋Šฅ ๋“ฑ์ด ํ‘œ์ค€ ํƒ‘์žฌ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์ด ํฐ ํŠน์ง•์ž…๋‹ˆ๋‹ค.

๋น„๊ต ํ•ญ๋ชฉSeleniumPlaywright
์…‹์—…ChromeDriver ๋ณ„๋„ ํ•„์š”playwright install ํ•œ ์ค„๋กœ ์™„๋ฃŒ
๋Œ€๊ธฐ ์ฒ˜๋ฆฌWebDriverWait ํ•„์š”wait_for_url๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ
์‹คํ–‰ ์†๋„๋ณดํ†ต๋น ๋ฆ„
๋…นํ™” ๊ธฐ๋Šฅ์—†์Œโœ… ํ‘œ์ค€ ํƒ‘์žฌ
slow_mo ๊ธฐ๋Šฅ์—†์Œโœ… ํ‘œ์ค€ ํƒ‘์žฌ

E2E ํ…Œ์ŠคํŠธ๋ž€?

E2E ํ…Œ์ŠคํŠธ๋Š” End-to-End ํ…Œ์ŠคํŠธ์˜ ์•ฝ์ž๋กœ, ์‹ค์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์กฐ์ž‘ํ•˜๋Š” ์ผ๋ จ์˜ ํ๋ฆ„์„ ๊ทธ๋Œ€๋กœ ์ž๋™ํ™”ํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธยทํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์™€ ๋‹ฌ๋ฆฌ ์‹ค์ œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ “๋กœ๊ทธ์ธ โ†’ ์ƒํ’ˆ ์„ ํƒ โ†’ ๊ตฌ๋งค ์™„๋ฃŒ”์™€ ๊ฐ™์€ ์‹ค์ œ ์‚ฌ์šฉ์ž ์กฐ์ž‘์„ ์žฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๏ผšํ•จ์ˆ˜ยท๋ฉ”์„œ๋“œ ๋‹จ์œ„๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๏ผš์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์„ ์กฐํ•ฉํ–ˆ์„ ๋•Œ์˜ ๋™์ž‘์„ ํ™•์ธ
  • E2E ํ…Œ์ŠคํŠธ๏ผš์‚ฌ์šฉ์ž ์กฐ์ž‘์˜ ์ „์ฒด ํ”Œ๋กœ์šฐ๋ฅผ ๋ธŒ๋ผ์šฐ์ € ๊ฒฝ์œ ๋กœ ํ™•์ธ โ† ์ด ๊ธ€์—์„œ ๋‹ค๋ฃจ๋Š” ๋‚ด์šฉ

E2E ํ…Œ์ŠคํŠธ๋Š” ๋ฆด๋ฆฌ์Šค ์ „ ์ตœ์ข… ํ™•์ธ์ด๋‚˜, ๋ฐฐํฌ๋งˆ๋‹ค ๊ธฐ๋ณธ ํ”Œ๋กœ์šฐ๊ฐ€ ๋ง๊ฐ€์ง€์ง€ ์•Š์•˜๋Š”์ง€๋ฅผ ์ž๋™์œผ๋กœ ์ฒดํฌํ•˜๋Š” ํšŒ๊ท€ ํ…Œ์ŠคํŠธ๋กœ ํŠนํžˆ ํšจ๊ณผ๋ฅผ ๋ฐœํœ˜ํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ์‚ฌ์ดํŠธ๏ผˆSauceDemo๏ผ‰

SauceDemo๋Š” Sauce Labs๊ฐ€ ์ œ๊ณตํ•˜๋Š” E2E ํ…Œ์ŠคํŠธ ์—ฐ์Šต์šฉ ๋ฐ๋ชจ EC ์‚ฌ์ดํŠธ์ž…๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธยท์ƒํ’ˆ ๋ชฉ๋กยท์žฅ๋ฐ”๊ตฌ๋‹ˆยท์ฒดํฌ์•„์›ƒ ๋“ฑ EC ์‚ฌ์ดํŠธ์˜ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์ด ๊ฐ–์ถฐ์ ธ ์žˆ์–ด ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ์—ฐ์Šต์— ์ตœ์ ์˜ ํ™˜๊ฒฝ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ด๋ฆ„๋น„๋ฐ€๋ฒˆํ˜ธํŠน์ง•
standard_usersecret_sauce์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๏ผˆ๋ฉ”์ธ ํ”Œ๋กœ์šฐ์—์„œ ์‚ฌ์šฉ๏ผ‰
locked_out_usersecret_sauce๋กœ๊ทธ์ธ ๋ถˆ๊ฐ€๏ผˆ๋„ค๊ฑฐํ‹ฐ๋ธŒ ํ…Œ์ŠคํŠธ์šฉ๏ผ‰
problem_usersecret_sauceUI ๋ฒ„๊ทธ ์žˆ์Œ
performance_glitch_usersecret_sauce์‘๋‹ต์ด ์˜๋„์ ์œผ๋กœ ๋А๋ฆผ

SauceDemo ๋กœ๊ทธ์ธ ํ™”๋ฉด Playwright E2E ํ…Œ์ŠคํŠธ ์ž๋™ํ™”

โ–ฒ SauceDemo ๋กœ๊ทธ์ธ ํ™”๋ฉด. ํ™”๋ฉด ํ•˜๋‹จ์— ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž ๋ชฉ๋ก๊ณผ ๊ณตํ†ต ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค

ํ™˜๊ฒฝ ๊ตฌ์ถ•๏ผˆPythonใƒปPlaywright๏ผ‰

์„ค์น˜

Playwright ์…‹์—…์€ ๋ช…๋ น์–ด 2์ค„๋กœ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ChromeDriver์˜ ์ˆ˜๋™ ๊ด€๋ฆฌ๋Š” ์ „ํ˜€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

pip install playwright
playwright install chromium

ํด๋” ๊ตฌ์„ฑ

์ด๋ฒˆ์—๋Š” ๊ฐ„๋‹จํ•œ 1ํŒŒ์ผ ๊ตฌ์„ฑ์ž…๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฐ์ƒท ํด๋”๋Š” ์‹คํ–‰ ์‹œ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

project/
โ”œโ”€โ”€ test_saucedemo.py       # ๋ฉ”์ธ ํ…Œ์ŠคํŠธ ์Šคํฌ๋ฆฝํŠธ
โ””โ”€โ”€ screenshots/            # ์‹คํ–‰ ์‹œ ์ž๋™ ์ƒ์„ฑ
    โ”œโ”€โ”€ ss_01_login_input.png
    โ”œโ”€โ”€ ss_02_after_login.png
    โ”œโ”€โ”€ ss_03_locked_user_error.png
    โ””โ”€โ”€ ...

๐Ÿ’ก Tip๏ผšscreenshots/ ํด๋”๋Š” ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ์‹œ os.makedirs()๋กœ ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ์ˆ˜๋™์œผ๋กœ ๋งŒ๋“ค ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ ํ•ด์„ค

์ฝ”๋“œ์˜ ํ•ต์‹ฌ ๋ถ€๋ถ„์„ ๋ฝ‘์•„์„œ ์ดˆ๋ณด์ž๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ ์ค„์”ฉ ์ƒ์„ธํžˆ ํ•ด์„คํ•ฉ๋‹ˆ๋‹ค. “์ฝ”๋“œ๋Š” ์ฝ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค”๋Š” ๋ถ€๋ถ„์„ ์—†์• ๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์ž…๋‹ˆ๋‹ค.

โ‘  ํผ์— ๊ฐ’ ์ž…๋ ฅํ•˜๊ธฐ๏ผšfill()

page.fill("#user-name", "standard_user")
page.fill("#password", "secret_sauce")

fill()์€ ์ž…๋ ฅ ํผ์— ๋ฌธ์ž๋ฅผ ์ž…๋ ฅํ•˜๋Š” Playwright ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. #user-name์€ ๋กœ๊ทธ์ธ ํ™”๋ฉด์˜ ์‚ฌ์šฉ์ž ์ด๋ฆ„ ํ•„๋“œ์˜ CSS ์…€๋ ‰ํ„ฐ๋กœ, HTML์˜ id="user-name"์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. Selenium์˜ send_keys()์— ํ•ด๋‹นํ•˜์ง€๋งŒ ํ•„๋“œ ์ดˆ๊ธฐํ™”์™€ ์ž…๋ ฅ์„ ์ž๋™์œผ๋กœ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•ด์ค๋‹ˆ๋‹ค.

SauceDemo ๋กœ๊ทธ์ธ ์—๋Ÿฌ ํ™”๋ฉด Playwright ์ž๋™ํ™” ํ…Œ์ŠคํŠธ

โ–ฒ ์ž˜๋ชป๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„ยท๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ–ˆ์„ ๋•Œ์˜ ์—๋Ÿฌ ํ‘œ์‹œ๏ผˆTC-03๏ผ‰

โ‘ก ๋ฒ„ํŠผ ํด๋ฆญ๏ผšclick()

page.click("#login-button")

click()์€ ์ง€์ •ํ•œ ์…€๋ ‰ํ„ฐ์˜ ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. #login-button์€ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์˜ ID์ž…๋‹ˆ๋‹ค. Playwright๋Š” ์š”์†Œ๊ฐ€ ํ‘œ์‹œ๋˜์–ด ํด๋ฆญ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ์ž๋™์œผ๋กœ ๋Œ€๊ธฐํ•œ ํ›„ ํด๋ฆญํ•˜๋ฏ€๋กœ Selenium์ฒ˜๋Ÿผ ๋ช…์‹œ์ ์ธ ๋Œ€๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋ณ„๋„๋กœ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

โ‘ข ํŽ˜์ด์ง€ ์ „ํ™˜ ๋Œ€๊ธฐ๏ผšwait_for_url()

page.wait_for_url("**/inventory.html", timeout=8000)

wait_for_url()์€ URL์ด ์ง€์ •๋œ ํŒจํ„ด์œผ๋กœ ๋ฐ”๋€” ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. **๋Š” ์™€์ผ๋“œ์นด๋“œ๋กœ ๋„๋ฉ”์ธ ๋ถ€๋ถ„์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. timeout=8000์€ 8์ดˆ ์ด๋‚ด์— ์ „ํ™˜๋˜์ง€ ์•Š์œผ๋ฉด ํƒ€์ž„์•„์›ƒ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์„ค์ •์ž…๋‹ˆ๋‹ค. Selenium์˜ WebDriverWait + expected_conditions ์กฐํ•ฉ์ด ์ด ํ•œ ์ค„๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค.

โ‘ฃ ์š”์†Œ ํ•„ํ„ฐ๋ง๏ผšfilter()

item = page.locator(".inventory_item").filter(has_text="Sauce Labs Backpack")
item.locator("button").click()

locator()๋กœ ์š”์†Œ๋ฅผ ์ทจ๋“ํ•˜๊ณ  filter(has_text=...)๋กœ ํŠน์ • ํ…์ŠคํŠธ๋ฅผ ํฌํ•จํ•œ ์š”์†Œ๋งŒ ์ถ”๋ ค๋ƒ…๋‹ˆ๋‹ค. ์ƒํ’ˆ๋ช…์œผ๋กœ ๋Œ€์ƒ ์•„์ดํ…œ์„ ํŠน์ •ํ•œ ํ›„ ๊ทธ ์•ˆ์˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋Š” ํ๋ฆ„์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์ƒํ’ˆ์ด ๋‚˜์—ด๋˜๋Š” ๋ชฉ๋ก ํ™”๋ฉด์—์„œ์˜ ์กฐ์ž‘์— ๋งค์šฐ ํŽธ๋ฆฌํ•œ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

โ‘ค ๋™์ž‘์„ ์Šฌ๋กœ์šฐ๋ชจ์…˜์œผ๋กœ๏ผšslow_mo

browser = p.chromium.launch(
    headless=False,
    slow_mo=800,   # ๊ฐ ์กฐ์ž‘์„ 800ms ์ง€์—ฐ
)

slow_mo๋Š” Playwright ๊ณ ์œ ์˜ ์˜ต์…˜์œผ๋กœ, ๊ฐ ์กฐ์ž‘ ์‚ฌ์ด์— ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„์˜ ์ง€์—ฐ์„ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. ๋””๋ฒ„๊น… ์‹œ๋‚˜ ๋™์ž‘ ํ™•์ธ ์‹œ์— ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ๋ˆˆ์œผ๋กœ ์ซ“์„ ์ˆ˜ ์žˆ์–ด ๋งค์šฐ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. CI/CD ํ™˜๊ฒฝ์—์„œ๋Š” slow_mo=0๏ผˆ๊ธฐ๋ณธ๊ฐ’๏ผ‰, ๋กœ์ปฌ ํ™•์ธ ์‹œ์—๋Š” slow_mo=800์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์‹ค๋ฌด ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก ์‹ค๋ฌด Tip๏ผšPage Object Model๏ผˆPOM๏ผ‰์— ๋Œ€ํ•ด
์‹ค๋ฌด์—์„œ๋Š” Page Object Model๏ผˆPOM๏ผ‰์„ ์‚ฌ์šฉํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์™€ ํŽ˜์ด์ง€ ์กฐ์ž‘์„ ๋ถ„๋ฆฌํ•˜๋Š” ์„ค๊ณ„๊ฐ€ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ํ•จ์ˆ˜ ๊ธฐ๋ฐ˜์˜ ๊ฐ„๋‹จํ•œ ๊ตฌ์„ฑ์ด์ง€๋งŒ, ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ๋Š˜์–ด๋‚˜๋ฉด LoginPage / CartPage ๋“ฑ์˜ ํด๋ž˜์Šค์— ์กฐ์ž‘์„ ๋ชจ์•„๋‘๋Š” ๊ฒƒ์œผ๋กœ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๋ฐฉ๋ฒ•

์‹คํ–‰ ๋ช…๋ น์–ด

python test_saucedemo.py

๐Ÿ’ก Tip๏ผšํ—ค๋“œ๋ฆฌ์Šค ๋ชจ๋“œ๏ผˆ๋ธŒ๋ผ์šฐ์ € ๋น„ํ‘œ์‹œ๏ผ‰๋กœ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์—๋Š” ์ฝ”๋“œ ๋‚ด์˜ headless=False๋ฅผ headless=True๋กœ ๋ณ€๊ฒฝํ•˜์„ธ์š”. CI/CD ํ™˜๊ฒฝ์—์„œ๋Š” True๊ฐ€ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

์‹คํ–‰ํ•˜๋ฉด ํ„ฐ๋ฏธ๋„์— ์„น์…˜๋ณ„ ๊ฒฐ๊ณผ๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ถœ๋ ฅ๋˜๊ณ , ๋งˆ์ง€๋ง‰์— ์ „์ฒด ํ…Œ์ŠคํŠธ์˜ ์š”์•ฝ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฐ์ƒท์€ screenshots/ ํด๋”์— ์ž๋™ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

==================================================
  SauceDemo Automated Test Suite [Playwright]
  Executed: 2025-07-01 10:00:00
==================================================

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  TC-02: Login Failure - Locked User
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  Error message: Epic sadface: Sorry, this user has been locked out.
    ๐Ÿ“ธ screenshots/ss_03_locked_user_error.png

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  TC-09: Order Completion
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  Completion message: Thank you for your order!
    ๐Ÿ“ธ screenshots/ss_10_order_complete.png

==================================================
  Test Result Summary
==================================================
  โœ… PASS  TC-02: Locked User Login Failure
           โ†’ Epic sadface: Sorry, this user has been locked out.
  โœ… PASS  TC-03: Wrong Password Login Failure
           โ†’ Epic sadface: Username and password do not match...
  โœ… PASS  TC-01: Login Success
           โ†’ //www.saucedemo.com/inventory.html
  โœ… PASS  TC-04: Product List Display (6 items)
           โ†’ 6 items displayed
  โœ… PASS  TC-05: Add 2 Items to Cart
           โ†’ Badge=2
  โœ… PASS  TC-06: Cart Contents Verification
           โ†’ Cart=2 / Added=2
  โœ… PASS  TC-07: Checkout Information Input
           โ†’ //www.saucedemo.com/checkout-step-two.html
  โœ… PASS  TC-08: Order Summary Verification
           โ†’ 2 items / Total: $19.42
  โœ… PASS  TC-09: Order Completion
           โ†’ Thank you for your order!
  โœ… PASS  TC-10: Logout
           โ†’ Redirected to login page
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  Total: 10   โœ… 10 Passed   โŒ 0 Failed
  Result: โœ… All Tests PASSED ๐ŸŽ‰
==================================================

์ „์ฒด 10๊ฐœ ์ผ€์ด์Šค๊ฐ€ PASS๊ฐ€ ๋˜๋ฉด ์„ฑ๊ณต์ž…๋‹ˆ๋‹ค. screenshots/ ํด๋”์—๋„ 11์žฅ์˜ ์Šคํฌ๋ฆฐ์ƒท์ด ์ž๋™ ์ €์žฅ๋˜์–ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

SauceDemo ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํ™”๋ฉด ์ƒํ’ˆ 2๊ฐœ ์ถ”๊ฐ€ Playwright E2E ํ…Œ์ŠคํŠธ

โ–ฒ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— 2๊ฐœ์˜ ์ƒํ’ˆ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ํ™•์ธ๏ผˆTC-06๏ผ‰

SauceDemo ์ฃผ๋ฌธ ์š”์•ฝ ํ•ฉ๊ณ„ ๊ธˆ์•ก ํ™•์ธ Playwright E2E ํ…Œ์ŠคํŠธ

โ–ฒ ์ฃผ๋ฌธ ์š”์•ฝ ํ™”๋ฉด. ์ƒํ’ˆ ์ˆ˜ยท์†Œ๊ณ„ยท์„ธ๊ธˆยทํ•ฉ๊ณ„ ๊ธˆ์•ก์„ ์ž๋™ ๊ฒ€์ฆ๏ผˆTC-08๏ผ‰

SauceDemo ์ฃผ๋ฌธ ์™„๋ฃŒ ํ™”๋ฉด Thank you for your order Playwright E2E ํ…Œ์ŠคํŠธ

โ–ฒ ใ€ŒThank you for your order!ใ€๊ฐ€ ํ‘œ์‹œ๋˜์–ด ์ฃผ๋ฌธ ์™„๋ฃŒ๋ฅผ ํ™•์ธ๏ผˆTC-09๏ผ‰

๋” ๋ฐœ์ „์‹œํ‚ค๋Š” ์•„์ด๋””์–ด

โšก pytestํ™”ํ•˜์—ฌ ๋ณ‘๋ ฌ ์‹คํ–‰

pytest-playwright์™€ ์กฐํ•ฉํ•˜๋ฉด ๋ณ‘๋ ฌ ์‹คํ–‰ยทํŒŒ๋ผ๋ฏธํ„ฐํ™”๊ฐ€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์‹คํ˜„๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“น ๋™์˜์ƒ ๋…นํ™” ๊ธฐ๋Šฅ

Playwright์—๋Š” ํ‘œ์ค€์œผ๋กœ ๋…นํ™” ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. record_video_dir์„ ์„ค์ •ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์ „์ฒด๋ฅผ ๋™์˜์ƒ์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“Š Allure ๋ฆฌํฌํŠธ ์—ฐ๋™

allure-pytest๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์Šคํฌ๋ฆฐ์ƒท์ด ์ฒจ๋ถ€๋œ ๋ณด๊ธฐ ์‰ฌ์šด HTML ๋ฆฌํฌํŠธ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿค– CI/CD ์—ฐ๋™

GitHub Actions๋‚˜ Jenkins์— ํ†ตํ•ฉํ•ด PR๋งˆ๋‹ค E2E ํ…Œ์ŠคํŠธ๋ฅผ ์ž๋™ ์‹คํ–‰ํ•˜๋Š” ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ํ™œ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค ๋ฐ ํ™•์žฅ ์˜ˆ์‹œ

  • ๋งค ๋ฆด๋ฆฌ์Šค ์ „ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ๋กœ ์ž๋™ ์‹คํ–‰
  • ์Šคํ…Œ์ด์ง• ํ™˜๊ฒฝ์—์„œ์˜ ๊ตฌ๋งค ํ”Œ๋กœ์šฐ ์ „์ฒด ์ •์ƒ ๋™์ž‘ ํ™•์ธ
  • ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๏ผˆproblem_userใƒปperformance_glitch_user๏ผ‰์—์„œ์˜ ๋™์ž‘ ๋น„๊ต ํ…Œ์ŠคํŠธ
  • ๋…นํ™” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๋™์˜์ƒ์„ ์—๋น„๋˜์Šค๋กœ ์ €์žฅ
  • pytestํ™”ํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ํŒŒ๋ผ๋ฏธํ„ฐํ™”ยท๋ณ‘๋ ฌ ์‹คํ–‰์œผ๋กœ ํ™•์žฅ
  • Slack Webhook ์—ฐ๋™์œผ๋กœ ํ…Œ์ŠคํŠธ ์‹คํŒจ ์‹œ ์ฆ‰์‹œ ์•Œ๋ฆผ

์ •๋ฆฌ

์ด ๊ธ€์—์„œ๋Š” Playwright์™€ Python์„ ์‚ฌ์šฉํ•ด SauceDemo์˜ ๋กœ๊ทธ์ธ๋ถ€ํ„ฐ ์ฃผ๋ฌธ ์™„๋ฃŒ๊นŒ์ง€์˜ E2E ํ…Œ์ŠคํŠธ๋ฅผ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•ด์„คํ–ˆ์Šต๋‹ˆ๋‹ค.

ํฌ์ธํŠธ๋‚ด์šฉ
ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋„ค๊ฑฐํ‹ฐ๋ธŒ 2๊ฑด๏ผ‹๋ฉ”์ธ ํ”Œ๋กœ์šฐ 8๊ฑด ์ด 10์ผ€์ด์Šค
๋Œ€๊ธฐ ์ฒ˜๋ฆฌwait_for_url๋กœ ๊ฐ„๋‹จํ•˜๊ณ  ํ™•์‹คํ•˜๊ฒŒ ํŽ˜์ด์ง€ ์ „ํ™˜ ๋Œ€๊ธฐ
์Šคํฌ๋ฆฐ์ƒท์ „ ์ผ€์ด์Šค์—์„œ ์ž๋™ ์ €์žฅยทํŒŒ์ผ๋ช…์œผ๋กœ ์–ด๋А ํ™”๋ฉด์ธ์ง€ ํ•œ๋ˆˆ์— ํŒŒ์•…
์š”์•ฝ ์ถœ๋ ฅresults ๋ฆฌ์ŠคํŠธ๋กœ ์ „ ์ผ€์ด์Šค์˜ ํ•ฉ๋ถˆ์„ ์ผ๊ด„ ๊ด€๋ฆฌยทํ‘œ์‹œ
์‹คํ–‰ ๋ชจ๋“œheadless / slow_mo๋กœ ๋กœ์ปฌยทCI ํ™˜๊ฒฝ์„ ๊ตฌ๋ถ„ํ•˜์—ฌ ์‚ฌ์šฉ

์‹ค๋ฌด์—์„œ๋Š” ์ด E2E ํ…Œ์ŠคํŠธ๋ฅผ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์— ํ†ตํ•ฉํ•˜๊ณ  ๋ฐฐํฌ๋งˆ๋‹ค ๊ตฌ๋งค ํ”Œ๋กœ์šฐ ์ „์ฒด๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ์ž๋™ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. Playwright๋Š” Selenium๋ณด๋‹ค ๊ธฐ์ˆ ์ด ๊ฐ„๋‹จํ•˜๊ณ , ๋…นํ™” ๊ธฐ๋Šฅ์ด๋‚˜ slow_mo ๋“ฑ ์‹ค๋ฌด์—์„œ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์ด ํ‘œ์ค€ ํƒ‘์žฌ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์ด ํฐ ๋งค๋ ฅ์ž…๋‹ˆ๋‹ค.

์†Œ์Šค ์ฝ”๋“œ๋Š” GitHub์— ๊ณต๊ฐœ๋˜์–ด ์žˆ์œผ๋‹ˆ ๊ผญ ์ง์ ‘ ์‹คํ–‰ํ•ด๋ณด์„ธ์š”๏ผ

์ œ๋ชฉ๊ณผ URL์„ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค