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.12.tar.gz (104.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.12-py3-none-any.whl (71.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: tquality_py_selenium-0.1.12.tar.gz
  • Upload date:
  • Size: 104.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.12.tar.gz
Algorithm Hash digest
SHA256 8f8304a5f50aeea30356a8aea6cdf761870c5b6fba62018245ff3b467a25ed75
MD5 dd197d5a78d97d50e05fe39217306cad
BLAKE2b-256 692ff56e3ed29be862c3df8ac157b57db7194fb16ed98c5235cc773ea5aeef94

See more details on using hashes here.

File details

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

File metadata

  • Download URL: tquality_py_selenium-0.1.12-py3-none-any.whl
  • Upload date:
  • Size: 71.2 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.12-py3-none-any.whl
Algorithm Hash digest
SHA256 7908cfe08e6b97910c8dd5b2ed206d7dbe9c72ccc08e0e360feaf1fff96eff1a
MD5 a19ec45d5241fad9005b5b74bac7f2cf
BLAKE2b-256 bc436b8f26e8cf2bc87608b2ea825fe30ff239e5f52583289e8fb68ce8e9e3d8

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