Repository navigation
v0.2.0
Added
pytest_given.PytestGivenWarningis a top-level export, and a step or
attach()recorded in a test without@scenarionow warns with it instead of
pytest.PytestWarning.--given-title=TEXT(or thegiven_titleini) names the report, replacing the
rootdir name.- A parametrized scenario's parameter table now carries a typed column per varying
value —param,derived, orattachmentfor a varying attachment payload —
rather than one column per parametrize name. @scenario(group_parametrized=False)declines the grouping and emits each case
as its own scenario, titled by its parametrize id.- The HTML report's sidebar gains Terms as a third browse axis, and all three
axes — Tags, Terms, Modules — now filter the Scenarios view the same way, with
each active filter carried in the URL. - The sidebar can be ordered by group size as well as by name, and resized by
dragging its seam or with the arrow keys. - A selected activity in the Stories view offers Open in Scenarios, filtering
the Scenarios view down to the scenarios covering it.
Changed
CLI
- Breaking.
--given-lintis a plain boolean flag: write--given-lintand
--no-given-lintinstead of--given-lint=true/--given-lint=false. Either
form still overrides thegiven_lintini for one run.
Authoring API
-
Breaking. Step narration must now be uniform across parametrize cases;
these fail the run withPytestGivenError, writing no report, instead of
quietly reporting case 1:- a plain
str(usually an f-string) that renders differently per case; - a varying interpolation that is not a bare name (
t"{cup_size * 0.01}",
t"{m.balance}"); - a t-string narrating a parametrize name that no longer holds the case's
value — either a local rebound it, or the body mutated it in place; - a step whose set of
attachlabels differs between cases; - a glossary term ref that names a different term or reads differently between
cases, including one bound to a parametrize column; - passed cases that narrate different templates altogether.
Every one but the last is fixed by binding the varying part to a local and
narrating it with a t-string, keeping labels and term refs constant; varying
content belongs in the newattachmentcolumn. The last needs
@scenario(..., group_parametrized=False), giving each case its own scenario. - a plain
-
Breaking.
attach()now takes a plainstrlabel; a t-string label raises
PytestGivenError— use an f-string. -
Breaking.
attach()called with no step open now raisesPytestGivenError
instead of silently discarding the payload; move the call inside the step it
belongs to. -
Breaking.
activity(..., id=N)is nowactivity(..., activity_id=N); the
Activity.idfield itself is unchanged. -
Breaking.
FileGlossaryis now aGlossarysubclass rather than a wrapper
around one, so its.glossaryattribute is gone — use theFileGlossary
itself wherever that attribute was passed. -
A glossary term placed in an activity slot its declared kind forbids now raises
PytestGivenErrorwhenactivity(...)is built rather than at session finish. -
A glossary file whose table has a header and separator but no data rows now
says so, instead of reporting that no table was found. -
A
FileGlossarywhose columns are all named now skips a Markdown table that
carries none of those names, so a glossary file may hold prose tables beside
the glossary; a table carrying some of them still raises, as does any table
under an index-based column spec. -
@scenario(activities=...)now rejects astrand non-intmembers with a
TypeError. -
@scenarionow returns the test function itself rather than a wrapper, so the
test keeps its own signature.
Plugin and run behavior
- An unknown
given_source_linkpreset is now aUsageErrorraised before the
suite runs. - The collection-time
@scenariochecks now report as aUsageErrorinstead of
anINTERNALERRORtraceback. - The narration lint summary prints each finding's location in its own column
rather than appended to the message. pytest-givenwith no subcommand, andpytest-given skillswith no
subcommand, now print that parser's usage and exit 2 instead of the root help
and exit 1.
Report content (all formats)
- Breaking (JSON report).
parameters.namesbecomesparameters.columns
({id, name, kind}), cells may hold an attachment object, placeholder parts
gaincolumn_id, term-ref parts loseparam_column, and a grouped step's
narration.textis the template rather than case 1's rendering. - Breaking (JSON report). A step no longer carries
statusorerror;
failure lives on the scenario and on the parameter table's cases. A consumer
readingstep.statusshould readscenario.statusinstead. - The Markdown report now shows a scenario's failure reason — the message and the
failing frame — under the scenario, and under the parameter table for each
failed case.
HTML report
- The browse sidebar leads with Modules and renders them as a collapsible
package tree whose nodes filter by path prefix; it no longer lists individual
scenarios under each group. - The report's colors are retuned into one system — a term ref in a step or a
scenario title reads as a word under a light wash rather than a bordered pill
(the Glossary view keeps its pills), and column colors are generated per
column — and the sidebar, its filter chips and the attachment badges are
tidied along with it. - The report opens and filters substantially faster on large suites, and its file
is smaller — a term reference now points at its glossary entry instead of
repeating the entry's definition, which takes about 18% off a term-heavy
report. - A glossary term referenced only in a
@scenariotitle now contributes an
instance to the Glossary view, where it previously counted toward the term's
scenario tally while showing no instance.
Bundled skills
- The authoring and reviewing skills gain the report mechanics their rules depend
on, a symptom index, a completeness audit, the full lint rule catalog, and
guidance for sparser tagging.
Removed
- Breaking. The
divergent-case-structurelint rule; delete any
given_lint_rulesorgiven_lint_ignoreentry naming it, which would
otherwise fail config parsing.
Fixed
Authoring API
-
Parametrize cases that claim different step activities now say so, instead of
reporting the more drastic "a different step structure". -
A
@givenfixture scoped wider thanfunctionno longer loses its step when
the first test to use it has no@scenario. -
@given/@when/@thenare signature-preserving, so a decorated helper stays
callable to a type checker (was:"StepDecorated" not callable). -
@given(...)above@pytest.fixturenow raises and names the fix, instead of
surfacing asfixture '<name>' not found. -
@scenario(activities=...)is now typedint | Sequence[int] | None, so a
bareactivities=2type-checks. -
@scenario(activities=...)with an unknown id, or withoutstory=, is
rejected at the decorator rather than at collection. -
A
-k- or--deselect-narrowed run no longer fails on an authoring error in
a scenario it did not select. -
Glossary term handles are now hashable, and equal for the same term whichever
accessor produced them. -
A
when_thenstep in a test without@scenarionow points its warning at the
test rather than at pytest-given's own module.
Narration lint
-
A
given_lint_ignoreentry beginning with a Windows drive letter
(c:/repo/tests/t.py::test_x) is no longer rejected as an unknown rule prefix. -
A rule configured
offno longer runs; levels were applied only after every
rule had already produced its findings. -
A scenario tag with no ASCII alphanumerics (
tags=['日本語']) no longer takes
the run down with a traceback fromtag-shadows-term.
Report
pytest-given reportreports an unreadable input as an error instead of a
traceback (a directory raisedIsADirectoryErrorthrough the console script).- A JSON report with an out-of-range scenario
statusor termkindis
rejected by name, instead of crashing a renderer with a bareKeyError. - A
<br>inside an inline code span in a glossary definition renders as text
rather than as a line break. - The Terms browse axis no longer lists a term the selected glossary does not
hold.
Plugin and run behavior
- A
--given-json/--given-html/--given-mdpath that could not be a report
file is now refused before the suite runs, instead of a bare flag swallowing a
following test path and overwriting — or, on a failed run, deleting — it. pytest-given reportnow discards a stale report when the render fails, not
only when the write does.pytest-given report --source-linkis now validated on a--format mdrun
instead of being accepted and ignored, and an unknown preset is reported under
the name the user typed.- A
giton PATH that cannot be executed no longer fails the run. - A nested in-process pytest run that dies while parsing its arguments no longer
strands the outer session's captured rootdir, which silently dropped every
later step's source anchor. @given/@when/@thenon anasync defhelper now records around the
awaited body, and async generator fixtures are handled too.- The narration lint now inspects
async defstep helpers, whose bodies were
invisible to every AST rule. - An explicit
--given-source-link=now disables source links instead of falling
through to thegiven_source_linkini. - A finished scenario no longer leaves its collector — and every scenario and
step it recorded — reachable from a process-global for the rest of the process. - An error-level lint finding no longer overwrites a more specific exit code, so
an interrupted or nothing-collected run keeps reporting as one. - A report that cannot be written into an unwritable directory now reports
through the terminal summary instead of escaping as a bare traceback. pytest-given reportandpytest-given skills installnow report a failed
write as a CLI error, and a failedreportwrite discards the previous run's
report rather than leaving it to read as current.pytest-given reportnow reports a bad input file — missing, unparsable, or
JSON that is not a pytest-given report — as a CLI error instead of a traceback,
as does an unknown--source-linkpreset.- A fixture that raises after its
yieldnow fails the scenario it tore down,
instead of leaving it green in a report pytest counted as an error. - An error-level narration-lint finding now counts as an error in the run's
summary line. - Every failure building or writing a report — a suite reaching two glossaries, a
term used in incompatible slots, an unusable source-link template, an
unwritable output path — now surfaces as a terminal summary and a failing exit
code, where only grouping errors did. - The sinks are now rendered in full before any is written, and a failure on
either side discards all of them.
Report content (all formats)
-
A parametrized scenario whose cases all skipped now keeps its skip reason
instead of reportingskippedwith none. -
A parameter row whose cell count disagreed with the table's columns silently
truncated in the HTML report; it now fails the same way it already did in
Markdown. -
A parametrized scenario now keeps its place in source order instead of moving
below every unparametrized one. -
A glossary term written as a code span keeps the markup inside it, so
`a*b*c`canonicalizes toa*b*c. -
A parameter-table cell now reads the way the step pointing at it read, carrying
the interpolation's own format spec and, underindirect=True, the bound test
argument. -
A
Templatenarration'stextis now what its parts render, so the report's
search box andjqqueries match what the page displays. -
The grouped step tree now comes from the first case that passed, where a
skipped case 1 used to render an empty tree. -
A parametrize value that is a glossary term instance now narrates as its
display rather than the wholeGlossarydataclass repr — in a step's
Templateslot, in a scenario name, and in an
Annotated[..., given(Template(...))]parameter label.
HTML report
- Two test files sharing a basename across directories no longer abort the HTML
report; the scenarios'#scenario=slugs gain directory components instead. - A
#view=stories,#view=glossaryor#term=link opened against a report
that has no such tab now falls back to the Scenarios view. - The Glossary view's kind headings and their term counts now follow the search
and definition filters, and a filter matching nothing says so. - Content reaching past a scenario card's right edge is no longer clipped: a wide
parameter table and an attachment payload scroll, a source path and a
traceback's frame location wrap, and the source link no longer overlaps the
card's last element. - Jumping to a scenario from a story activity, or to a term's scenarios from the
Glossary tab, now clears filters that would hide the target; the filters in a
#scenario=deep link still win. - Accent-colored text and the parametrize column colors now meet WCAG AA, and
term kinds stay distinguishable for red-green color blindness. - The report is operable from the keyboard: status pills, browse-axis and
browse-tree rows, tag pills, story sidebar entries, activity and attachment
badges, and every expand/collapse chevron are now real buttons, and the view
tabs report which one is selected. - A step pinned with
given(..., activity=N)now covers an activity regardless
of its term count; an under-anchored activity previously still rendered as
"not coverage-tracked".
Bundled skills
- The bundled skills are corrected against the shipped behavior.