Skip to main content

Selenium integration for the tquality test automation framework, built on tquality-py-core.

Project description

tquality-py-selenium

Languages: English · Русский

Selenium integration built on top of tquality-py-core.

Components

  • SeleniumConfig — extension of BaseConfig with a browser selector field and separate nested blocks chrome, firefox, edge, safari, undetected_chrome (all blocks coexist), plus a nested screencast block for step video recording.
  • BrowserType — enum: chrome, firefox, edge, safari, undetected-chrome. Per-OS availability is checked by OSUtils at browser startup (with an immediate failure on mismatch).
  • BaseElement and the typed subclasses Button, Input, CheckBox, Label with a full surface: click, text, get_attribute, wait.until_* (element.wait returns a per-element ElementWaiterbutton.wait.until_clickable().click()), js_actions (lazily bound to the element).
  • BaseForm — page base class with title, current_url, element_factory (resolved via the composition root).
  • SeleniumServices — composition root (a dependency-injector container). Subclass it to add or replace any service.

Services

  • BrowserServiceWebDriver wrapper; parameters are taken from config.active_browser.
  • Waiter — explicit waits at the page level. Element-level waits are exposed per-element via element.wait (returns a per-element ElementWaiter[Self]); chainable methods return the bound element.
  • ElementFactory — element factory.
  • JsActions + ElementJsActions — JavaScript actions on the page and on individual elements.
  • CollectionFactory — Pydantic-model collection factory backed by the DOM (+ DomField.css/xpath).
  • SeleniumScreenshotProvider — screenshots for steps at the CRITICAL log level.
  • SeleniumScreencastProvider — webm video recording (VP9 via imageio-ffmpeg) for steps at WITH_SCREENCAST.

Requirements

  • Python 3.12+
  • Installed browsers (for tests against a real driver).

Installation

The package is published to public PyPI. This is the recommended installation path for all consumers:

pip install tquality-py-selenium

Or in pyproject.toml:

dependencies = [
    "tquality-py-selenium>=0.1.5",
]

Alternative: install from the GitHub mirror

For a source build (e.g., to verify a commit that has not yet been released), the package is also available by git tag from the public GitHub mirror:

dependencies = [
    "tquality-py-selenium @ git+https://github.com/Tquality-ru/tquality-py-selenium.git@v0.1.5",
]

Direct git references require [tool.hatch.metadata] allow-direct-references = true on the consumer's side.

Quick start

# conftest.py
import pytest
from tquality_selenium import SeleniumServices

# Composition root. config_dir defaults to the directory of this file,
# so config.json5 next to conftest.py is picked up regardless of the
# current working directory.
SeleniumServices.setup()


@pytest.fixture(autouse=True)
def browser():
    SeleniumServices.browser()
    yield
    SeleniumServices.browser().quit()
    SeleniumServices.browser.reset()
    SeleniumServices.logger.reset()
# pages/login_page.py
from tquality_selenium import BaseForm, By


class LoginPage(BaseForm):
    def __init__(self) -> None:
        self._username = self.element_factory.input(
            By.id("username"), "Username",
        )
        self._password = self.element_factory.input(
            By.id("password"), "Password",
        )
        self._submit = self.element_factory.button(
            By.id("login-btn"), "Sign in",
        )
        super().__init__(unique_element=self._username, name="Login page")

    def login(self, username: str, password: str) -> None:
        self._username.type_text(username)
        self._password.type_text(password)
        self._submit.click()
// config.json5 — next to conftest.py
{
    "$schema": "https://cdn.jsdelivr.net/gh/Tquality-ru/tquality-py-selenium@v0.1.4/schema/config.schema.json",

    "base_url": "https://example.com",
    "browser": "chrome",
    "highlight_elements": true,  // red outline during interactions

    // All browsers are pre-configured — switching is a single line above.
    "chrome": { "headless": true },
    "firefox": { "headless": true },
    "undetected_chrome": { "headless": false },

    "screencast": {
        "fps": 10,
        "frame_interval": 0.1,  // captures short UI states more often
    },
}

Extending via subclasses of SeleniumServices

