pytest-html-plus-action
=======================
Run pytest with `pytest-html-plus `__ and
get rich HTML reports, JSON outputs, step summaries, and PR comments
— without adding the plugin to your project dependencies.
--------------
Overview
--------
This GitHub Action installs and runs ``pytest-html-plus`` in your CI
pipeline. It is designed for teams who want report generation handled
entirely by the action, keeping their ``pyproject.toml`` or
``requirements.txt`` clean.
**What it does:**
- Installs ``pytest-html-plus`` and runs your test suite
- Generates an HTML report and uploads it as a workflow artifact
- Writes a test summary to the GitHub step summary page
- Optionally posts a summary comment on pull requests
- Exposes structured step outputs (``total``, ``passed``, ``failed``,
``skipped``, ``duration``) for downstream steps
--------------
Quick Start
-----------
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
That’s it. With all defaults, this will:
- Run ``pytest`` from the repo root
- Generate ``final_report.json`` and an HTML report in
``report_output/``
- Upload the HTML report as a workflow artifact named
``pytest-html-plus-report``
- Write a summary to the GitHub step summary page
--------------
Inputs
------
+-----------------------+-----------------------+-----------------------+
| Input | Description | Default |
+=======================+=======================+=======================+
| ``test_path`` | Path or target for | ``""`` |
| | pytest | |
| | (e.g. ``tests/``). If | |
| | empty, pytest | |
| | discovery runs from | |
| | repo root. | |
+-----------------------+-----------------------+-----------------------+
| ``pytest_args`` | Additional arguments | ``""`` |
| | passed directly to | |
| | pytest. | |
+-----------------------+-----------------------+-----------------------+
| ``json_report`` | Path for the JSON | ``final_report.json`` |
| | report file. | |
+-----------------------+-----------------------+-----------------------+
| ``html_output`` | Directory to save the | ``report_output`` |
| | HTML report. | |
+-----------------------+-----------------------+-----------------------+
| ``screenshots`` | Directory to save | ``screenshots`` |
| | screenshots. | |
+-----------------------+-----------------------+-----------------------+
| `` | When to capture | ``failed`` |
| capture_screenshots`` | screenshots: | |
| | ``failed``, ``all``, | |
| | or ``none``. | |
+-----------------------+-----------------------+-----------------------+
| ` | When to auto-open the | ``failed`` |
| `should_open_report`` | report locally: | |
| | ``always``, | |
| | ``failed``, or | |
| | ``never``. | |
+-----------------------+-----------------------+-----------------------+
| ``generate_xml`` | Generate a | ``false`` |
| | JUnit-style XML | |
| | report. | |
+-----------------------+-----------------------+-----------------------+
| ``xml_report`` | Path for the XML | ``""`` |
| | report file. | |
+-----------------------+-----------------------+-----------------------+
| ``plus_email`` | Send the HTML report | ``false`` |
| | via email (requires | |
| | email config in | |
| | plugin). | |
+-----------------------+-----------------------+-----------------------+
| ``use_poetry`` | Run pytest through | ``false`` |
| | Poetry | |
| | (`` | |
| | poetry run pytest``). | |
| | Cannot be combined | |
| | with ``use_uv``. | |
+-----------------------+-----------------------+-----------------------+
| ``use_uv`` | Run pytest through uv | ``false`` |
| | (``uv run pytest``). | |
| | Cannot be combined | |
| | with ``use_poetry``. | |
+-----------------------+-----------------------+-----------------------+
| ``git_branch`` | Git branch name to | ``""`` |
| | embed in the report. | |
+-----------------------+-----------------------+-----------------------+
| ``git_commit`` | Git commit SHA to | ``""`` |
| | embed in the report. | |
+-----------------------+-----------------------+-----------------------+
| ``post_pr_comment`` | Post a summary | ``false`` |
| | comment on the pull | |
| | request. | |
+-----------------------+-----------------------+-----------------------+
| ``github_token`` | GitHub token for | ``""`` |
| | posting PR comments. | |
| | Required when | |
| | ``post_pr_comment`` | |
| | is ``true``. | |
+-----------------------+-----------------------+-----------------------+
| ``u | Upload the HTML | ``true`` |
| pload_html_artifact`` | report as a GitHub | |
| | Actions artifact. | |
+-----------------------+-----------------------+-----------------------+
| ` | Name of the uploaded | ``pyte |
| `html_artifact_name`` | artifact. | st-html-plus-report`` |
+-----------------------+-----------------------+-----------------------+
| ``plugin_version`` | Version of | ``""`` |
| | ``pytest-html-plus`` | |
| | to install. Defaults | |
| | to latest. | |
+-----------------------+-----------------------+-----------------------+
Outputs
-------
============ ====================================
Output Description
============ ====================================
``total`` Total number of tests
``passed`` Number of passed tests
``failed`` Number of failed or errored tests
``skipped`` Number of skipped tests
``duration`` Sum of all test durations in seconds
============ ====================================
--------------
Use Cases
---------
1. Minimal — zero config
~~~~~~~~~~~~~~~~~~~~~~~~
Run pytest with full report generation and artifact upload, no
configuration needed.
.. code:: yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -r requirements.txt
- uses: reporterplus/pytest-html-plus-action@v1
--------------
2. Run a specific test directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
test_path: tests/unit
--------------
3. Pass additional pytest arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Coverage, reruns, markers, and any other pytest flags go in
``pytest_args``.
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
test_path: tests/
pytest_args: >-
--cov=mypackage
--cov-fail-under=80
--cov-report=term
--reruns 2
--ignore=tests/browser
--------------
4. Poetry project
~~~~~~~~~~~~~~~~~
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
use_poetry: "true"
test_path: tests/
Make sure ``poetry install`` has already run in a previous step.
--------------
5. uv project
~~~~~~~~~~~~~
``uv`` is not pre-installed on GitHub-hosted runners, so install it
first with the official setup action.
.. code:: yaml
- uses: astral-sh/setup-uv@v5
- name: Install dependencies
run: uv sync
- uses: reporterplus/pytest-html-plus-action@v1
with:
use_uv: "true"
test_path: tests/
``use_uv`` and ``use_poetry`` are mutually exclusive — setting both to
``true`` will fail the step with a clear error before pytest runs.
--------------
6. Post a summary comment on pull requests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
post_pr_comment: "true"
github_token: ${{ secrets.GITHUB_TOKEN }}
The comment includes total, passed, failed, skipped, duration, and a
list of up to 5 failed test cases.
**Security note:** Always use ``secrets.GITHUB_TOKEN`` rather than a
personal access token — it is automatically scoped to the current
repository and expires after the run. The token only needs
``issues: write`` permission. If your repo accepts PRs from forks,
review your workflow’s trigger settings before enabling
``post_pr_comment``, as fork workflows may have access to the token
depending on your repository configuration.
--------------
7. Embed git context in the report
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Useful when sharing reports outside of GitHub — the report itself shows
which branch and commit it was generated from.
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
git_branch: ${{ github.ref_name }}
git_commit: ${{ github.sha }}
--------------
8. Generate a JUnit XML report alongside HTML
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Useful for integrating with tools that consume JUnit XML (e.g. test
analytics platforms, SonarQube).
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
generate_xml: "true"
xml_report: reports/junit.xml
--------------
9. Use step outputs to conditionally fail or notify
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
id: pytest
with:
test_path: tests/
- name: Print test summary
run: |
echo "Total: ${{ steps.pytest.outputs.total }}"
echo "Passed: ${{ steps.pytest.outputs.passed }}"
echo "Failed: ${{ steps.pytest.outputs.failed }}"
- name: Notify on failure
if: ${{ steps.pytest.outputs.failed > 0 }}
run: echo "::warning::${{ steps.pytest.outputs.failed }} test(s) failed"
--------------
10. Pin the plugin version for reproducible CI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
plugin_version: "1.2.0"
Recommended for teams with strict dependency policies or those who want
to upgrade the plugin intentionally rather than automatically picking up
the latest release.
--------------
11. Custom artifact name per matrix leg
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When running a test matrix (e.g. multiple OS or Python versions), give
each artifact a unique name so they don’t overwrite each other.
.. code:: yaml
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.11", "3.12"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: pip install -r requirements.txt
- uses: reporterplus/pytest-html-plus-action@v1
with:
html_artifact_name: report-${{ matrix.os }}-py${{ matrix.python-version }}
--------------
12. Screenshot capture on failure (browser/UI tests)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For projects using Playwright or Selenium, screenshots of failed tests
are captured automatically and included in the HTML report.
.. code:: yaml
- uses: reporterplus/pytest-html-plus-action@v1
with:
test_path: tests/browser
capture_screenshots: failed
screenshots: test-screenshots
Set ``capture_screenshots: all`` to capture every test regardless of
outcome.
--------------
13. PYTHONWARNINGS — treat warnings as errors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The action has no dedicated input for environment variables, but any
variable written to ``$GITHUB_ENV`` in a prior step persists into the
action’s environment.
.. code:: yaml
- name: Configure Python warnings
run: echo "PYTHONWARNINGS=error" >> $GITHUB_ENV
- uses: reporterplus/pytest-html-plus-action@v1
with:
test_path: tests/
xml_report: reports/junit_warnings.xml
html_output: report_output_warnings
--------------
14. Full production setup
~~~~~~~~~~~~~~~~~~~~~~~~~
A complete example combining git context, PR comments, XML output,
coverage, and reruns.
.. code:: yaml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -r requirements.txt
- uses: reporterplus/pytest-html-plus-action@v1
id: pytest
with:
use_poetry: "false"
test_path: tests/
pytest_args: >-
--cov=mypackage
--cov-fail-under=75
--cov-report=term
--reruns 1
git_branch: ${{ github.ref_name }}
git_commit: ${{ github.sha }}
generate_xml: "true"
xml_report: reports/junit.xml
html_output: report_output
html_artifact_name: test-report-${{ github.run_id }}
post_pr_comment: "true"
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Fail with context if tests failed
if: ${{ steps.pytest.outputs.failed > 0 }}
run: |
echo "${{ steps.pytest.outputs.failed }} of ${{ steps.pytest.outputs.total }} tests failed"
exit 1
--------------
Notes
-----
**Windows runners:** The action uses a bash entrypoint and is not
compatible with Windows runners. Use ``ubuntu-latest`` or
``macos-latest``.
**Self-hosted runners:** Ensure Python and pip are available on the
runner. The action installs ``pytest-html-plus`` at runtime via pip.
**Air-gapped environments:** If your runner cannot reach PyPI,
pre-install ``pytest-html-plus`` in your runner image and set
``plugin_version`` to the pre-installed version to avoid the install
step attempting to upgrade.
**PR comments accumulate:** Each push to a PR branch posts a new comment
rather than updating the previous one. If comment volume is a concern,
delete previous bot comments in a prior step using the GitHub API.
**uv runners:** ``uv`` is not pre-installed on GitHub-hosted runners.
Add ``astral-sh/setup-uv@v5`` and ``uv sync`` as steps before the
action. ``use_uv`` and ``use_poetry`` cannot both be ``true`` — the
action will exit with an error before pytest runs if both are set.
**Rerun compatibility:** ``pytest-rerunfailures`` works transparently —
the JSON report and step outputs reflect the final state after all
retries have been exhausted.
--------------
License
-------
MIT