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.

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)                    

Scroll to Top