Run the sample Playwright Python visual test
Step 1: Setup environment
Requirements
- Python 3
- Pytest framework
- Playwright framework
- Access key
- You can generate an Access key using the following instruction – Access key
- Billing unit
- The billing unit is your team’s unique identifier, or just the word “personal” in the case of an individual account.
More information can be found here.
- The billing unit is your team’s unique identifier, or just the word “personal” in the case of an individual account.
Step 2: Add the interaction with visual testing API
After setup up the environment, you need to add the interaction with the visual testing API:
from typing import Optional
import pytest
import requests
from pydantic import BaseModel, Field
class VisualBuildInputData(BaseModel):
name: str
project: str
branch: str
class VisualSnapshotInputData(BaseModel):
name: str
build_id: str
image: Path
test_name: Optional[str]
suite_name: Optional[str]
browser: Optional[str]
class VisualBuildData(BaseModel):
id: str
name: str
project: str
branch: str
status: str
class VisualSnapshotData(BaseModel):
id: str
name: str
build_id: str = Field(alias="buildId")
test_name: str = Field(alias="testName")
suite_name: str = Field(alias="suiteName")
browser: Optional[str]
class VisualTestingAPI:
def __init__(self, base_url: str, api_key: str):
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
self.api_key = api_key
def create_build(self, input_data: VisualBuildInputData) -> VisualBuildData:
url = f"{self.base_url}/builds"
response = requests.post(url, headers=self.headers, json=input_data.dict())
response.raise_for_status() # Raise an error if the request failed
return VisualBuildData(**response.json())
def finish_build(self, build_id: str) -> None:
url = f"{self.base_url}/builds/{build_id}/finish"
response = requests.post(url, headers=self.headers)
response.raise_for_status()
def submit_snapshot(self, data: VisualSnapshotInputData) -> VisualSnapshotData:
url = f"{self.base_url}/builds/{data.build_id}/snapshots"
files = {
"image": (data.image.name, open(data.image, "rb"), "image/png")
}
payload = {
"name": data.name,
"testName": data.test_name,
"suiteName": data.suite_name,
"browser": data.browser,
}
response = requests.post(url, headers={"Authorization": f"Bearer {self.api_key}"}, files=files, data=payload)
response.raise_for_status() # Raise an error if the request failed
return VisualSnapshotData(**response.json())
Step 3: Run sample test
After setup up the environment and integrating the visual testing API, you can run your first web visual test
from playwright.sync_api import sync_playwright, Page, expect
import tempfile
from pathlib import Path
from typing import Optional
import pytest
import requests
from pydantic import BaseModel, Field
BILLING_UNIT = '<TEAM_CODE>'
ACCESS_TOKEN = 'mobitru_ak_...'
MOBITRU_HOST = 'browserhub-us.mobitru.com'
BROWSER_NAME = 'chrome'
PW_VERSION = '1.55.0'
VISUAL_TESTING_API_HOST = "visual.mobitru.com"
VISUAL_TESTING_API_BASE_URL = f"https://{VISUAL_TESTING_API_HOST}/billing/unit/{BILLING_UNIT}/api/v1"
@pytest.fixture()
def visual_testing_api(request):
return VisualTestingAPI(base_url=VISUAL_TESTING_API_BASE_URL, api_key=ACCESS_TOKEN)
@pytest.fixture()
def visual_testing_build(visual_testing_api):
"""create a new build """
build_input_data = VisualBuildInputData(name='Build 1', project='Python Web Playwright Automation Demo', branch='master')
build_data = visual_testing_api.create_build(build_input_data)
yield build_data
visual_testing_api.finish_build(build_data.id)
@pytest.fixture(scope="function")
def mobitru_page(request):
with sync_playwright() as playwright:
chromium = playwright.chromium
ws_endpoint = f"wss://{BILLING_UNIT}:{ACCESS_TOKEN}@{MOBITRU_HOST}/playwright/{BROWSER_NAME}/playwright-{PW_VERSION}?enableVideo=false"
browser = chromium.connect(ws_endpoint=ws_endpoint)
page = browser.new_page()
page.goto("https://www.mobitru.com/")
yield page
browser.close()
def test_contact_us_button(mobitru_page: Page, visual_testing_api, visual_testing_build):
# Expect contact us button to ve visible
expect(mobitru_page.locator("button[class*='request-demo']")).to_be_visible()
submit_snapshot(mobitru_page, result_name='after_open_url', test_name=visual_testing_build.name,
visual_build_data=visual_testing_build,
visual_testing_api=visual_testing_api)
def submit_snapshot(
page,
result_name,
test_name,
visual_build_data: VisualBuildData,
visual_testing_api: VisualTestingAPI
) -> VisualSnapshotData:
# Capture a screenshot and return the temporary file path
screenshot_path = capture_screenshot(page)
# Build VisualSnapshotInputData
snapshot_input_data = VisualSnapshotInputData(
name=result_name,
build_id=visual_build_data.id,
test_name=test_name,
browser=page.context.browser.browser_type.name,
suite_name=visual_build_data.project, # Assuming suite name is the project name
image=screenshot_path # Screenshot file
)
return visual_testing_api.submit_snapshot(snapshot_input_data)
def capture_screenshot(page) -> Path:
with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix=".png") as tmp_file:
# Get the path of the temporary file
screenshot_path = tmp_file.name
page.screenshot(path = screenshot_path) # Save the screenshot
return Path(screenshot_path)