Skip to content
Merged

uv #196

Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/devRun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: psf/black@stable
- uses: isort/isort-action@v1
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand All @@ -23,7 +21,7 @@ jobs:
- name: Create venv & install dependencies
run: |
uv venv
uv pip sync uv.lock
uv sync --all-extras --dev
- name: Install Playwright Browsers
run: |
PLAYWRIGHT_VERSION=$(grep -E '^playwright = "[^"]*"' pyproject.toml | sed -E 's/playwright = "([^"]*)".*$/\1/')
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Create venv & install dependencies
run: |
uv venv
uv pip sync uv.lock
uv sync --all-extras --dev
- name: Install Playwright Browsers
run: |
PLAYWRIGHT_VERSION=$(grep -E '^playwright = "[^"]*"' pyproject.toml | sed -E 's/playwright = "([^"]*)".*$/\1/')
Expand Down
10 changes: 5 additions & 5 deletions .github/README.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
![YouTube Channel](https://img.shields.io/youtube/channel/subscribers/UCQjS-eoKl0a1nuP_dvpLsjQ?label=YouTube%20Channel)
![dev run](https://github.com/nirtal85/Playwright-Python-Example/actions/workflows/devRun.yml/badge.svg)
![nightly](https://github.com/nirtal85/Playwright-Python-Example/actions/workflows/nightly.yml/badge.svg)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

## 📃 Articles written about this project

Expand Down Expand Up @@ -50,15 +50,15 @@ cd playwright-python
pip install uv
uv venv
.\env\Scripts\activate
uv pip sync uv.lock
uv sync --all-extras --dev
```

#### For Mac:
```bash
python3 -m pip install uv
uv venv
source .venv/bin/activate
uv pip sync uv.lock
source .venv/bin/activate
uv sync --all-extras --dev
```

### Install playwright
Expand Down
76 changes: 45 additions & 31 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "playwright-python"
version = "0.1.0"
description = "Playwright Python example project with pytest and Allure report"
authors = [{ name = "nirtal85", email = "nirt236@gmail.com" }]
requires-python = "~=3.11"
readme = "README.md"
keywords = [
"playwright",
"automation",
"testing",
"web",
]
dependencies = [
"allure-pytest==2.13.5",
"axe-playwright-python==0.1.4",
"playwright==1.51.0",
"pytest==8.3.5",
"pytest-base-url==2.1.0",
"pytest-playwright==0.7.0",
"pytest-split==0.10.0",
"requests==2.32.3",
]
requires = ["hatchling"]

[dependency-groups]
dev = [
"black==25.1.0",
"isort==6.0.1",
"pre-commit==4.2.0",
"ruff==0.11.4",
"pre-commit==4.2.0"
]

[tool.isort]
profile = "black"
skip = ["env", "venv"]
[project]
authors = [{name = "nirtal85", email = "nirt236@gmail.com"}]
dependencies = [
"allure-pytest==2.13.5",
"axe-playwright-python==0.1.4",
"playwright==1.51.0",
"pytest==8.3.5",
"pytest-base-url==2.1.0",
"pytest-playwright==0.7.0",
"pytest-split==0.10.0",
"requests==2.32.3"
]
description = "Playwright Python example project with pytest and Allure report"
keywords = [
"playwright",
"automation",
"testing",
"web"
]
name = "playwright-python"
readme = "README.md"
requires-python = "~=3.11"
version = "0.1.0"

[tool.hatch.build.targets.sdist]
include = ["playwright_python"]

[tool.hatch.build.targets.wheel]
include = ["playwright_python"]

[tool.isort]
profile = "black"
skip = ["env", "venv"]

[tool.pytest.ini_options]
addopts = [
"--clean-alluredir",
Expand All @@ -68,3 +67,18 @@ log_cli_level = "INFO"
markers = [
"devRun: marks tests that run before merge to the main branch"
]

[tool.ruff]
exclude = [".venv", "env"]
ignore = [
"D203", # One blank line required before class docstring (conflicts with D211)
"D213", # Multi-line docstring summary should start at the second line
"COM812"
]
line-length = 100
select = ["ALL"]
target-version = "py311"

[tool.ruff.format]
docstring-code-format = true
quote-style = "double"
1 change: 0 additions & 1 deletion tests/accesability_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


class TestAccessibility:

@allure.title("Test Accessibility with Default Counts")
def test_accessibility_default_counts(self, axe_playwright, page):
axe_playwright.check_accessibility(page)
Expand Down
1 change: 0 additions & 1 deletion tests/checkout_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@


class TestCheckout:

@pytest.mark.parametrize(
"browser_context_args", [User.STANDARD_USER], indirect=True
)
Expand Down
17 changes: 12 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Dict

import allure
import pytest
import requests
Expand Down Expand Up @@ -27,6 +25,7 @@ def goto(page: Page, request: SubRequest):

Example:
@pytest.mark.parametrize('browser_context_args', ["standard_user"], indirect=True)

"""
if request.getfixturevalue("browser_context_args").get("storage_state"):
page.goto("/inventory.html")
Expand All @@ -43,27 +42,31 @@ def axe_playwright():

Returns:
AxeHelper: An instance of AxeHelper with Axe initialized.

"""
yield AxeHelper(Axe())
return AxeHelper(Axe())


@pytest.fixture(scope="function")
def browser_context_args(
browser_context_args: Dict, base_url: str, request: SubRequest
browser_context_args: dict, base_url: str, request: SubRequest
):
"""This fixture allows setting browser context arguments for Playwright.

Args:
browser_context_args (dict): Base browser context arguments.
request (SubRequest): Pytest request object to get the 'browser_context_args' fixture value.
base_url (str): The base URL for the application under test.

Returns:
dict: Updated browser context arguments.

See Also:
https://playwright.dev/python/docs/api/class-browser#browser-new-contex

Returns:
dict: Updated browser context arguments.

"""
context_args = {
**browser_context_args,
Expand All @@ -85,7 +88,7 @@ def browser_context_args(


@pytest.fixture(scope="session")
def browser_type_launch_args(browser_type_launch_args: Dict, playwright: Playwright):
def browser_type_launch_args(browser_type_launch_args: dict, playwright: Playwright):
"""Fixture to set browser launch arguments.

This fixture updates the browser launch arguments to start the browser maximized
Expand All @@ -103,6 +106,7 @@ def browser_type_launch_args(browser_type_launch_args: Dict, playwright: Playwri

See Also:
https://playwright.dev/python/docs/api/class-browsertype#browser-type-launch

"""
playwright.selectors.set_test_id_attribute("data-test")
return {**browser_type_launch_args, "args": ["--start-maximized"]}
Expand All @@ -113,6 +117,7 @@ def get_public_ip() -> str:

Returns:
str: Public IP address.

"""
return requests.get(
"http://checkip.amazonaws.com",
Expand All @@ -129,6 +134,7 @@ def attach_playwright_results(page: Page, request: FixtureRequest):
Args:
page (Page): Playwright page object.
request: Pytest request object.

"""
yield
if request.node.rep_call.failed:
Expand Down Expand Up @@ -158,6 +164,7 @@ def pytest_runtest_makereport(item: Item):

Yields:
Outcome of the test execution.

"""
outcome = yield
rep = outcome.get_result()
Expand Down
1 change: 0 additions & 1 deletion tests/inventory_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@


class TestInventory:

@pytest.mark.parametrize(
"browser_context_args", [User.STANDARD_USER], indirect=True
)
Expand Down
4 changes: 1 addition & 3 deletions utilities/axe_helper.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import json
from collections import Counter
from typing import Dict

import allure
from axe_playwright_python.sync_playwright import Axe
from playwright.sync_api import Page


class AxeHelper:

def __init__(self, axe: Axe):
self.axe = axe

def check_accessibility(
self, page: Page, maximum_allowed_violations_by_impact: Dict[str, int] = None
self, page: Page, maximum_allowed_violations_by_impact: dict[str, int] = None
Comment on lines 13 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improved type hinting with modern syntax

The change from Dict[str, int] to dict[str, int] is appropriate and follows modern Python typing practices (Python 3.9+) where built-in container types can be used directly as type annotations.

However, there's a static analysis issue to fix:

- def check_accessibility(
-     self, page: Page, maximum_allowed_violations_by_impact: dict[str, int] = None
+ def check_accessibility(
+     self, page: Page, maximum_allowed_violations_by_impact: dict[str, int] | None = None

This change addresses the warning about implicit Optional types and makes the parameter typing more explicit.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def check_accessibility(
self, page: Page, maximum_allowed_violations_by_impact: Dict[str, int] = None
self, page: Page, maximum_allowed_violations_by_impact: dict[str, int] = None
def check_accessibility(
self, page: Page, maximum_allowed_violations_by_impact: dict[str, int] | None = None
🧰 Tools
🪛 Ruff (0.8.2)

14-14: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)

) -> None:
"""Checks accessibility of the page using playwright axe.

Expand Down
Loading