TIL

Playwright Python: Tutorial #4 - Browser Context

아람2 2025. 2. 27. 14:49
반응형

Playwright Python: Tutorial #4 - Browser Context

Tutorial #1 https://helloahram.tistory.com/221 
Tutorial #2 https://helloahram.tistory.com/222
Tutorial #3 https://helloahram.tistory.com/223

 

 

Browser Context 

Playwright 공식 문서 https://playwright.dev/python/docs/api/class-browsercontext 

 

BrowserContext는 여러 개의 독립적인 브라우저 세션을 운영하는 방법을 제공한다 

Browser 에 Cookie 를 넣을 수도 있고, 테스트 환경을 격리하여 성능을 최적화 할 수도 있다 

# https://youtu.be/uX4pehDO4i4?si=K9ISdOxIWJXRckrI

import asyncio
from playwright.async_api import async_playwright, expect

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context()
        await context.tracing.start(screenshots=True, snapshots=True, sources=True)
        page = await context.new_page()
        await page.set_viewport_size({"width": 1800, "height": 1200})
        await page.goto("https://demoqa.com/checkbox")
        
        # Action 
        await page.check('label[for="tree-node-home"]')
        await page.screenshot(path="screenshots/checkboxes.png")
        
        # Assertion 
        await page.is_checked('label[for="tree-node-home"]') is True
        await expect(page.locator("#result")).to_have_text("You have selected :homedesktopnotescommandsdocumentsworkspacereactangularveuofficepublicprivateclassifiedgeneraldownloadswordFileexcelFile")
        
        # Stoping Tracing 
        await context.tracing.stop(path="logs/trace.zip")
        
        # Closing Browser 
        await browser.close() 

asyncio.run(main())

 

코드 설명 

Import Library 

asyncio - 비동기 처리를 위해 사용되는 Python 표준 라이브러리

async_playwright - Playwright 의 비동기 API 를 사용하기 위한 라이브러리, Playwright 를 통해 브라우저 자동화 작업을 수행한다 

expect - Playwright 의 Assertion 라이브러리로, 웹 페이지에서 특정 요소의 상태를 확인할 때 사용한다 

import asyncio
from playwright.async_api import async_playwright, expect

 

Main 비동기 함수 

비동기적으로 실행되는 Main 함수, 모든 Playwright 관련 작업이 이 함수 내에서 실행된다 

async def main():

 

async_playwright() 사용

Playwright 를 비동기 방식으로 시작

async with 문을 사용하여 Playwright 의 세션을 관리하고 종료할 때 자동으로 리소스를 정리한다

    async with async_playwright() as p:

 

브라우저 인스턴스 생성 

Chromium 브라우저 인스턴스 실행

headless=False 옵션은 브라우저가 실제로 UI 가 띄워지고, headless=True이면 UI 없이 백그라운드에서 실행된다 

browser = await p.chromium.launch(headless=False)

 

브라우저 컨텍스트 생성 

새로운 브라우저 컨텍스트 생성

각 컨텍스트는 독립적인 브라우저 환경을 제공하고, 여러 사용자 세션을 시뮬레이션할 수 있다 

context = await browser.new_context()

 

Tracing 시작 

Tracing 을 시작하여 페이지 스크린샷, 스냅샷, 소스 정보 등 기록 

테스트를 디버깅하고 트레이스를 기록할 때 유용하다 

await context.tracing.start(screenshots=True, snapshots=True, sources=True)

 

새 페이지 생성 및 초기화 

새로운 페이지를 생성하고, 페이지의 뷰포트 크기 (1800x1200) 를 설정한다

page = await context.new_page()
await page.set_viewport_size({"width": 1800, "height": 1200})

 

웹 페이지로 이동 

