Skip to content

refactor: stop overwriting pytest data #597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions src/pytest_html/nextgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def __init__(self, title, duration_format):
def data(self):
return self._data

def add_test(self, test):
self._data["tests"].append(test)

def set_data(self, key, value):
self._data[key] = value

Expand Down Expand Up @@ -206,15 +209,15 @@ def _write_report(self, rendered_report):
def pytest_sessionstart(self, session):
config = session.config
if hasattr(config, "_metadata") and config._metadata:
self._report.data["environment"] = self._generate_environment()
self._report.set_data("environment", self._generate_environment())

session.config.hook.pytest_html_report_title(report=self._report)

header_cells = self.Cells()
session.config.hook.pytest_html_results_table_header(cells=header_cells)
self._report.set_data("resultsTableHeader", header_cells.html)

self._report.data["runningState"] = "Started"
self._report.set_data("runningState", "Started")
self._generate_report()

@pytest.hookimpl(trylast=True)
Expand All @@ -224,7 +227,7 @@ def pytest_sessionfinish(self, session):
summary=self._report.data["additionalSummary"]["summary"],
postfix=self._report.data["additionalSummary"]["postfix"],
)
self._report.data["runningState"] = "Finished"
self._report.set_data("runningState", "Finished")
self._generate_report()

@pytest.hookimpl(trylast=True)
Expand All @@ -235,35 +238,36 @@ def pytest_terminal_summary(self, terminalreporter):

@pytest.hookimpl(trylast=True)
def pytest_collection_finish(self, session):
self._report.data["collectedItems"] = len(session.items)
self._report.set_data("collectedItems", len(session.items))

@pytest.hookimpl(trylast=True)
def pytest_runtest_logreport(self, report):
data = self._config.hook.pytest_report_to_serializable(
config=self._config, report=report
)
data = {
"duration": report.duration,
"when": report.when,
}

test_id = report.nodeid
if report.when != "call":
test_id += f"::{report.when}"
data["nodeid"] = test_id
data["testId"] = test_id

# Order here matters!
log = report.longreprtext or report.capstdout or "No log output captured."
data["longreprtext"] = _handle_ansi(log)
data["log"] = _handle_ansi(log)

data["outcome"] = _process_outcome(report)
data["result"] = _process_outcome(report)

row_cells = self.Cells()
self._config.hook.pytest_html_results_table_row(report=report, cells=row_cells)
data.update({"resultsTableRow": row_cells.html})
data["resultsTableRow"] = row_cells.html

table_html = []
self._config.hook.pytest_html_results_table_html(report=report, data=table_html)
data.update({"tableHtml": table_html})
data["tableHtml"] = table_html

data.update({"extras": self._process_extras(report, test_id)})
self._report.data["tests"].append(data)
data["extras"] = self._process_extras(report, test_id)
self._report.add_test(data)
self._generate_report()


