Pytest-html add/generate custom link/data to the HTML report

832 views Asked by At

I am using:

  • pytest 6.2.4
  • pytest-html 3.1.1
  • pytest-json-report 1.2.4
  • pytest-metadata 2.0.4

and I have the following simple tests in file test.py:

@pytest.mark.order(2)
@pytest.mark.parametrize('p_iteration', [x for x in range(3)])
def test_a(p_iteration):
    logging.info('test_a')
    if p_iteration == 2:
        logging.debug(f'I am parameter: {p_iteration}')
        assert True
    else:
        pass


@pytest.mark.order(1)
def test_b():
    logging.info('test_b')
    assert True

and I have in my conftest.py method:

def pytest_html_report_title(report):
    report.title = "My very own title!"


@pytest.hookimpl(tryfirst=True)
def pytest_html_results_table_header(cells):
    cells.insert(4, html.th('Custom Data Row'))


@pytest.hookimpl(tryfirst=True)
def pytest_html_results_table_row(report, cells):
    test_id = report
    custom_data = getattr(report, 'custom_data', test_id)  # Access the custom data from the report
    cells.insert(4, html.td(custom_data))

But when I wanted to add some custom data, e.g. link to the test being executed (not just the test name, like in Test column) I couldn't find the way, how to build up the link into the Custom Data Row column rows.

I also tried generate custom link into the report via hook method:

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()

    if report.when == "call":
        extra.append(pytest_html.extras.url(content="https://github.com" + os.sep + str(item.fspath), name="Link to test code"))
        extra.append(pytest_html.extras.text(content=str(report), name="Additional info"))
        report.extra = extra

this will generate the link, but of course the absolute path to the test file.

Is it possible to get the path of the test file being executed from the root of the working directory? I would like to prepend it with the link to the Git repository, so I would have links to the Git repository directly inside HTML report.

This is how my HTML report looks like: enter image description here

I looked at the official documentation for pytest-html: https://pytest-html.readthedocs.io/en/stable/user_guide.html but it didn't help to solve my problem.

1

There are 1 answers

0
karl5252 On

don`t know if you managed to get over it but here is what had worked for me so anyway I can share.

My former attempt went with appending the docstring value (as per docs) but I think it is against the intended use. I had also variable within the tests method '_trid' that worked pretty well though it was additional boilerplate.

This example seems to be cleaner but I need to check how it will behave with additional fixtures.

This is a test example (not very good one but hey!):

    @pytest.mark.testrail_id("C1231234")
def test_navigate_to_elements_page(self, testrail_id):
    """Test method to navigate to the Elements page."""
    home_page = ToolsQAHomePage(self)  
    home_page.navigate_to_home_page()  
    elements_page = home_page.navigate_to_elements_page()  
    assert elements_page.is_elements_page_loaded()  

This is part of conftest.py (majority of the code comes from pytest-html docs anyway):

def pytest_html_results_table_header(cells):
    cells.insert(1, "<th>TestRail ID</th>")
    # omited rest for clarity

def pytest_html_results_table_row(report, cells):
    cells.insert(3, f'<td><a href="http://server/view.html?{report._trid}">{report._trid}</a></td>')
# omited rest for clarity

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
    report.description = str(item.function.__doc__)

    # store as _trid the value from marker
    report._trid = item.get_closest_marker("testrail_id").args[0]
    # omited rest for clarity

I tried using extras (like you did) since it seemed the most organic way: extras.append(pytest_html.extras.url(f'{report._trid}')) However, for some reason it didn`t worked out properly.

### reporting to testrail
@pytest.fixture(scope="session")
def testrail_ids_collection():
    return []

# Fixture to associate TestRail IDs with tests
@pytest.fixture
def testrail_id(request, testrail_ids_collection):
    tr_id = request.node.get_closest_marker('testrail_id')
    if tr_id:
        testrail_id_value = tr_id.args[0]
        testrail_ids_collection.append(testrail_id_value)
        return testrail_id_value
    return None

Should output pytest-html report resulting pytest html report