To add custom services, subclass SeleniumServices. The scope is defined by the dependency-injector provider type (and where it is reset in fixtures):

Scope Provider Lifetime
global providers.Singleton One instance per pytest process.
session providers.ContextLocalSingleton + reset in a scope="session" fixture One instance per session, reset on exit.
test providers.ContextLocalSingleton + reset in an autouse=True fixture A new instance per test.
transient providers.Factory A fresh instance on every services.my_service() call.
# my_project/services.py
from dependency_injector import providers
from tquality_selenium import SeleniumServices

from my_project.clients import ApiClient, CurrentUser, TempDirFactory


class ProjectServices(SeleniumServices):
    # Global: one API client per process.
    api_client = providers.Singleton(ApiClient)

    # Session: data shared across all tests of a single run.
    session_data = providers.ContextLocalSingleton(SessionData)

    # Test: fresh state per test.
    current_user = providers.ContextLocalSingleton(CurrentUser)

    # Transient: a fresh instance on every access.
    temp_dir = providers.Factory(TempDirFactory)

    # Replacing an existing service (referencing the parent's config):
    # browser = providers.ContextLocalSingleton(
    #     MyBrowserService, config=SeleniumServices.config,
    # )
# conftest.py
import pytest

from my_project.services import ProjectServices

ProjectServices.setup()


@pytest.fixture(autouse=True)
def _reset_test_scoped_services():
    """Test-scoped ContextLocalSingleton instances are reset after each test."""
    yield
    ProjectServices.current_user.reset()


@pytest.fixture(scope="session", autouse=True)
def _reset_session_scoped_services():
    """Session-scoped ContextLocalSingleton instances are reset at the end of the pytest session."""
    yield
    ProjectServices.session_data.reset()


@pytest.fixture(autouse=True)
def browser():
    ProjectServices.browser()
    yield
    ProjectServices.browser().quit()
    ProjectServices.browser.reset()
    ProjectServices.logger.reset()

Resolving a service by type, without referencing the provider name — useful inside elements and forms that don't see the concrete subclass:

from tquality_selenium import SeleniumServices
from my_project.clients import ApiClient

client = SeleniumServices.get_service(ApiClient)

get_service goes to the active composition root (the one whose setup() was called last), so providers replaced in a subclass are resolved transparently.

Step video recording

from tquality_selenium import LogLevel, step


def login():
    with step("Sign in", level=LogLevel.WITH_SCREENCAST):
        ...
    # An attached webm of the whole step is added to the allure report.

Capture runs in a background thread with contextvars.copy_context() so a second WebDriver session is not opened. The frame-capture strategy is BiDi → CDP → classic get_screenshot_as_png (with a warning on fallback).

Development

See CONTRIBUTING.md.

Version history

See CHANGELOG.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tquality_py_selenium-0.1.10.tar.gz (82.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tquality_py_selenium-0.1.10-py3-none-any.whl (55.4 kB view details)

Uploaded Python 3

File details

Details for the file tquality_py_selenium-0.1.10.tar.gz.

File metadata

  • Download URL: tquality_py_selenium-0.1.10.tar.gz
  • Upload date:
  • Size: 82.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tquality_py_selenium-0.1.10.tar.gz
Algorithm Hash digest
SHA256 30fac4f7475b9879b33c877b28123dcb025ebe09c88cae09f896621a9b69e70d
MD5 c9a7f13982f905267625f966b78ef237
BLAKE2b-256 d62a0425b745b1a068e27e1654ed0eb1e6dd67d40a3ff9bb884af0814313442d

See more details on using hashes here.

File details

Details for the file tquality_py_selenium-0.1.10-py3-none-any.whl.

File metadata

  • Download URL: tquality_py_selenium-0.1.10-py3-none-any.whl
  • Upload date:
  • Size: 55.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tquality_py_selenium-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 d568963ebd2eaad9c46c29adbf11451ed9e8bea67f5df42b132e136189f56a30
MD5 84adfd00a82f7b6ff3f94e7adf3908cb
BLAKE2b-256 ae013f287f9e8e4a67b9be4acdc293e606caa1278651df59afa9350de8963be4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page