Expand Down
4 changes: 2 additions & 2 deletions src/pytest_html/resources/index.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
<template id="template_results-table__head">
<thead id="results-table-head">
<tr>
<th class="sortable" data-column-type="outcome">Result</th>
<th class="sortable" data-column-type="nodeid">Test</th>
<th class="sortable" data-column-type="result">Result</th>
<th class="sortable" data-column-type="testid">Test</th>
<th class="sortable" data-column-type="duration">Duration</th>
<th>Links</th>
</tr>
Expand Down
2 changes: 1 addition & 1 deletion src/pytest_html/scripts/datamanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class DataManager {
const dataBlob = { ...data, tests: data.tests.map((test, index) => ({
...test,
id: `test_${index}`,
collapsed: collapsedCategories.includes(test.outcome.toLowerCase()),
collapsed: collapsedCategories.includes(test.result.toLowerCase()),
})) }
this.data = { ...dataBlob }
this.renderData = { ...dataBlob }
Expand Down
18 changes: 9 additions & 9 deletions src/pytest_html/scripts/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const dom = {
const header = listHeader.content.cloneNode(true)
const sortAttr = storageModule.getSort()
const sortAsc = JSON.parse(storageModule.getSortDirection())
const sortables = ['outcome', 'nodeid', 'duration']
const sortables = ['result', 'testId', 'duration']

sortables.forEach((sortCol) => {
if (sortCol === sortAttr) {
Expand All @@ -67,23 +67,23 @@ const dom = {
},
getListHeaderEmpty: () => listHeaderEmpty.content.cloneNode(true),
getColGroup: () => templateCollGroup.content.cloneNode(true),
getResultTBody: ({ nodeid, id, longreprtext, duration, extras, resultsTableRow, tableHtml, outcome, collapsed }) => {
const outcomeLower = outcome.toLowerCase()
getResultTBody: ({ testId, id, log, duration, extras, resultsTableRow, tableHtml, result, collapsed }) => {
const resultLower = result.toLowerCase()
let formattedDuration = formatDuration(duration)
formattedDuration = formatDuration < 1 ? formattedDuration.ms : formattedDuration.formatted
const resultBody = templateResult.content.cloneNode(true)
resultBody.querySelector('tbody').classList.add(outcomeLower)
resultBody.querySelector('.col-result').innerText = outcome
resultBody.querySelector('tbody').classList.add(resultLower)
resultBody.querySelector('.col-result').innerText = result
resultBody.querySelector('.col-result').classList.add(`${collapsed ? 'expander' : 'collapser'}`)
resultBody.querySelector('.col-result').dataset.id = id
resultBody.querySelector('.col-name').innerText = nodeid
resultBody.querySelector('.col-name').innerText = testId

resultBody.querySelector('.col-duration').innerText = duration < 1 ? formatDuration(duration).ms : formatDuration(duration).formatted


if (longreprtext) {
// resultBody.querySelector('.log').innerText = longreprtext
resultBody.querySelector('.log').innerHTML = longreprtext
if (log) {
// resultBody.querySelector('.log').innerText = log
resultBody.querySelector('.log').innerHTML = log
}
// if (collapsed || !longreprtext) {
if (collapsed) {
Expand Down
2 changes: 1 addition & 1 deletion src/pytest_html/scripts/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { manager } = require('./datamanager.js')
const storageModule = require('./storage.js')

const getFilteredSubSet = (filter) =>
manager.allData.tests.filter(({ outcome }) => filter.includes(outcome.toLowerCase()))
manager.allData.tests.filter(({ result }) => filter.includes(result.toLowerCase()))

const doInitFilter = () => {
const currentFilter = storageModule.getVisible()
Expand Down
36 changes: 18 additions & 18 deletions src/pytest_html/scripts/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const renderStatic = () => {
}

const renderContent = (tests) => {
const renderSet = tests.filter(({ when, outcome }) => when === 'call' || outcome === 'Error' )
const renderSet = tests.filter(({ when, result }) => when === 'call' || result === 'Error' )
const rows = renderSet.map(dom.getResultTBody)
const table = document.querySelector('#results-table')
removeChildren(table)
Expand Down Expand Up @@ -62,30 +62,30 @@ const renderContent = (tests) => {
}

const renderDerived = (tests, collectedItems, isFinished) => {
const renderSet = tests.filter(({ when, outcome }) => when === 'call' || outcome === 'Error')

const possibleOutcomes = [
{ outcome: 'passed', label: 'Passed' },
{ outcome: 'skipped', label: 'Skipped' },
{ outcome: 'failed', label: 'Failed' },
{ outcome: 'error', label: 'Errors' },
{ outcome: 'xfailed', label: 'Unexpected failures' },
{ outcome: 'xpassed', label: 'Unexpected passes' },
{ outcome: 'rerun', label: 'Reruns' },
const renderSet = tests.filter(({ when, result }) => when === 'call' || result === 'Error')

const possibleResults = [
{ result: 'passed', label: 'Passed' },
{ result: 'skipped', label: 'Skipped' },
{ result: 'failed', label: 'Failed' },
{ result: 'error', label: 'Errors' },
{ result: 'xfailed', label: 'Unexpected failures' },
{ result: 'xpassed', label: 'Unexpected passes' },
{ result: 'rerun', label: 'Reruns' },
]

const currentFilter = getVisible()
possibleOutcomes.forEach(({ outcome, label }) => {
const count = renderSet.filter((test) => test.outcome.toLowerCase() === outcome).length
const input = document.querySelector(`input[data-test-result="${outcome}"]`)
document.querySelector(`.${outcome}`).innerText = `${count} ${label}`
possibleResults.forEach(({ result, label }) => {
const count = renderSet.filter((test) => test.result.toLowerCase() === result).length
const input = document.querySelector(`input[data-test-result="${result}"]`)
document.querySelector(`.${result}`).innerText = `${count} ${label}`

input.disabled = !count
input.checked = currentFilter.includes(outcome)
input.checked = currentFilter.includes(result)
})

const numberOfTests = renderSet.filter(({ outcome }) =>
['Passed', 'Failed', 'XPassed', 'XFailed'].includes(outcome)).length
const numberOfTests = renderSet.filter(({ result }) =>
['Passed', 'Failed', 'XPassed', 'XFailed'].includes(result)).length

if (isFinished) {
const accTime = tests.reduce((prev, { duration }) => prev + duration, 0)
Expand Down
2 changes: 1 addition & 1 deletion src/pytest_html/scripts/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const setFilter = (currentFilter) => {

const getSort = () => {
const url = new URL(window.location.href)
return new URLSearchParams(url.search).get('sort') || 'outcome'
return new URLSearchParams(url.search).get('sort') || 'result'
}
const setSort = (type) => {
const url = new URL(window.location.href)
Expand Down
30 changes: 15 additions & 15 deletions testing/unittest.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,27 @@ const setTestData = () => {
[
{
'id': 'passed_1',
'outcome': 'passed',
'result': 'passed',
},
{
'id': 'failed_2',
'outcome': 'failed',
'result': 'failed',
},
{
'id': 'passed_3',
'outcome': 'passed',
'result': 'passed',
},
{
'id': 'passed_4',
'outcome': 'passed',
'result': 'passed',
},
{
'id': 'passed_5',
'outcome': 'passed',
'result': 'passed',
},
{
'id': 'passed_6',
'outcome': 'passed',
'result': 'passed',
},
],
}
Expand All @@ -55,15 +55,15 @@ describe('Filter tests', () => {

doInitFilter()
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ outcome }) => outcome)).to.eql([])
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([])
})
it('exclude passed', () => {
getFilterMock = sinon.stub(storageModule, 'getVisible').returns(['failed'])
managerSpy = sinon.spy(dataModule.manager, 'setRender')

doInitFilter()
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ outcome }) => outcome)).to.eql(['failed'])
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql(['failed'])
})
})
describe('doFilter', () => {
Expand All @@ -76,7 +76,7 @@ describe('Filter tests', () => {

doFilter('passed', true)
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ outcome }) => outcome)).to.eql([
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([
'passed', 'passed', 'passed', 'passed', 'passed',
])
})
Expand All @@ -101,18 +101,18 @@ describe('Sort tests', () => {

doInitSort()
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ outcome }) => outcome)).to.eql([
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([
'passed', 'failed', 'passed', 'passed', 'passed', 'passed',
])
})
it('has stored sort preference', () => {
sortMock = sinon.stub(storageModule, 'getSort').returns('outcome')
sortMock = sinon.stub(storageModule, 'getSort').returns('result')
sortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(false)
managerSpy = sinon.spy(dataModule.manager, 'setRender')

doInitSort()
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ outcome }) => outcome)).to.eql([
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([
'failed', 'passed', 'passed', 'passed', 'passed', 'passed',
])
})
Expand All @@ -127,16 +127,16 @@ describe('Sort tests', () => {
afterEach(() => [
getSortMock, setSortMock, getSortDirectionMock, setSortDirection, managerSpy,
].forEach((fn) => fn.restore()))
it('sort on outcome', () => {
it('sort on result', () => {
getSortMock = sinon.stub(storageModule, 'getSort').returns(null)
setSortMock = sinon.stub(storageModule, 'setSort')
getSortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(null)
setSortDirection = sinon.stub(storageModule, 'setSortDirection')
managerSpy = sinon.spy(dataModule.manager, 'setRender')

doSort('outcome')
doSort('result')
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ outcome }) => outcome)).to.eql([
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([
'passed', 'passed', 'passed', 'passed', 'passed', 'failed',
])
})
Expand Down