Skip to content

Commit 056dd08

Browse files
jernstJohannes Ernst
andauthored
HTML report improvements and related unit tests (#433)
* Lint improvement * Improve HTML reports. * More unit tests for transcript and HTML generation. Closes #332 Closes #232 --------- Co-authored-by: Johannes Ernst <[email protected]>
1 parent 5993cc0 commit 056dd08

File tree

10 files changed

+412
-23
lines changed

10 files changed

+412
-23
lines changed

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ dependencies = [
2222
"multidict",
2323
"jinja2",
2424
"pyhamcrest",
25-
"pytest",
2625
"requests",
2726
"types-requests",
28-
"pre-commit"
27+
"pre-commit",
28+
29+
# For testing: not sure how to specify this just for testing
30+
"pytest",
31+
"beautifulsoup4"
2932
]
33+
3034
description = "Test framework to test distributed, heterogeneous systems with complex protocols such as the Fediverse"
3135
readme = "README-PyPI.md"
3236

src/feditest/testrun.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ def transcribe(self) -> TestRunTranscript:
496496

497497
trans_sessions.append(TestRunSessionTranscript(
498498
run_session.plan_constellation_index,
499+
len(self.run_sessions),
499500
cast(datetime, run_session.started),
500501
cast(datetime, run_session.ended),
501502
trans_constellation,

src/feditest/testruntranscript.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ class TestRunSessionTranscript(msgspec.Struct):
296296
Captures information about the run of a single session in a transcript.
297297
"""
298298
run_session_index: int
299+
total_sessions: int
299300
started : datetime
300301
ended : datetime
301302
constellation: TestRunConstellationTranscript
@@ -315,7 +316,8 @@ def build_summary(self, augment_this: TestRunTranscriptSummary | None = None ):
315316

316317

317318
def __str__(self):
318-
return f"Session {self.run_session_index}"
319+
return f"Test Run Session { self.run_session_index + 1 }/{ self.total_sessions }"
320+
# +1 for what humans expect when it says 1/2
319321

320322

321323
class TestRunTranscript(msgspec.Struct):
@@ -383,6 +385,6 @@ def has_compatible_version(self):
383385

384386
def __str__(self):
385387
if self.plan.name:
386-
return f'{ self.id } ({ self.plan.name })'
387-
return self.id
388+
return str(self.plan.name)
389+
return 'Test Run'
388390

src/feditest/testruntranscriptserializer/html.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class HtmlRunTranscriptSerializer(TestRunTranscriptSerializer):
5454
A CSS file will be written to the provided destination with an extra extension.
5555
"""
5656

57-
def __init__(self, template_path: str):
57+
def __init__(self, template_path: str | None = None):
5858
if template_path:
5959
self.template_path = [ t.strip() for t in template_path.split(",") ]
6060
else:

src/feditest/testruntranscriptserializer/templates/testplantranscript_default/matrix.jinja2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<html lang="en">
33
<head>
44
{% include "partials/shared/head.jinja2" %}
5-
<title>{{ transcript.plan.name | e }} | Feditest</title>
5+
<title>{{ transcript | e }} ({{ transcript.id }}) | Feditest</title>
66
</head>
77
<body>
88
<header class="feditest title">
9-
<h1><span class="prefix"><a href="https://feditest.org/">Feditest</a> Summary Report:</span> {{ transcript.plan.name | e }}</h1>
9+
<h1><span class="prefix"><a href="https://feditest.org/">Feditest</a>:</span> {{ transcript | e }}</h1>
1010
<p class="id">{{ transcript.id }}</p>
1111
</header>
1212
{% include "partials/shared/mobile.jinja2" %}

src/feditest/testruntranscriptserializer/templates/testplantranscript_default/partials/matrix/matrix.jinja2

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
{%- set constellation = run_session.constellation %}
66
<th>
77
<div class="title">
8-
<a href="{{ session_file_path(run_session) }}">
9-
<dl class="roles">
8+
<p><a href="{{ session_file_path(run_session) }}">{{ run_session }}</a></p>
9+
<dl class="roles">
1010
{%- for role, node in constellation.nodes.items() %}
11-
<dt>{{ role | e }}</dt>
12-
<dd>{{ node.node_driver | e }}</dd>
11+
<dt>{{ role | e }}</dt>
12+
<dd>{{ node.appdata['app'] | e }}</dd>
1313
{%- endfor %}
14-
</dl>
15-
</a>
14+
</dl>
1615
</div>
1716
</th>
1817
{%- endfor %}

src/feditest/testruntranscriptserializer/templates/testplantranscript_default/session_with_matrix.jinja2

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
<html lang="en">
33
<head>
44
{% include "partials/shared/head.jinja2" %}
5-
<title>{{ run_session.name | e }} | Feditest</title>
5+
<title>{{ run_session | e }} ({{ transcript.id }}) | Feditest</title>
66
</head>
77
<body>
8-
<header class="feditest title" style="text-align: center">
9-
<h1><span class="prefix"><a href="https://feditest.org/">Feditest</a> Session Report:</span> {{ run_session | e }}</h1>
10-
<p class="id">{{ transcript.id }} [<a href="{{ matrix_file_path }}">Summary</a>]</p>
11-
</header>
12-
13-
{% include "partials/shared/mobile.jinja2" %}
8+
<header class="feditest title" style="text-align: center">
9+
<h1><span class="prefix"><a href="https://feditest.org/">Feditest</a>:</span> {{ run_session | e }}</h1>
10+
<p class="id">{{ transcript.id }} <a href="{{ matrix_file_path }}">&#x21e7;</a></p>
11+
</header>
12+
{% include "partials/shared/mobile.jinja2" %}
1413
<nav class="feditest matrix">
1514
<ul>
1615
<li><a href="#summary">Summary</a></li>
@@ -19,14 +18,14 @@
1918
</ul>
2019
</nav>
2120
<div id="summary" class="feditest module summary">
22-
<h2>Test Run Summary</h2>
21+
<h2>Test Run Session Summary</h2>
2322
{% include "partials/shared/summary.jinja2" %}
2423
</div>
2524
<div id="results" class="feditest module results">
2625
{% include "partials/shared_session/results.jinja2" %}
2726
</div>
2827
<div id="metadata" class="feditest module metadata">
29-
<h2>Test Run Metadata</h2>
28+
<h2>Test Run Session Metadata</h2>
3029
{% include "partials/shared_session/metadata.jinja2" %}
3130
</div>
3231
{% include "partials/shared/footer.jinja2" %}

tests.unit/dummy.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Dummy classes for testing
3+
#
4+
5+
from feditest.nodedrivers import AccountManager, Node, NodeConfiguration, NodeDriver
6+
7+
8+
class DummyNode(Node):
9+
pass
10+
11+
12+
class DummyNodeDriver(NodeDriver):
13+
# Python 3.12 @Override
14+
def _provision_node(self, rolename: str, config: NodeConfiguration, account_manager: AccountManager | None) -> Node:
15+
return DummyNode(rolename, config, account_manager)
16+

tests.unit/test_50_transcript.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#
2+
# Test the transcript has all the expected values
3+
#
4+
5+
import pytest
6+
7+
import feditest
8+
from feditest import nodedriver, test
9+
from feditest.utils import FEDITEST_VERSION
10+
from feditest.testplan import TestPlan, TestPlanConstellation, TestPlanConstellationNode, TestPlanSessionTemplate, TestPlanTestSpec
11+
from feditest.testrun import TestRun
12+
from feditest.testruncontroller import AutomaticTestRunController
13+
from feditest.testruntranscript import TestRunResultTranscript
14+
15+
from dummy import DummyNodeDriver
16+
17+
APP_NAMES = [
18+
'APP_0',
19+
'APP_1',
20+
'APP_2',
21+
'APP_3'
22+
]
23+
driver_names = []
24+
25+
@pytest.fixture(scope="module", autouse=True)
26+
def init_node_drivers():
27+
global driver_names
28+
29+
""" Keep these isolated to this module """
30+
feditest.all_node_drivers = {}
31+
feditest._loading_node_drivers = True
32+
33+
@nodedriver
34+
class NodeDriver1(DummyNodeDriver):
35+
pass
36+
37+
@nodedriver
38+
class NodeDriver2(DummyNodeDriver):
39+
pass
40+
41+
feditest._loading_node_drivers = False
42+
43+
driver_names = list(feditest.all_node_drivers.keys())
44+
45+
46+
@pytest.fixture(scope="module", autouse=True)
47+
def init_tests():
48+
"""
49+
Cleanly define some tests.
50+
"""
51+
feditest.all_tests = {}
52+
feditest._registered_as_test = {}
53+
feditest._registered_as_test_step = {}
54+
feditest._loading_tests = True
55+
56+
##
57+
## FediTest tests start here
58+
##
59+
60+
@test
61+
def passes() -> None:
62+
"""
63+
This test always passes.
64+
"""
65+
return
66+
67+
##
68+
## FediTest tests end here
69+
## (Don't forget the next two lines)
70+
##
71+
72+
feditest._loading_tests = False
73+
feditest._load_tests_pass2()
74+
75+
76+
@pytest.fixture(autouse=True)
77+
def test_plan_fixture() -> TestPlan:
78+
"""
79+
The test plan tests all known tests.
80+
"""
81+
constellations = [
82+
TestPlanConstellation(
83+
{
84+
'node1a': TestPlanConstellationNode(
85+
driver_names[0],
86+
{
87+
'app' : APP_NAMES[0]
88+
}
89+
),
90+
'node2a': TestPlanConstellationNode(
91+
driver_names[1],
92+
{
93+
'app' : APP_NAMES[1]
94+
}
95+
)
96+
},
97+
'constellation-1'),
98+
TestPlanConstellation(
99+
{
100+
'node1b': TestPlanConstellationNode(
101+
driver_names[0],
102+
{
103+
'app' : APP_NAMES[2]
104+
}
105+
),
106+
'node2b': TestPlanConstellationNode(
107+
driver_names[1],
108+
{
109+
'app' : APP_NAMES[3]
110+
}
111+
)
112+
},
113+
'constellation-2')
114+
]
115+
tests = [ TestPlanTestSpec(name) for name in sorted(feditest.all_tests.keys()) if feditest.all_tests.get(name) is not None ]
116+
session = TestPlanSessionTemplate(tests, "Test a test that passes")
117+
ret = TestPlan(session, constellations)
118+
ret.properties_validate()
119+
# ret.print()
120+
return ret
121+
122+
123+
@pytest.fixture
124+
def transcript(test_plan_fixture: TestPlan) -> TestRunResultTranscript:
125+
test_plan_fixture.check_can_be_executed()
126+
127+
test_run = TestRun(test_plan_fixture)
128+
controller = AutomaticTestRunController(test_run)
129+
test_run.run(controller)
130+
131+
ret = test_run.transcribe()
132+
return ret
133+
134+
135+
def test_transcript(transcript: TestRunResultTranscript):
136+
assert transcript.plan
137+
assert transcript.id
138+
assert transcript.started
139+
assert transcript.ended
140+
141+
assert len(transcript.sessions) == 2
142+
assert len(transcript.test_meta) == 1
143+
assert transcript.result is None
144+
assert transcript.type == 'feditest-testrun-transcript'
145+
assert transcript.feditest_version == FEDITEST_VERSION
146+
147+
for i in range(0, 1):
148+
assert transcript.sessions[i].started
149+
assert transcript.sessions[i].ended
150+
assert len(transcript.sessions[i].run_tests) == 1
151+
assert transcript.sessions[i].run_tests[0].started
152+
assert transcript.sessions[i].run_tests[0].ended
153+
assert transcript.sessions[i].run_tests[0].result is None
154+

0 commit comments

Comments
 (0)