refactor: stop overwriting pytest data (#597)
This commit is contained in:
parent
0408b0d504
commit
6eff86d537
|
@ -61,6 +61,9 @@ class BaseReport:
|
||||||
def data(self):
|
def data(self):
|
||||||
return self._data
|
return self._data
|
||||||
|
|
||||||
|
def add_test(self, test):
|
||||||
|
self._data["tests"].append(test)
|
||||||
|
|
||||||
def set_data(self, key, value):
|
def set_data(self, key, value):
|
||||||
self._data[key] = value
|
self._data[key] = value
|
||||||
|
|
||||||
|
@ -206,7 +209,7 @@ class BaseReport:
|
||||||
def pytest_sessionstart(self, session):
|
def pytest_sessionstart(self, session):
|
||||||
config = session.config
|
config = session.config
|
||||||
if hasattr(config, "_metadata") and config._metadata:
|
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)
|
session.config.hook.pytest_html_report_title(report=self._report)
|
||||||
|
|
||||||
|
@ -214,7 +217,7 @@ class BaseReport:
|
||||||
session.config.hook.pytest_html_results_table_header(cells=header_cells)
|
session.config.hook.pytest_html_results_table_header(cells=header_cells)
|
||||||
self._report.set_data("resultsTableHeader", header_cells.html)
|
self._report.set_data("resultsTableHeader", header_cells.html)
|
||||||
|
|
||||||
self._report.data["runningState"] = "Started"
|
self._report.set_data("runningState", "Started")
|
||||||
self._generate_report()
|
self._generate_report()
|
||||||
|
|
||||||
@pytest.hookimpl(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
|
@ -224,7 +227,7 @@ class BaseReport:
|
||||||
summary=self._report.data["additionalSummary"]["summary"],
|
summary=self._report.data["additionalSummary"]["summary"],
|
||||||
postfix=self._report.data["additionalSummary"]["postfix"],
|
postfix=self._report.data["additionalSummary"]["postfix"],
|
||||||
)
|
)
|
||||||
self._report.data["runningState"] = "Finished"
|
self._report.set_data("runningState", "Finished")
|
||||||
self._generate_report()
|
self._generate_report()
|
||||||
|
|
||||||
@pytest.hookimpl(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
|
@ -235,35 +238,36 @@ class BaseReport:
|
||||||
|
|
||||||
@pytest.hookimpl(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_collection_finish(self, session):
|
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)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_runtest_logreport(self, report):
|
def pytest_runtest_logreport(self, report):
|
||||||
data = self._config.hook.pytest_report_to_serializable(
|
data = {
|
||||||
config=self._config, report=report
|
"duration": report.duration,
|
||||||
)
|
"when": report.when,
|
||||||
|
}
|
||||||
|
|
||||||
test_id = report.nodeid
|
test_id = report.nodeid
|
||||||
if report.when != "call":
|
if report.when != "call":
|
||||||
test_id += f"::{report.when}"
|
test_id += f"::{report.when}"
|
||||||
data["nodeid"] = test_id
|
data["testId"] = test_id
|
||||||
|
|
||||||
# Order here matters!
|
# Order here matters!
|
||||||
log = report.longreprtext or report.capstdout or "No log output captured."
|
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()
|
row_cells = self.Cells()
|
||||||
self._config.hook.pytest_html_results_table_row(report=report, cells=row_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 = []
|
table_html = []
|
||||||
self._config.hook.pytest_html_results_table_html(report=report, data=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)})
|
data["extras"] = self._process_extras(report, test_id)
|
||||||
self._report.data["tests"].append(data)
|
self._report.add_test(data)
|
||||||
self._generate_report()
|
self._generate_report()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,8 @@
|
||||||
<template id="template_results-table__head">
|
<template id="template_results-table__head">
|
||||||
<thead id="results-table-head">
|
<thead id="results-table-head">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="sortable" data-column-type="outcome">Result</th>
|
<th class="sortable" data-column-type="result">Result</th>
|
||||||
<th class="sortable" data-column-type="nodeid">Test</th>
|
<th class="sortable" data-column-type="testid">Test</th>
|
||||||
<th class="sortable" data-column-type="duration">Duration</th>
|
<th class="sortable" data-column-type="duration">Duration</th>
|
||||||
<th>Links</th>
|
<th>Links</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -6,7 +6,7 @@ class DataManager {
|
||||||
const dataBlob = { ...data, tests: data.tests.map((test, index) => ({
|
const dataBlob = { ...data, tests: data.tests.map((test, index) => ({
|
||||||
...test,
|
...test,
|
||||||
id: `test_${index}`,
|
id: `test_${index}`,
|
||||||
collapsed: collapsedCategories.includes(test.outcome.toLowerCase()),
|
collapsed: collapsedCategories.includes(test.result.toLowerCase()),
|
||||||
})) }
|
})) }
|
||||||
this.data = { ...dataBlob }
|
this.data = { ...dataBlob }
|
||||||
this.renderData = { ...dataBlob }
|
this.renderData = { ...dataBlob }
|
||||||
|
|
|
@ -52,7 +52,7 @@ const dom = {
|
||||||
const header = listHeader.content.cloneNode(true)
|
const header = listHeader.content.cloneNode(true)
|
||||||
const sortAttr = storageModule.getSort()
|
const sortAttr = storageModule.getSort()
|
||||||
const sortAsc = JSON.parse(storageModule.getSortDirection())
|
const sortAsc = JSON.parse(storageModule.getSortDirection())
|
||||||
const sortables = ['outcome', 'nodeid', 'duration']
|
const sortables = ['result', 'testId', 'duration']
|
||||||
|
|
||||||
sortables.forEach((sortCol) => {
|
sortables.forEach((sortCol) => {
|
||||||
if (sortCol === sortAttr) {
|
if (sortCol === sortAttr) {
|
||||||
|
@ -67,23 +67,23 @@ const dom = {
|
||||||
},
|
},
|
||||||
getListHeaderEmpty: () => listHeaderEmpty.content.cloneNode(true),
|
getListHeaderEmpty: () => listHeaderEmpty.content.cloneNode(true),
|
||||||
getColGroup: () => templateCollGroup.content.cloneNode(true),
|
getColGroup: () => templateCollGroup.content.cloneNode(true),
|
||||||
getResultTBody: ({ nodeid, id, longreprtext, duration, extras, resultsTableRow, tableHtml, outcome, collapsed }) => {
|
getResultTBody: ({ testId, id, log, duration, extras, resultsTableRow, tableHtml, result, collapsed }) => {
|
||||||
const outcomeLower = outcome.toLowerCase()
|
const resultLower = result.toLowerCase()
|
||||||
let formattedDuration = formatDuration(duration)
|
let formattedDuration = formatDuration(duration)
|
||||||
formattedDuration = formatDuration < 1 ? formattedDuration.ms : formattedDuration.formatted
|
formattedDuration = formatDuration < 1 ? formattedDuration.ms : formattedDuration.formatted
|
||||||
const resultBody = templateResult.content.cloneNode(true)
|
const resultBody = templateResult.content.cloneNode(true)
|
||||||
resultBody.querySelector('tbody').classList.add(outcomeLower)
|
resultBody.querySelector('tbody').classList.add(resultLower)
|
||||||
resultBody.querySelector('.col-result').innerText = outcome
|
resultBody.querySelector('.col-result').innerText = result
|
||||||
resultBody.querySelector('.col-result').classList.add(`${collapsed ? 'expander' : 'collapser'}`)
|
resultBody.querySelector('.col-result').classList.add(`${collapsed ? 'expander' : 'collapser'}`)
|
||||||
resultBody.querySelector('.col-result').dataset.id = id
|
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
|
resultBody.querySelector('.col-duration').innerText = duration < 1 ? formatDuration(duration).ms : formatDuration(duration).formatted
|
||||||
|
|
||||||
|
|
||||||
if (longreprtext) {
|
if (log) {
|
||||||
// resultBody.querySelector('.log').innerText = longreprtext
|
// resultBody.querySelector('.log').innerText = log
|
||||||
resultBody.querySelector('.log').innerHTML = longreprtext
|
resultBody.querySelector('.log').innerHTML = log
|
||||||
}
|
}
|
||||||
// if (collapsed || !longreprtext) {
|
// if (collapsed || !longreprtext) {
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ const { manager } = require('./datamanager.js')
|
||||||
const storageModule = require('./storage.js')
|
const storageModule = require('./storage.js')
|
||||||
|
|
||||||
const getFilteredSubSet = (filter) =>
|
const getFilteredSubSet = (filter) =>
|
||||||
manager.allData.tests.filter(({ outcome }) => filter.includes(outcome.toLowerCase()))
|
manager.allData.tests.filter(({ result }) => filter.includes(result.toLowerCase()))
|
||||||
|
|
||||||
const doInitFilter = () => {
|
const doInitFilter = () => {
|
||||||
const currentFilter = storageModule.getVisible()
|
const currentFilter = storageModule.getVisible()
|
||||||
|
|
|
@ -29,7 +29,7 @@ const renderStatic = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderContent = (tests) => {
|
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 rows = renderSet.map(dom.getResultTBody)
|
||||||
const table = document.querySelector('#results-table')
|
const table = document.querySelector('#results-table')
|
||||||
removeChildren(table)
|
removeChildren(table)
|
||||||
|
@ -62,30 +62,30 @@ const renderContent = (tests) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderDerived = (tests, collectedItems, isFinished) => {
|
const renderDerived = (tests, collectedItems, isFinished) => {
|
||||||
const renderSet = tests.filter(({ when, outcome }) => when === 'call' || outcome === 'Error')
|
const renderSet = tests.filter(({ when, result }) => when === 'call' || result === 'Error')
|
||||||
|
|
||||||
const possibleOutcomes = [
|
const possibleResults = [
|
||||||
{ outcome: 'passed', label: 'Passed' },
|
{ result: 'passed', label: 'Passed' },
|
||||||
{ outcome: 'skipped', label: 'Skipped' },
|
{ result: 'skipped', label: 'Skipped' },
|
||||||
{ outcome: 'failed', label: 'Failed' },
|
{ result: 'failed', label: 'Failed' },
|
||||||
{ outcome: 'error', label: 'Errors' },
|
{ result: 'error', label: 'Errors' },
|
||||||
{ outcome: 'xfailed', label: 'Unexpected failures' },
|
{ result: 'xfailed', label: 'Unexpected failures' },
|
||||||
{ outcome: 'xpassed', label: 'Unexpected passes' },
|
{ result: 'xpassed', label: 'Unexpected passes' },
|
||||||
{ outcome: 'rerun', label: 'Reruns' },
|
{ result: 'rerun', label: 'Reruns' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const currentFilter = getVisible()
|
const currentFilter = getVisible()
|
||||||
possibleOutcomes.forEach(({ outcome, label }) => {
|
possibleResults.forEach(({ result, label }) => {
|
||||||
const count = renderSet.filter((test) => test.outcome.toLowerCase() === outcome).length
|
const count = renderSet.filter((test) => test.result.toLowerCase() === result).length
|
||||||
const input = document.querySelector(`input[data-test-result="${outcome}"]`)
|
const input = document.querySelector(`input[data-test-result="${result}"]`)
|
||||||
document.querySelector(`.${outcome}`).innerText = `${count} ${label}`
|
document.querySelector(`.${result}`).innerText = `${count} ${label}`
|
||||||
|
|
||||||
input.disabled = !count
|
input.disabled = !count
|
||||||
input.checked = currentFilter.includes(outcome)
|
input.checked = currentFilter.includes(result)
|
||||||
})
|
})
|
||||||
|
|
||||||
const numberOfTests = renderSet.filter(({ outcome }) =>
|
const numberOfTests = renderSet.filter(({ result }) =>
|
||||||
['Passed', 'Failed', 'XPassed', 'XFailed'].includes(outcome)).length
|
['Passed', 'Failed', 'XPassed', 'XFailed'].includes(result)).length
|
||||||
|
|
||||||
if (isFinished) {
|
if (isFinished) {
|
||||||
const accTime = tests.reduce((prev, { duration }) => prev + duration, 0)
|
const accTime = tests.reduce((prev, { duration }) => prev + duration, 0)
|
||||||
|
|
|
@ -41,7 +41,7 @@ const setFilter = (currentFilter) => {
|
||||||
|
|
||||||
const getSort = () => {
|
const getSort = () => {
|
||||||
const url = new URL(window.location.href)
|
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 setSort = (type) => {
|
||||||
const url = new URL(window.location.href)
|
const url = new URL(window.location.href)
|
||||||
|
|
|
@ -13,27 +13,27 @@ const setTestData = () => {
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
'id': 'passed_1',
|
'id': 'passed_1',
|
||||||
'outcome': 'passed',
|
'result': 'passed',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'failed_2',
|
'id': 'failed_2',
|
||||||
'outcome': 'failed',
|
'result': 'failed',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'passed_3',
|
'id': 'passed_3',
|
||||||
'outcome': 'passed',
|
'result': 'passed',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'passed_4',
|
'id': 'passed_4',
|
||||||
'outcome': 'passed',
|
'result': 'passed',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'passed_5',
|
'id': 'passed_5',
|
||||||
'outcome': 'passed',
|
'result': 'passed',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'passed_6',
|
'id': 'passed_6',
|
||||||
'outcome': 'passed',
|
'result': 'passed',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ describe('Filter tests', () => {
|
||||||
|
|
||||||
doInitFilter()
|
doInitFilter()
|
||||||
expect(managerSpy.callCount).to.eql(1)
|
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', () => {
|
it('exclude passed', () => {
|
||||||
getFilterMock = sinon.stub(storageModule, 'getVisible').returns(['failed'])
|
getFilterMock = sinon.stub(storageModule, 'getVisible').returns(['failed'])
|
||||||
|
@ -63,7 +63,7 @@ describe('Filter tests', () => {
|
||||||
|
|
||||||
doInitFilter()
|
doInitFilter()
|
||||||
expect(managerSpy.callCount).to.eql(1)
|
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', () => {
|
describe('doFilter', () => {
|
||||||
|
@ -76,7 +76,7 @@ describe('Filter tests', () => {
|
||||||
|
|
||||||
doFilter('passed', true)
|
doFilter('passed', true)
|
||||||
expect(managerSpy.callCount).to.eql(1)
|
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',
|
'passed', 'passed', 'passed', 'passed', 'passed',
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
@ -101,18 +101,18 @@ describe('Sort tests', () => {
|
||||||
|
|
||||||
doInitSort()
|
doInitSort()
|
||||||
expect(managerSpy.callCount).to.eql(1)
|
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',
|
'passed', 'failed', 'passed', 'passed', 'passed', 'passed',
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
it('has stored sort preference', () => {
|
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)
|
sortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(false)
|
||||||
managerSpy = sinon.spy(dataModule.manager, 'setRender')
|
managerSpy = sinon.spy(dataModule.manager, 'setRender')
|
||||||
|
|
||||||
doInitSort()
|
doInitSort()
|
||||||
expect(managerSpy.callCount).to.eql(1)
|
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',
|
'failed', 'passed', 'passed', 'passed', 'passed', 'passed',
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
@ -127,16 +127,16 @@ describe('Sort tests', () => {
|
||||||
afterEach(() => [
|
afterEach(() => [
|
||||||
getSortMock, setSortMock, getSortDirectionMock, setSortDirection, managerSpy,
|
getSortMock, setSortMock, getSortDirectionMock, setSortDirection, managerSpy,
|
||||||
].forEach((fn) => fn.restore()))
|
].forEach((fn) => fn.restore()))
|
||||||
it('sort on outcome', () => {
|
it('sort on result', () => {
|
||||||
getSortMock = sinon.stub(storageModule, 'getSort').returns(null)
|
getSortMock = sinon.stub(storageModule, 'getSort').returns(null)
|
||||||
setSortMock = sinon.stub(storageModule, 'setSort')
|
setSortMock = sinon.stub(storageModule, 'setSort')
|
||||||
getSortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(null)
|
getSortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(null)
|
||||||
setSortDirection = sinon.stub(storageModule, 'setSortDirection')
|
setSortDirection = sinon.stub(storageModule, 'setSortDirection')
|
||||||
managerSpy = sinon.spy(dataModule.manager, 'setRender')
|
managerSpy = sinon.spy(dataModule.manager, 'setRender')
|
||||||
|
|
||||||
doSort('outcome')
|
doSort('result')
|
||||||
expect(managerSpy.callCount).to.eql(1)
|
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',
|
'passed', 'passed', 'passed', 'passed', 'passed', 'failed',
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue