Pytest browser test framework
Project description
pybrowsertestfw Module and Sample Project
1. pybrowsertestfw Module Overview
This project provides a lightweight test automation core module based on pytest, targeting a unified usage pattern and reporting output for Web (Selenium) and mobile (Appium). It is ready to use with a “convention over configuration” style. Once installed from PyPI as pybrowsertestfw, it can be reused in any project.
Positioning
- Unified: Web and mobile operations share the same abstraction, and screenshot/report paths are consistent.
- Simple: Zero-parameter default behaviors (such as
WebActions.screenshot()), with a minimal usable API set. - Visible: Built-in HTML, PDF, and JSON reports, automatically attaching screenshots and runtime logs.
Features
- Reports and attachments
- Automatically generates
reports/<ts>/report_<ts>.html,report_<ts>.pdf, andreport_<ts>.json. - Screenshots are uniformly named
screenshot/ss_{YYYYMMDD_HHMMSS}.pngand injected into the report.
- Automatically generates
- Logging
- Root log is written to
reports/<ts>/framework_<ts>.log. - Provides
get_logger(name)to obtain a named logger consistently.
- Root log is written to
- Minimal APIs
- Direct attach:
capture_and_attach(config, rep, driver, label). - Queue-based:
capture_and_queue_simple(driver)plus a unified attach step in plugin hooks.
- Direct attach:
Installation and Integration
pip install pybrowsertestfw
Or add the dependency to your existing pyproject.toml:
[project]
dependencies = [
"pybrowsertestfw>=0.1.0",
]
After installation, pytest will automatically load the plugin framework.pytest_plugin via entry points, no extra parameters required.
Python version requirement: supports Python 3.9.x - 3.13.x (
requires-python = ">=3.9, <3.14").
Module Directory (Simplified)
├── framework/
│ ├── config.py # CLI/session configuration parsing
│ ├── driver_factory.py # WebDriver/Appium driver creation
│ ├── logger.py # Logging configuration and entry
│ ├── reporting.py # Reporting and screenshots
│ ├── order.py # Test ordering logic (no pytest-order required)
│ ├── pdf_report.py # Optional PDF report generation
│ └── pytest_plugin.py # Framework hooks and context
├── operations/
│ └── web.py # WebActions wrapper
└── video/
└── recorder.py # Screen recording implementation (Web/Appium)
This repository only contains reusable framework core code (released as the pybrowerstestfw package).
2. Create a Sample Project
The following uses a minimal sample project to demonstrate how to quickly set up and run locally.
Directory Layout
├── drivers/
│ └── chromedriver.exe
├── properties.yml
├── pytest.ini
├── requirements.txt
├── test_order.yml
├── tests/
│ └── test_sample.py
├── datas/ # Optional
| └── data.csv
└── reports/ # Generated at runtime
| └── <ts>/
| ├── report_<ts>.html
| ├── report_<ts>.pdf
| ├── report_<ts>.json
| ├── framework_<ts>.log
| └── screenshot/
| └── ss_*.png
Browser and Mobile Drivers
- Path consistency: All desktop browser drivers should be placed in the
drivers/directory under the project root (lowercase). - Version matching: Each browser driver’s major version must match the corresponding browser’s major version on the machine, otherwise session creation may fail.
- Desktop examples:
- In
properties.yml, pointexecutable_pathto the corresponding file (Safari excluded). - Chrome: example path
.\\drivers\\chromedriver.exe. - Edge: example path
.\\drivers\\msedgedriver.exe. - Firefox: example path
.\\drivers\\geckodriver.exe. - Safari (macOS): uses the system
safaridriver. Runsafaridriver --enableon macOS to pre-authorize; no localexecutable_pathis needed.
- In
- Mobile examples:
- Android: set
'appium:chromedriverExecutable'in capabilities to a valid ChromeDriver absolute path, for example'C:\\Drivers\\chromedriver.exe', to drive mobile Chrome/WebView. - iOS: connect real devices or simulators through Appium, which relies on the device’s
safaridrivercapabilities. No additional browser driver files are required in the project.
- Android: set
- Remote mode: When connecting to Selenium Grid, local
executable_pathis usually unnecessary; driver versions are managed on the remote side.
Quick Start
1. Create a project directory and enter it, for example:
mkdir my_sample_project
cd my_sample_project
2. Create and activate a virtual environment (recommended):
- Windows (PowerShell):
python -m venv .venv .\.venv\Scripts\Activate.ps1
- Windows (cmd):
python -m venv .venv .venv\Scripts\activate.bat
- macOS / Linux (shell):
python -m venv .venv source .venv/bin/activate
3. Create and fill requirements.txt:
pybrowerstestfw>=0.1.0
4. Install dependencies
pip install -r requirements.txt
5. Create pytest.ini:
[pytest]
markers =
smoke: 'smoke test'
addopts = --strict
6. Create properties.yml:
# This is an example of Chrome configuration.
chrome:
browserName: 'chrome'
executable_path: '.\\drivers\\chromedriver.exe'
'goog:chromeOptions':
args:
- '--start-maximized'
experimentalOptions:
excludeSwitches:
- 'enable-automation'
7. Create test_order.yml (optional, to control execution order):
- "tests/test_sample.py::test_demo_aut"
8. Create a sample test tests/test_sample.py
-
Example 1:
- Test case without CSV:
import pytest from selenium.webdriver.common.by import By @pytest.mark.smoke def test_demo_aut(driver, acts: WebActions): driver.get("https://katalon-test.s3.amazonaws.com/aut/html/form.html") driver.find_element(By.ID, "first-name").clear() driver.find_element(By.ID, "first-name").send_keys("Alex") driver.find_element(By.ID, "last-name").clear() driver.find_element(By.ID, "last-name").send_keys("Smith") acts.screenshot()
- Test case without CSV:
-
Example 2:
-
Test case using CSV:
import pytest from selenium.webdriver.common.by import By from operations.web import WebActions @pytest.mark.smoke def test_demo_aut(driver, acts: WebActions): rows = acts.load_vars_from_csv("data.csv") for row in rows: first = row.get("first", "") last = row.get("last", "") driver.get("https://katalon-test.s3.amazonaws.com/aut/html/form.html") driver.find_element(By.ID, "first-name").clear() driver.find_element(By.ID, "first-name").send_keys(first) driver.find_element(By.ID, "last-name").clear() driver.find_element(By.ID, "last-name").send_keys(last) acts.screenshot()
-
Create test data file
datas/data.csv:first,last Alex,Smith Steve,Rogers
-
9. Run the sample test
pytest --profile="chrome" -q tests/test_sample.py
10. Open the reports
- HTML:
reports/<ts>/report_<ts>.html - JSON:
reports/<ts>/report_<ts>.json - PDF:
reports/<ts>/report_<ts>.pdf - Log:
reports/<ts>/framework_<ts>.log - Screenshots:
reports/<ts>/screenshot/ss_*.png
Basic Usage
- Get a named logger
from framework.logger import get_logger
logger = get_logger("operations.web")
- Example usage of
screenshot
from operations.web import WebActions
web = WebActions(driver)
web.screenshot()
- Example usage of
load_vars_from_csv
from operations.web import WebActions
def test_sample_two(driver, acts: WebActions):
rows = acts.load_vars_from_csv("data.csv")
for row in rows:
first = row.get("first", "")
last = row.get("last", "")
driver.get("https://katalon-test.s3.amazonaws.com/aut/html/form.html")
driver.find_element(By.ID, "first-name").clear()
driver.find_element(By.ID, "first-name").send_keys(first)
driver.find_element(By.ID, "last-name").clear()
driver.find_element(By.ID, "last-name").send_keys(last)
Configuration
requirements.txt: Declare project dependencies, at leastpybrowerstestfw,pytest, andselenium.pytest.ini: Pytest global configuration, defines markers and strict mode.properties.yml: Stores browser/device capabilities (caps) that the framework reads to create corresponding drivers.test_order.yml: Optional, used to specify test execution order.- At session start, the plugin automatically:
- Initializes report directories and filenames (
init_reporting). - Configures the root logger (
setup_logging).
- Initializes report directories and filenames (
Reporting and Screenshot Flow
- During test execution:
WebActions.screenshot()→capture_and_queue_simple(driver)saves PNG files and enqueues them. - Reporting phase: The plugin triggers
drain_pending_extras, attaching all queued images to the HTML report viarep.extras. - JSON report: Automatically injects a
screenshotsfield with relative paths.
Test Ordering (Without pytest-order)
- Supports controlling execution order via the
test_order.ymlmanifest, without modifying test files, and is compatible with Katalon scripts exported in bulk or individually. - Usage:
- Create
test_order.ymlin the project root. Each item is a NodeID pattern (YAML list), matched in declared order:tests/test_login.py::test_logintests/test_saucedemo_v2.py::test_*tests/generated/**/test_*.py::test_*
- Verify collection order:
pytest --collect-only -p no:order
- Create
- Notes:
- The framework registers
pytest_collection_modifyitemsin the plugin and delegates toframework/order.py. Ifpytest-orderis also installed, it may reorder items again after collection; it is recommended to disable it via-p no:orderor remove it from dependencies. - Items not matched in
test_order.ymlmaintain default ordering and run after matched items. Parallel execution (pytest-xdist) may break ordering; disable parallelism or use single-test orchestration when strict ordering is required.
- The framework registers
Extension Points
-
Custom CLI options
--profile: Specify the capabilities key (caps) inproperties.yml. Example:--profile web_chrome.--remote-address: Remote WebDriver/Appium address. Example (Selenium Grid):http://localhost:4444/wd/hub; example (Appium):http://127.0.0.1:4723/wd/hub.--video: Whether to record video (y|n, defaultn). Output file:reports/<ts>/video_<ts>.mp4.- Notes: For Web (Selenium) it uses a built-in screen recorder (bundled in
video/pyscreenrec.py) to capture the entire screen (non-headless is recommended). For mobile (Appium) it uses the driver’s built-in recording. - Examples:
# Local browser (Chrome, local driver) pytest --profile="chrome" -m "smoke" # Remote Selenium Grid (Chrome) pytest --profile="chrome" --remote-address="http://localhost:4444/wd/hub" -m "smoke" # Appium (mobile Web): requires remote mode + browserName pytest --profile="android_chrome" --remote-address="http://127.0.0.1:4723/wd/hub" -m "smoke" --video="y" # Local browser (Edge) pytest --profile="edge_local" -m "smoke" # Local browser (Firefox) pytest --profile="firefox_local" -m "smoke" # Safari (macOS only) pytest --profile="safari_mac" -m "smoke"
-
Appium usage example (mobile Web)
properties.ymlexample:android_chrome: platformName: 'Android' browserName: 'chrome' 'appium:automationName': 'UiAutomator2' 'appium:deviceName': 'emulator-5554' 'appium:noReset': true 'appium:chromedriverExecutable': 'C:\\Drivers\\chromedriver.exe' 'goog:chromeOptions': experimentalOptions: w3c: false ios_safari: platformName: 'iOS' browserName: 'safari' 'appium:automationName': 'XCUITest' 'appium:deviceName': 'iPhone 15' 'appium:udid': '000XXX20-001C35XXXE42XXXX' 'appium:noReset': true 'appium:nativeWebTap': true 'appium:safariAllowPopups': false 'appium:safariIgnoreFraudWarning': true
- Run example:
# Android Chrome (ensure Appium Server is running) pytest --profile="android_chrome" --remote-address="http://127.0.0.1:4723/wd/hub" -m "smoke"
- Note: The current version requires
browserNameincapabilities(for mobile Web/WebView).
Locator Strategy Compatibility (Mobile Web / Appium)
- In mobile Web sessions through Appium→WebDriver, the server enforces locator strategies more strictly. Directly using
using: "id"|"name"|"class name"may be considered invalid and returninvalid locator(400). - If test cases call
driver.find_element("id", ...)directly, mobile Web scenarios may still fail. Using CSS or XPath locators is recommended.
FAQ
- Screenshots not visible? Ensure you are using a
pytest-htmlversion that supportsrep.extras(4.1.x or above). - Paths too long? The framework removes
nodeidin filenames and uses timestamps to keep them short and consistent.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pybrowsertestfw-0.1.0.tar.gz.
File metadata
- Download URL: pybrowsertestfw-0.1.0.tar.gz
- Upload date:
- Size: 44.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b55bad9ddd107dc0c0d031c087721189ade7c63e6c76e9231d223aa133c27f9f
|
|
| MD5 |
e0ff6da0c44147f53332f27a2bc29e3f
|
|
| BLAKE2b-256 |
604c7b6a8665441178a621a7be967e75f637480dbf4ffb645f6dd6b8e03ff07a
|
File details
Details for the file pybrowsertestfw-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pybrowsertestfw-0.1.0-py3-none-any.whl
- Upload date:
- Size: 41.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
652ef136987c6105efc2287a3669c09e4ddefbbbd4113db6e21a4161f2e3ddc2
|
|
| MD5 |
9163b6450468750a04cbcb05c4000765
|
|
| BLAKE2b-256 |
08e099b753d81b2e7179a50359b1f22da9f2d6484a2828913ed7eb4f77263372
|