Kubernetes 이야기

Playwright와 Python 사용 방법 본문

개발/python

Playwright와 Python 사용 방법

kmaster 2023. 2. 22. 22:08
반응형

Playwright는 다음을 참고한다. 이번에는 Python을 활용하여 Playwright 를 사용하는 방법에 대해 알아보자.

 

playwright를 활용한 e2e 테스트

Playwright는 최신 웹 앱에 대한 신뢰할 수 있는 종단 간 테스트를 지원하는 테스트 자동화 도구이다. Playwright는 Chromium, WebKit 및 Firefox를 포함한 모든 최신 렌더링 엔진을 지원한다. 설치 설치는 npm

kmaster.tistory.com

 

Playwright에서 예제를 보면 다음과 같이 스크립트를 생성한다.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context()
    page = context.new_page()

 

fixture

pytest-playwright 플러그인은 fixture를 사용하여 python의 자동처리를 지원할 수 있도록 한다.

 

fixture에는 Session 브라우저 범위가 있다. 이것은 모든 테스트가 하나의 브라우저 인스턴스를 공유한다는 의미이다.

또한  테스트가 완료된 후 모든 것을 자동으로 정리한다. 즉 브라우저를 명시적으로 닫을 필요는 없다.

from playwright.sync_api import Page

def test_http_get(page):
    page.goto('https://httpbin.org')

 

Playwright는 selector를 사용하여 페이지의 모든 요소를 찾을 수 있다. selector 에는 다음과 같은 유형이 있다.

  • Text
  • CSS
  • XPath
  • N-th element
  • React
  • Vue
  • ID attributes

[xpath 예]

page.locator('xpath=//*[@id="operations-tag-HTTP_Methods"]/a').click()

[실행]

pytest test.py --headed

 

brower context 정의 예제

@pytest.fixture(scope="session")
def browser_context_args(browser_context_args, playwright):
    return {
        **browser_context_args,
        "ignore_https_errors": True,
        "locale": "ko-KR",
        "timezone_id": "Asia/Seoul",
        "viewport": {
            "width": 1920,
            "height": 1080,
        }
    }

 

assert

Playwright로 수행한 테스트 결과에 대해 검증하는 것은 매우 중요한 일이다. 검증을 위해 expect 함수를 사용한다.

 

[테스트 시나리오]

HTTP Methods 에서 /get method를 선택하여 실행하면 200 code가 리턴되는지 검증한다.

from playwright.sync_api import expect, Page

def test_http_get(page):
    page.goto('https://httpbin.org')
    page.locator('xpath=//*[@id="operations-tag-HTTP_Methods"]/a').click()

    page.locator('xpath=//*[@id="operations-HTTP Methods-get_get"]/div[1]/div').click()
    page.locator('xpath=//*[@id="operations-HTTP Methods-get_get"]/div[2]/div/div[1]/div[1]/div[2]/button').click()

    page.locator('xpath=//*[@id="operations-HTTP Methods-get_get"]/div[2]/div/div[2]/button[1]').click()
    expect(page.locator('xpath=//*[@id="operations-HTTP Methods-get_get"]/div[2]/div/div[3]/div[2]/div/div/table/tbody/tr/td[1]')).to_contain_text('200')
    #expect(page.locator('#operations-HTTP\ Methods-get_get > div:nth-child(2) > div > div.responses-wrapper > div.responses-inner > div > div > table > tbody > tr > td.col.response-col_status')).to_have_value('200')

 

[실행결과]

# pytest test.py
test.py .                                                                                                                   [100%]

======================================================== 1 passed in 8.74s ========================================================

 

만약 500으로 체크한다면, 다음과 같은 오류가 발생한다.

est.py:11: AssertionError
===================================================== short test summary info =====================================================
FAILED test.py::test_http_get[chromium] - AssertionError: Locator expected to contain text '500'
======================================================= 1 failed in 10.81s ========================================================

 

Assertions 은 https://playwright.dev/python/docs/test-assertions 를 참고한다.

 

Refactoring

Playwriget 호출시마다 원시적인 방법을 사용한다면 코드 중복이 이어질 수 있다. 예를들어 테스트하려면 페이지 기능이 회원과 게시판이 있다고 가정해 보자.

게시판에 회원이 글을 올릴때 회원정보를 필요로 할 수 있다.  (혹은 게시글 등록 전 회원 등록 후 게시글 등록 시나리오 등을 만들 수 있다. )

 

예) Member Class

from playwright.sync_api import Page

class MemberPage:

    URL = 'https://www.example.com'

    def __init__(self, page: Page) -> None:
        self.page = page
        self.insert_button = page.locator('#insert_button')
        self.insert_text_id = page.locator('#insert_text_id')
        self.insert_text_name = page.locator('#insert_text_name')
        self.insert_submit_button = page.locator('#insert_submit_button')
        
        self.search_input = page.locator('#search_form_input')
        self.search_button = page.locator('#search_button')
        self.search_result = page.locator('a[data-id="result-member"]')
    
    def load(self) -> None:
        self.page.goto(self.URL)
    
    def search(self, search_word: str) -> None:
        self.search_input.fill(search_word)
        self.search_button.click()
        self.search_result = 
        
    def insert(self, id: str, name: str) -> None:
        self.insert_button.click()
        self.insert_text_id.fill(id)
        self.insert_text_name.fill(name)
        self.insert_submit_button.click()
        
    def result_link_members(self) -> List[str]:
        self.result_links.nth(4).wait_for()
        return self.result_links.all_text_contents()
    
    def result_link_members_contain_phrase(self, phrase: str, minimum: int = 1) -> bool:
        titles = self.result_link_members()
        matches = [t for t in titles if phrase.lower() in t.lower()]
        return len(matches) >= minimum

필요한 Class를 만들었으면, 테스트코드는 다음과 같이 호출한다. (예시)

import pytest

from pages.member import MemberPage
from playwright.sync_api import expect, Page

MEMBERS = [
    ("1","member1"),
    ("2","member2")
]

@pytest.mark.parametrize("id, name", MEMBERS)
def test_member (
    id: str,
    name: str,
    page: Page,
    member_page: MemberPage) -> None:
  
    member_page.load()
    
    member_page.insert(id, name)
    member_page.search(name)

    assert member_page.result_link_member_contain_phrase(name)

 

 

반응형

'개발 > python' 카테고리의 다른 글

ChatGPT API 사용  (0) 2023.03.27
mitmproxy을 사용하여 K8S API Server Reverse Proxy 설정하기  (0) 2023.02.22
playwright를 활용한 e2e 테스트  (0) 2023.02.15
Python에서 gRPC 구현  (0) 2023.02.13
Kopf ( 예제 )  (1) 2023.02.05
Comments