Selenium tests should run automatically on every push. Headless Chrome works in any CI environment without a display server.
pytest-html Reports
pip install pytest-html
pytest tests/ --html=report.html --self-contained-htmlOpen report.html in a browser — you get a summary, pass/fail status per test, and captured logs.
Screenshots on Failure
# conftest.py
import pytest
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
if report.when == "call" and report.failed:
driver = item.funcargs.get("driver")
if driver:
driver.save_screenshot(f"screenshots/{item.name}.png")Now any failing test automatically saves a screenshot next to the report.
GitHub Actions Workflow
# .github/workflows/selenium.yml
name: Selenium Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install selenium pytest pytest-html
- name: Install Chrome
uses: browser-actions/setup-chrome@v1
- name: Run tests
run: pytest tests/ --html=report.html --self-contained-html
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: selenium-report
path: |
report.html
screenshots/if: always() uploads the report even when tests fail — essential for debugging CI failures.
Parallel Execution with pytest-xdist
pip install pytest-xdist
pytest tests/ -n auto # uses all available CPU coresEach worker gets its own browser instance. Runs that took 10 minutes now finish in 2.
CI Pipeline Overview
CI pipeline stages
Ctrl+Enter
HTML
CSS
JS
Preview