Add debug info

This commit is contained in:
Darren Burns
2022-09-21 15:18:53 +01:00
parent 53ac7b4fa4
commit 04a513ff9f
4 changed files with 118 additions and 25 deletions

View File

@@ -6,7 +6,7 @@ class CenterLayoutExample(App):
CSS_PATH = "center_layout.css"
def compose(self) -> ComposeResult:
yield Static("One", id="bottom")
yield Static("Onee", id="bottom")
yield Static("Two", id="middle")
yield Static("Three", id="top")

View File

@@ -4,6 +4,7 @@ import os
import shlex
from typing import Iterable
from textual.app import App
from textual._import_app import import_app
# This module defines our "Custom Fences", powered by SuperFences
@@ -25,7 +26,9 @@ def format_svg(source, language, css_class, options, md, attrs, **kwargs) -> str
try:
rows = int(attrs.get("lines", 24))
columns = int(attrs.get("columns", 80))
svg = take_svg_screenshot(path, press, title, terminal_size=(rows, columns))
svg = take_svg_screenshot(
None, path, press, title, terminal_size=(rows, columns)
)
finally:
os.chdir(cwd)
@@ -39,8 +42,9 @@ def format_svg(source, language, css_class, options, md, attrs, **kwargs) -> str
def take_svg_screenshot(
app_path: str,
press: Iterable[str] = ("_", "_"),
app: App | None = None,
app_path: str | None = None,
press: Iterable[str] = ("_",),
title: str | None = None,
terminal_size: tuple[int, int] = (24, 80),
) -> str:
@@ -48,7 +52,10 @@ def take_svg_screenshot(
os.environ["COLUMNS"] = str(columns)
os.environ["LINES"] = str(rows)
app = import_app(app_path)
if app is None:
app = import_app(app_path)
app.console.legacy_windows = False
if title is None:
title = app.title

View File

@@ -1,4 +1,6 @@
import difflib
import os
import pprint
from dataclasses import dataclass
from datetime import datetime
from functools import partial
@@ -13,15 +15,19 @@ from _pytest.fixtures import FixtureRequest
from _pytest.main import Session
from _pytest.terminal import TerminalReporter
from jinja2 import Template
from rich import inspect
from rich.console import Console
from rich.panel import Panel
from syrupy import SnapshotAssertion
from textual.app import App
from textual._doc import take_svg_screenshot
from textual._import_app import import_app
snapshot_svg_key = pytest.StashKey[str]()
actual_svg_key = pytest.StashKey[str]()
snapshot_pass = pytest.StashKey[bool]()
TEXTUAL_SNAPSHOT_SVG_KEY = pytest.StashKey[str]()
TEXTUAL_ACTUAL_SVG_KEY = pytest.StashKey[str]()
TEXTUAL_SNAPSHOT_PASS = pytest.StashKey[bool]()
TEXTUAL_APP_KEY = pytest.StashKey[App]()
@pytest.fixture
@@ -36,15 +42,17 @@ def snap_compare(
def compare(app_path: str, snapshot: SnapshotAssertion) -> bool:
node = request.node
actual_screenshot = take_svg_screenshot(app_path)
app = import_app(app_path)
actual_screenshot = take_svg_screenshot(app=app)
result = snapshot == actual_screenshot
if result is False:
# The split and join below is a mad hack, sorry...
node.stash[snapshot_svg_key] = "\n".join(str(snapshot).splitlines()[1:-1])
node.stash[actual_svg_key] = actual_screenshot
node.stash[TEXTUAL_SNAPSHOT_SVG_KEY] = "\n".join(str(snapshot).splitlines()[1:-1])
node.stash[TEXTUAL_ACTUAL_SVG_KEY] = actual_screenshot
node.stash[TEXTUAL_APP_KEY] = app
else:
node.stash[snapshot_pass] = True
node.stash[TEXTUAL_SNAPSHOT_PASS] = True
return result
@@ -59,6 +67,8 @@ class SvgSnapshotDiff:
file_similarity: float
path: PathLike
line_number: int
app: App
environment: dict
def pytest_sessionfinish(
@@ -73,22 +83,28 @@ def pytest_sessionfinish(
diffs: List[SvgSnapshotDiff] = []
num_snapshots_passing = 0
for item in session.items:
num_snapshots_passing += int(item.stash.get(snapshot_pass, False))
snapshot_svg = item.stash.get(snapshot_svg_key, None)
actual_svg = item.stash.get(actual_svg_key, None)
if snapshot_svg and actual_svg:
# Grab the data our fixture attached to the pytest node
num_snapshots_passing += int(item.stash.get(TEXTUAL_SNAPSHOT_PASS, False))
snapshot_svg = item.stash.get(TEXTUAL_SNAPSHOT_SVG_KEY, None)
actual_svg = item.stash.get(TEXTUAL_ACTUAL_SVG_KEY, None)
app = item.stash.get(TEXTUAL_APP_KEY, None)
if snapshot_svg and actual_svg and app:
path, line_index, name = item.reportinfo()
diffs.append(
SvgSnapshotDiff(
snapshot=str(snapshot_svg),
actual=str(actual_svg),
file_similarity=100
* difflib.SequenceMatcher(
* difflib.SequenceMatcher(
a=str(snapshot_svg), b=str(actual_svg)
).ratio(),
test_name=name,
path=path,
line_number=line_index + 1,
app=app,
environment=dict(os.environ),
)
)

View File

@@ -8,6 +8,8 @@
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<div class="row mb-4" style="background-color:#F4F8F7;">
<div class="col-8 p-4">
@@ -51,14 +53,18 @@
</strong>
<span class="text-muted">({{ "%.2f"|format(diff.file_similarity) }}% source similarity)</span>
</div>
<span class="text-muted">{{ diff.path }}:{{ diff.line_number }}</span>
<div class="text-muted">
{{ diff.path }}:{{ diff.line_number }}
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col">
{{ diff.actual }}
<div class="w-100 d-flex justify-content-center mt-1">
<span class="small">Output from test</span>
<span class="small">Output from test (<a href="#" class="link-primary mb-0"
data-bs-toggle="modal"
data-bs-target="#environmentModal">More info</a>)</span>
</div>
</div>
<div class="col">
@@ -69,6 +75,63 @@
</div>
</div>
</div>
<div class="modal modal-lg fade" id="environmentModal" tabindex="-1"
aria-labelledby="environmentModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="environmentModalLabel">More info for <span
class="font-monospace">{{ diff.test_name }}</span></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body overflow-auto">
<h5>Textual App State</h5>
<table class="table mb-4">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="font-monospace">app.console.legacy_windows</td>
<td class="font-monospace">{{ diff.app.console.legacy_windows }}</td>
</tr>
<tr>
<td class="font-monospace">app.console.size</td>
<td class="font-monospace">{{ diff.app.console.size }}</td>
</tr>
</tbody>
</table>
<h5>Environment (<span class="font-monospace">os.environ</span>)</h5>
<table class="table">
<thead>
<tr>
<th scope="col">Variable</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
{% for key, value in diff.environment.items() %}
<tr>
<td class="font-monospace">{{ key }}</td>
<td class="font-monospace">{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -78,21 +141,28 @@
<div class="col">
<div class="card bg-light">
<div class="card-body">
<p class="card-text">If you're happy with the change, run pytest with the <span class="font-monospace text-primary">--snapshot-update</span> flag to update the snapshot.</p>
<p class="card-text">If you're happy with the test output, run pytest with the <span
class="font-monospace text-primary">--snapshot-update</span> flag to update the snapshot.
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="w-100 d-flex p-4 justify-content-center">
<p class="text-muted">Report generated at UTC {{ now }}.</p>
<div class="row">
<div class="col">
<div class="w-100 d-flex p-4 justify-content-center">
<p class="text-muted">Report generated at UTC {{ now }}.</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
crossorigin="anonymous"></script>
</body>
</html>