지정된 URL (https://demoqa.com/checkbox) 로 이동 

이 페이지는 체크박스를 포함하는 데모 페이지이고, 그 외 다른 테스트도 가능하다 

await page.goto("https://demoqa.com/checkbox")

 

체크박스 선택  

페이지 내에서 label[for="tree-node-home"] 라는 요소 (체크박스) 선택 

await page.check('label[for="tree-node-home"]')

 

스크린샷 찍기 

현재 페이지의 스크린샷을 찍고 "screenshots/checkboxes.png" 경로에 저장 

이 스크린샷은 체크박스를 선택한 후의 상태를 보여준다

await page.screenshot(path="screenshots/checkboxes.png")

 

체크 상태 확인 

체크박스가 선택되었는지 확인하는 코드

is_checked()는 해당 요소가 체크된 상태인지 확인하고, True이면 선택됨을 의미한다 

await page.is_checked('label[for="tree-node-home"]') is True

 

문자열 확인 

페이지에서 #result ID를 가진 요소가 특정 텍스트를 포함하는지 확인 

이 부분은 체크박스를 선택한 후 결과 메시지가 제대로 나타나는지 확인하는 부분이다 

await expect(page.locator("#result")).to_have_text("You have selected :homedesktopnotescommandsdocumentsworkspacereactangularveuofficepublicprivateclassifiedgeneraldownloadswordFileexcelFile")

 

Tracing 중지 및 로그 저장 

Tracing 를 중지하고 기록된 트레이스를 logs/trace.zip 파일로 저장 

트레이스는 테스트 실행 중 발생한 모든 이벤트를 기록하여 나중에 분석할 수 있다

await context.tracing.stop(path="logs/trace.zip")

 

브라우저 종료 

await browser.close()

 

Tracing 확인 

위의 코드를 실행시킨 후 생성된 trace.zip 은 아래 명령어로 확인할 수 있다 

playwright show-trace logs/trace.zip

 

Clicks.py

# https://youtu.be/uX4pehDO4i4?si=_73zCUVaMChBsHzS

# to run this: python 08_Clicks.py
import asyncio
from playwright.async_api import async_playwright, expect

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context()
        await context.tracing.start(screenshots=True, snapshots=True, sources=True)
        page = await context.new_page()

        await page.set_viewport_size({"width": 1800, "height": 1200})
        await page.goto("https://demoqa.com/buttons")
        
        #- Generic Click - Dynamic Selector
        button = page.locator("text=Click Me").nth(2)
        await button.click()
        await page.screenshot(path="screenshots/dynamicClick.png")
        #-Assertion
        await expect(page.locator("#dynamicClickMessage")).to_have_text("You have done a dynamic click")
        #- Double Click 
        button = page.locator("text=Click Me").nth(0)
        await button.dblclick()
        await page.screenshot(path="screenshots/doubleClick.png")
        #-Assertion
        await expect(page.locator("#doubleClickMessage")).to_have_text("You have done a double click")
        #-Stoping Tracing
        await context.tracing.stop(path = "logs/trace.zip")
        #-Closing browser
        await browser.close()
        # #- Right Click - Asking behavior at: https://github.com/microsoft/playwright-python/issues/1426
        # button = page.locator("text=Click Me").nth(1)
        # await button.click(button="right")
        # await page.screenshot(path="rightClick.png")
        # #-Assertion
        # await expect(page.locator("#doubleClickMessage")).to_have_text("You have done a right click")
        # #-Closing browser
        # await browser.close()

asyncio.run(main())

nth()

Playwright 에서 Locator, 로케이터를 사용하여 특정 인덱스의 요소를 선택하는 메서드이다 

예를 들어, page.locator("text=Click Me").nth(2) 는 "Click Me" 라는 텍스트가 포함된 요소들 중 세 번째 요소를 선택한다 

이 메서드는 페이지 내에서 동일한 텍스트나 클래스를 가진 여러 요소가 있을 때, 특정 인덱스를 사용하여

원하는 요소를 지정할 수 있게 해준다, nth(0) 은 첫 번째 요소를, nth(1) 은 두 번째 요소를 선택하는 방식이다 

 

python 으로 코드를 실행하고 playwright show-trace logs/trace.zip 로 결과와 Snapshot 을 확인할 수 있다 

Options.py

# https://youtu.be/uX4pehDO4i4?si=XBK8_fLLrc3wCjRh

#to run this: python 09_Options.py
import asyncio
from playwright.async_api import async_playwright, expect

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context()
        await context.tracing.start(screenshots=True, snapshots=True, sources=True)
        page = await context.new_page()
        await page.set_viewport_size({"width": 1800, "height": 1200})
        await page.goto("https://demoqa.com/select-menu")
        #-Actions
        await page.select_option('select#cars', ['volvo', 'saab', 'audi'])
        await page.screenshot(path="screenshots/options.png")
        #-Stoping Tracing
        await context.tracing.stop(path = "logs/trace.zip")
        #-Closing browser
        await browser.close()

asyncio.run(main())

 

HTML 페이지에서 select#cars 는 "cars" 라는 ID 를 가진 <select> 요소를 의미한다 

이 요소는 사용자가 여러 옵션을 선택할 수 있는 드롭다운 메뉴로, Standard Multi Select 항목에 해당한다 

 

RadioButton.py

# https://youtu.be/uX4pehDO4i4?si=XBK8_fLLrc3wCjRh

#to run this: python 10_RadioButton.py
import asyncio
from playwright.async_api import async_playwright, expect

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context()
        await context.tracing.start(screenshots=True, snapshots=True, sources=True)
        page = await context.new_page()
        await page.set_viewport_size({"width": 1800, "height": 1200})
        await page.goto("https://demoqa.com/radio-button")
        #-Actions
        await page.check("#yesRadio", force=True)
        await page.screenshot(path="screenshots/radioButton.png")
        #-Assertions
        await page.is_checked("#yesRadio") is True
        await expect(page.locator(".text-success")).to_have_text("Yes")
        #-Stoping Tracing
        await context.tracing.stop(path = "logs/trace.zip")
        #-Closing browser
        await browser.close()

asyncio.run(main())

 

page.check() 메소드에서 사용되는 force=True 는 해당 요소가 비활성화되었거나

다른 이유로 클릭할 수 없을 때 강제로 선택을 수행하도록 만든다 

#yesRadio 가 비활성화되어 있거나, 다른 UI 요소에 의해 막혀 있을 때 force=True 를 지정하면

해당 라디오 버튼을 강제로 클릭하도록 할 수 있다 

 

 

 

반응형