This guide explains how to set up and run Playwright-based Python tests with Allure reporting on macOS, Windows, and Linux.
All Platforms:
- Python 3.11+
- pip
- Node.js (for Playwright browser installation)
- Allure Commandline
python-dotenv(for loading.envfiles)
Windows Only:
macOS Only:
- Homebrew (recommended for installing Allure and Node.js)
git clone https://github.com/your-org/your-repo.git
cd your-repoCreate the environment file(s) you need in the project root:
.env.devfor development.env.testfor test.env.prodfor production
Each file should contain the environment variables your tests require, for example:
BASE_URL=https://your-base-url
API_LOGIN_URL=https://your-api-url
USER_EMAIL=pm@example.com
USER_PASSWORD=yourpassword
# ...and so on for all required variables
Alternately, these files should be available in your secrets server and may need to be customized for your tests.
macOS/Linux:
python3 -m venv .venv
source .venv/bin/activateWindows (Command Prompt):
python -m venv .venv
.venv\Scripts\activateWindows (PowerShell):
python -m venv .venv
.venv\Scripts\Activate.ps1pip install --upgrade pip
pip install -r requirements_with_versions.txtMake sure your requirements_with_versions.txt includes:
python-dotenv
opencv-python
pillow
numpy
Important: This step is required to download browser binaries for Chromium, Firefox, and WebKit.
python -m playwright install --with-depsNote: If you encounter "Executable doesn't exist" errors when running tests with specific browsers (e.g., Firefox), make sure you've run this command to install all browser binaries.
macOS (with Homebrew):
brew install allureLinux:
sudo apt-get install default-jre
wget https://github.com/allure-framework/allure2/releases/download/2.27.0/allure-2.27.0.tgz
tar -xzf allure-2.27.0.tgz
sudo mv allure-2.27.0 /opt/allure
sudo ln -s /opt/allure/bin/allure /usr/bin/allureWindows:
- Download the Allure zip and extract it.
- Add the
binfolder to yourPATHenvironment variable. - Open a new terminal and run
allure --versionto verify.
Add this to your conftest.py or at the top of your test entrypoint:
import os
from dotenv import load_dotenv
# Choose the environment file you want to load
env_file = os.getenv("ENV_FILE", ".env.dev")
load_dotenv(dotenv_path=env_file)You can set the ENV_FILE environment variable to switch between .env.dev, .env.test, or .env.prod.
Example:
ENV_FILE=.env.test pytest ...Run your tests with pytest. For example, to run smoke tests with Allure reporting, reruns and in parallel:
pytest --alluredir=test_artifacts/allure/allure-results --capture=tee-sys --reruns 2 --reruns-delay 5 -m smoke -n auto- Adjust the
-m smokemarker or other pytest options as needed.
You can also pass env vars on the commandline, for example if you want headed tests or a different browser.
BROWSER=firefox HEADLESS=false pytest --alluredir=test_artifacts/allure/allure-results --capture=tee-sys --reruns 2 --reruns-delay 5 -m smoke -n autoAdjust as needed.
allure generate test_artifacts/allure/allure-results -o test_artifacts/allure/allure-report --clean --single-filemacOS:
open test_artifacts/allure/allure-report/index.htmlLinux:
xdg-open test_artifacts/allure/allure-report/index.htmlWindows:
Open test_artifacts\allure\allure-report\index.html in your browser.
Everything is already configured to run a smoke test, then if that passes it will run the full 'login' test suite. All secrets are configured on the repo level, so if you add any, you will need to update the config.
- Baselines managed in
test_artifacts/visual/visual_baselines/ - Current run in
test_artifacts/visual/visual_current/ - Diffs (with OpenCV highlights) in
test_artifacts/visual/visual_diffs/
Example:
@pytest.mark.asyncio
async def test_homepage_visual(page, visual_regression):
await page.goto("https://example.com")
await visual_regression("homepage", tolerance=0.02)Run:
pytest tests/visual_regression/ -v- Mock GET/POST/PUT/DELETE
- Load from files
- Handle slow responses
Example:
await api_mocker.mock_get("**/api/users", {"users": [{"id": 1}]})The Ollama Python library is installed as part of requirements_with_versions.txt.
Check Available Models
ollama listPull a Suitable Model
ollama pull llava:7b
# or
ollama pull llava:13bollama pull llama3.1:8b
# or
ollama pull llama3.2:3bUpdate Your Environment Variable
Set the model you actually have:
export OLLAMA_MODEL=llava:7b
# or whatever model you pulledTest Ollama is Working
ollama run llava:7b "Hello, can you analyze test failures?"This is not configured on Github Actions due to needing a larger machine runner. Reports will be found in test_artifacts/ai/ai_healing_reports
To see this in action, you can run a test specifically created to show it in action by running
AI_HEALING_ENABLED=true ENV=dev SKIP_SCREENSHOTS=0 HEADLESS=false pytest --alluredir=test_artifacts/allure/allure-results --capture=tee-sys --reruns 2 --reruns-delay 5 -m trigger_ai_healingThis is an example of commandline output
π§ Test failed, capturing context for AI healing: test_login_direct_valid_credentials
Screenshot saved and attached to Allure: screenshots/tests_login_test_login.py_test_login_direct_valid_credentials_2025-07-29_21-37-36.png
πΎ Context saved for AI healing hook (key: tests/login/test_login.py::test_login_direct_valid_credentials)
π§ Final failure detected for test_login_direct_valid_credentials, triggering AI healing
π€ Using Ollama at http://localhost:11434 with model gemma2:2b
π€ Checking Ollama service at http://localhost:11434...
π€ Ollama executable path: /usr/local/bin/ollama
π€ Ollama service is already running.
π€ Checking if model gemma2:2b is available...
π€ Warming up model gemma2:2b (waiting for a real response)...
π€ Model gemma2:2b is loaded and ready.
π§ Calling Ollama for AI healing analysis...
π§ Querying Ollama model: gemma2:2b
πΈ Including screenshot: screenshots/tests_login_test_login.py_test_login_direct_valid_credentials_2025-07-29_21-37-36.png
π€ Raw Ollama response (first 200 chars): ```json
{
"analysis": "The error message 'LoginPage' object has no attribute 'enter_passwordx' indicates that the code is trying to access an element named 'enter_passwordx' which doesn't exist wi...
π€ Found JSON in code block
β
Successfully parsed JSON response
π€ Full Ollama response: {'analysis': "The error message 'LoginPage' object has no attribute 'enter_passwordx' indicates that the code is trying to access an element named 'enter_passwordx' which doesn't exist within the LoginPage class. This likely means there's a typo in the test code, or the element name might have been changed.", 'root_cause': 'Typographical error in the test code (e.g., incorrect element name)', 'confidence': 0.95, 'suggested_fix': 'Verify the element names used in the test code against the actual HTML structure of the LoginPage class. Double-check for typos or misspellings.', 'updated_test_code': "```python\n@pytest.mark.login\nasync def test_login_direct_valid_credentials(app):\n # ... (rest of the code)\n await app.login_page.enter_passwordx(PERSONAS['user']['password']) \n # ... (rest of the code)\n```", 'recommendations': "It's recommended to use a robust test framework like pytest for better test organization and error handling. Consider using assertions to ensure that elements are found correctly, and implement strategies to handle flaky tests effectively.", 'raw_ollama_response': '```json\n{\n "analysis": "The error message \'LoginPage\' object has no attribute \'enter_passwordx\' indicates that the code is trying to access an element named \'enter_passwordx\' which doesn\'t exist within the LoginPage class. This likely means there\'s a typo in the test code, or the element name might have been changed.",\n "root_cause": "Typographical error in the test code (e.g., incorrect element name)",\n "confidence": 0.95,\n "suggested_fix": "Verify the element names used in the test code against the actual HTML structure of the LoginPage class. Double-check for typos or misspellings.",\n "updated_test_code": "```python\\n@pytest.mark.login\\nasync def test_login_direct_valid_credentials(app):\\n # ... (rest of the code)\\n await app.login_page.enter_passwordx(PERSONAS[\'user\'][\'password\']) \\n # ... (rest of the code)\\n```",\n "recommendations": "It\'s recommended to use a robust test framework like pytest for better test organization and error handling. Consider using assertions to ensure that elements are found correctly, and implement strategies to handle flaky tests effectively." \n}\n```'}
π§ AI analysis complete, generating healing report...
πΎ Ollama healed test saved: ai_healing_reports/test_login_direct_valid_credentials_20250729_213826_ollama_healed.pyYou can see some example reports and attempts at fixing the files in test_artifacts/ai/ai_healing_reports/
You can run your Playwright tests on real browsers in the cloud using BrowserStack. This is useful for cross-browser and cross-OS testing without maintaining your own infrastructure.
- You must have a BrowserStack account.
- Your account's Username and Access Key (found in your BrowserStack dashboard).
Install the BrowserStack Local Python bindings:
pip install browserstack-localAdd the following to your .env.dev (or relevant .env file):
BROWSERSTACK_USERNAME=your_browserstack_username
BROWSERSTACK_ACCESS_KEY=your_browserstack_access_key
BROWSERSTACK_ENABLED=true
Note: Set
BROWSERSTACK_ENABLED=falseto run tests locally.
When BROWSERSTACK_ENABLED=true, the test runner will:
- Connect to BrowserStack using your credentials.
- Launch the specified browser/OS in the cloud.
- Run your Playwright tests remotely.
When BROWSERSTACK_ENABLED=false, tests run locally as usual.
Activate your virtual environment and run:
BROWSERSTACK_ENABLED=true pytest --alluredir=test_artifacts/allure/allure-resultsYou can also set the environment variable in your .env.dev file.
Edit the capabilities in the conftest.py file under the caps dictionary to change browser, version, OS, etc. Example:
caps = {
"browser": "chrome",
"browser_version": "latest",
"os": "osx",
"os_version": "sonoma",
"name": "Playwright Test",
"build": "playwright-python-build-1",
"browserstack.username": os.getenv("BROWSERSTACK_USERNAME"),
"browserstack.accessKey": os.getenv("BROWSERSTACK_ACCESS_KEY"),
}See BrowserStack Playwright Capabilities for more options.
- Test results and screenshots will be available in your BrowserStack dashboard.
- Allure reports will still be generated locally if you use
--alluredir.
Tip:
You can switch between local and BrowserStack runs by toggling the BROWSERSTACK_ENABLED variable, without changing your test code.
Automatically post test results to Jira tickets and trigger workflow transitions on pass/fail. Conditionally enabled via environment variables.
Add the following to your .env.dev (or relevant .env file):
JIRA_ENABLED=true
JIRA_BASE=https://your-instance.atlassian.net
JIRA_USER=you@example.com
JIRA_TOKEN=your_api_token
JIRA_DRY_RUN=false
Note: Set
JIRA_ENABLED=falseto disable Jira reporting entirely. SetJIRA_DRY_RUN=trueto log what would be posted without making actual API calls.
| Variable | Default | Description |
|---|---|---|
JIRA_ENABLED |
false |
Enable/disable Jira reporting |
JIRA_BASE |
β | Jira instance URL |
JIRA_USER |
β | Jira username/email |
JIRA_TOKEN |
β | Jira API token |
JIRA_JQL |
project = ABC AND status in ("To Do", "In Progress") |
JQL filter for ticket lookup |
JIRA_DRY_RUN |
false |
Log instead of posting |
JIRA_TRANSITION_ON_PASS |
β | Workflow transition name when test passes |
JIRA_TRANSITION_ON_FAIL |
β | Workflow transition name when test fails |
- Test names or node IDs are scanned for Jira ticket patterns (e.g.,
PROJ-123). - On test completion (pass or final retry failure), a formatted comment is posted to the ticket.
- If transition env vars are configured, the ticket's workflow state is updated automatically.
Include the ticket ID in your test name or file path:
def test_PROJ_123_login_flow(page):
...Or use pytest marks/node IDs that contain the ticket pattern [A-Z][A-Z0-9]+-\d+.
Structured per-test metrics collection with JSONL output, summary reports, and error categorization. Tracks flake rate, pass rate, slowest tests, heal events, and failures by category.
OBSERVABILITY_ENABLED=true
Note: Set
OBSERVABILITY_ENABLED=falseto disable metric collection entirely. Zero overhead when disabled.
Each test execution records:
| Field | Description |
|---|---|
test_id |
Unique test identifier (node ID) |
test_name |
Human-readable test name |
suite |
Test suite/module |
status |
passed, failed, skipped |
duration_ms |
Execution time in milliseconds |
retry_count |
Number of retries for this test |
browser |
Browser engine used |
commit_sha |
Git commit (auto-detected) |
branch |
Git branch (auto-detected) |
heal_event |
Whether AI healing was triggered |
error_category |
Auto-categorized: timeout, element-not-found, navigation, assertion, browser-crash, other |
| File | Location |
|---|---|
| JSONL metrics | test_artifacts/observability/metrics.jsonl |
| Summary JSON | test_artifacts/observability/summary.json |
| Markdown report | test_artifacts/observability/report.md |
OBSERVABILITY_ENABLED=true pytest --alluredir=test_artifacts/allure/allure-results --capture=tee-sys --reruns 2 --reruns-delay 5 -m smoke -n autoThe summary is printed to the console at the end of the session and a Markdown report is written to test_artifacts/observability/report.md.
Regenerate Docs for LLMs:
This project makes use of OneFileLLM: https://github.com/jimmc414/onefilellm
To install:
git clone https://github.com/jimmc414/onefilellm.git
cd onefilellm
pip install -r requirements.txt
pip install -e .For GitHub API access (recommended):
export GITHUB_TOKEN="your_personal_access_token"To regenerate output.xml:
python onefilellm.py https://github.com/philmcneely/playwright-ai-frameworkYou can also run the script against a local repository by providing the local path instead of a GitHub URL, for example:
python onefilellm.py /path/to/your/local/repo- Missing .env file:
Make sure you have created the correct.env.<env>file with all required variables. - Virtual environment activation issues:
Double-check the activation command for your OS and shell. - Allure not found:
Ensure Allure is installed and available in yourPATH. - Windows build errors:
Install the Visual C++ Build Tools as described above. - Browser "Executable doesn't exist" errors:
Runpython -m playwright install --with-depsto download all browser binaries.
.
βββ π .env.dev, .env.test, .env.prod β Environment variable files
βββ π conftest.py β Config & fixtures
βββ π pytest.ini β Pytest settings
βββ π requirements_with_versions.txt β Python deps
β
βββ π test_artifacts/ β Test artifacts
β βββ π visual/
β β βββ π visual_baselines β Baseline screenshots (committed)
β β βββ π visual_current β Current screenshots (gitignored)
β β βββ π visual_diffs β Diff images (gitignored)
β βββ π ai/
β β βββ π ai_healing_reports β AI healing reports (with committed examples)
β βββ π allure/ β Allure reports/results/screenshots (gitignored)
β βββ π observability/
β β βββ π metrics.jsonl β Per-test JSONL metrics
β β βββ π summary.json β Aggregated summary
β β βββ π report.md β Markdown report
βββ π pages/ β Page Object Models
βββ π utils/ β Utilities
β βββ π visual_regression.py
β βββ π network_mocking.py
β βββ π jira_client.py β Jira REST API client
β βββ π test_observability.py β Test metrics collector
βββ π data/ β Test data
βββ π config/ β Settings
βββ π tests/ β Test files
β βββ π login/ β Login functional/security tests
β βββ π visual_regression/ β Visual regression tests
β βββ π api/ β API mocking tests
β βββ π unit/ β Framework utility unit tests
Happy testing! π