Usage

Options

These are the options that can be added to the pytest.ini file.


  • extras_screenshots

The screenshots to add in the report.

Accepted values:

  • all: Include all gathered screenshots in the report.

  • last: Include only the last screenshot of each test in the report. Works only when using pytest-html plugin and if the API has been previously called during the test execution.

  • fail: Include only the last screenshot of each failed and skipped test in the report. Works only when using pytest-html plugin and if the API has been previously called during the test execution.

  • none: Exclude all screenshots in the report.

Default value: all


  • extras_sources

Whether to include gathered webpage sources in the report.

Default value: False


  • extras_attachment_indent

The indent to use for attachments.

Accepted values: any positive integer.

Default value: 4


  • extras_issue_link_pattern

The pattern for the issues links (example: https://bugtracker.com/issues/{})

Default value: None


  • extras_tms_link_pattern

The pattern for the test-case links (example: https://tms.com/tests/{})

Default value: None


  • extras_links_column

The type of links to display in the Links columns of the pytest report.

Accepted values: all, issue, tms, link or none

Default value: all


  • extras_title

The test report title

Default value: Test Report

API

The function scoped fixture report provides the following methods:

To add a step with screenshot:

screenshot(
    comment: str,                                # Comment of the test step.
    target: WebDriver | WebElement | Page | Locator = None,  # The screenshot target.
    full_page: bool = True,                      # Whether to take a full page screenshot.
    page_source: bool = False,                   # Whether to include the webpage HTML source.
    escape_html: bool = True                     # Whether to escape HTML characters in the comment.
)

To add a step with attachment:

attach(
    comment: str,                                 # Comment of the test step.
    body: str | bytes | dict | list[str] = None,  # The content/body of the attachment.
    source: str = None,                           # The filepath of the attachment.
    mime: Mime | str = None,                      # The attachment mime type.
    escape_html: bool = True                      # Whether to escape HTML characters in the comment.
)

# Type of 'body'' parameter:
#    str: - for XML, JSON, YAML, CSV or TXT attachments
#         - for image attachments if it is a base64 string
#    bytes: for image attachments
#    dict: for JSON attachments
#    list[str]: for list-uri attachments

# The supported mime types are:
#    report.Mime.JSON   or "application/json"   or "json"
#    report.Mime.XML    or "application/xml"    or "xml"
#    report.Mime.YAML   or "application/yaml"   or "yaml"
#    report.Mime.MP3    or "audio/mpeg"         or "mp3"
#    report.Mime.OGA    or "audio/ogg"          or "oga"
#    report.Mime.BMP    or "image/bmp"          or "bmp"
#    report.Mime.GIF    or "image/gif"          or "gif"
#    report.Mime.JPEG   or "image/jpeg"         or "jpeg"
#    report.Mime.PNG    or "image/png"          or "png"
#    report.Mime.SVG    or "image/svg+xml"      or "svg"
#    report.Mime.CSV    or "text/csv"           or "csv"
#    report.Mime.HTML   or "text/html"          or "html"
#    report.Mime.TEXT   or "text/plain"         or "text"
#    report.Mime.URI    or "text/uri-list"      or "uri"
#    report.Mime.MP4    or "video/mp4"          or "mp4"
#    report.Mime.OGV    or "video/ogg"          or "ogv"
#    report.Mime.WEBM   or "video/webm"         or "webm"

To add links to the report:

@pytest.mark.issue("<issue keys separated by comma>", icon: str)
@pytest.mark.tms("<test-case keys separated by comma>", icon: str)
@pytest.mark.link(url: str, name: str, icon: str)

Examples

When using the pytest-html plugin (with the --html option), an external CSS file may be provided with the --css option.

Command-line invocation

If using pytest-html report:

pytest --html=path/to/report --css=path/to/css

If using Allure report:

pytest --alluredir=path/to/allure-results

If using both reports:

pytest --html=path/to/report --css=path/to/css --alluredir=path/to/allure-results

Sample pytest.ini file

extras_attachment_indent = 4
extras_screenshots = all
extras_sources = False
extras_issue_link_pattern = http://bugtracker.com/{}
extras_tms_link_pattern = http://tms.com/tests/{}
extras_links_column = all
extras_title = My awesome test report

Sample code

  • Example with Selenium

def test_with_selenium(report):
    """
    This is a test using Selenium
    """
    driver = WebDriver()
    driver.get("https://www.selenium.dev/selenium/web/web-form.html")
    report.screenshot("Get the webpage to test", driver)
    driver.find_element(By.ID, "my-text-id").send_keys("Hello World!")
    report.screenshot("<h1>Set input text</h1>", driver, full_page=True, escape_html=False)
    driver.find_element(By.NAME, "my-password").send_keys("password")
    report.screenshot(comment="Another comment", target=driver)
    report.screenshot("Comment without screenshot")
    report.screenshot(comment="Comment without screenshot")
    driver.quit()
  • Example with Playwright

def test_with_playwright(browser: Browser, report):
    """
    This is a test using Playwright
    """
    context = browser.new_context(record_video_dir="path/to/videos/")
    page = context.new_page()
    page.goto("https://www.wikipedia.org")
    report.screenshot("Wikipedia page", page)
    context.close()
    page.close()
    report.attach("Recorded video", source=page.video.path(), report.Mime.WEBM)
  • Example with attachments

def test_attachments(report):
    report.attach(
        "This is a XML document:",
        body="<root><child>text</child></root>",
        mime=report.Mime.XML
    )
    report.attach(
        comment="This is a JSON document:",
        source="path/to/file",
        mime="json"
    )
  • Example with links

@pytest.mark.tms("TEST-3")
@pytest.mark.issue("PROJ-123, PROJ-456")
@pytest.mark.link("https://example.com")
@pytest.mark.link(uri="https://wikipedia.org", name="Wikipedia")
@pytest.mark.link(uri="https://wikipedia.org", name="Wikipedia", icon="&#129373;")
def test_link_markers(report)
    pass
  • Example with pytest-bdd (cucumber)

Feature: Wikipedia

Scenario: Search in Wikipedia
  Given I go to Wikipedia
  When I search for "pizza"
  Then the page title is "Pizza - Wikipedia"
import pytest
from pytest_bdd import scenarios, given, when, then, parsers
from playwright.sync_api import sync_playwright, Page

scenarios('features/wikipedia.feature')

@pytest.fixture
def playwright_context():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        yield page
        browser.close()

@given('I go to Wikipedia')
def go_to_wikipedia(playwright_context: Page, report):
    playwright_context.goto("https://www.wikipedia.org")
    assert "Wikipedia" in playwright_context.title()
    report.screenshot("Wikipedia page", playwright_context)

@when(parsers.parse('I search for "{term}"'))
def search_wikipedia(playwright_context: Page, term, report):
    playwright_context.locator("[id='searchInput']").fill(term)
    playwright_context.keyboard.press("Enter")
    playwright_context.wait_for_load_state("load")
    report.screenshot("The searched page", playwright_context)

@then(parsers.parse('the page title is "{title}"'))
def check_title(playwright_context: Page, title):
    assert playwright_context.title() == title

Sample CSS file

.extras_comment {
    font-family: monospace;
    color: blue;
}

.extras_comment strong {
    color: black;
}

.extras_color_skipped {
    color: #727272;
}

.extras_color_xfailed,
.extras_color_xpassed {
    color: #b37400;
}

.extras_color_error {
    color: black;
}

.extras_color_failed {
    color: red;
}

.extras_header td {
    padding-top: 10px;
    vertical-align: top;
}

.extras_header_separator {
    width: 10px;
}

.extras_td_multimedia {
    width: 320px;
}

.extras_td_multimedia div {
    text-align: center;
}

.extras_title {
    color: black;
    font-size: medium;
    font-weight: bold;
}

.extras_description {
    color: black;
    font-size: 16px;
}

.extras_params_key {
    color: #999;
    font-size: 14px;
}

.extras_params_value {
    color: black;
    font-size: 14px;
}

.extras_header_block {
    white-space: pre-wrap;
    overflow-wrap: break-word;
    margin-top: 0px;
    margin-bottom: 0px;
    margin-left: 0px;
}

.visibility_links a {
    text-decoration: none;
    color: darkslategrey;
}

.extras_separator {
    height: 1px;
    background-color: gray;
}

.extras_video {
    border: 1px solid #e6e6e6;
    width: 300px;
    height: 170px;
}

.extras_td_multimedia svg {
    border: 1px solid #e6e6e6;
    width: 300px;
    height: 170px;
}

.extras_image {
    border: 1px solid #e6e6e6;
    width: 300px;
    height: 170px;
    object-fit: cover;
    object-position: top;
}

.extras_page_src {
    color: #00b5ff;
    font-size: 12px;
}

.extras_attachment {
    color: black;
    margin-left: 30px;
    margin-right: 30px;
}

.extras_comment code,
.extras_attachment_block {
    white-space: pre-wrap;
    overflow-wrap: break-word;
    padding: .2em .4em;
    color: black;
    background-color: #818b981f;
    border-radius: 6px;
}

.extras_attachment_error {
    color: red;
}

.extras_iframe {
    margin-top: 15px;
    margin-left: 30px;
    margin-right: 30px;
    resize: both;
    overflow: auto;
    background-color: #faf0e6;
    inline-size: -webkit-fill-available;
}

.extras_status {
    border-radius: 3px;
    color: #fff;
    font-size: medium;
    font-weight: bold;
    letter-spacing: 1px;
    padding: 2px 4px 2px 5px;
    vertical-align: baseline;
}

.extras_status_passed {
    background: #97cc64;
}

.extras_status_failed {
    background: #fd5a3e;
}

.extras_status_skipped {
    background: #aaa;
}

.extras_status_xfailed,
.extras_status_xpassed {
    background: orange;
}

.extras_status_error {
    background: black;
}

.extras_status_reason {
    color: black;
    font-size: 14px;
}

Sample reports

  • pytest-html sample report

_images/demo-pytest.png
  • Allure sample report

_images/demo-allure.png