v0.19.0 - #164
Open
eda-s-claude-bot[bot] wants to merge 21 commits into
Open
Conversation
`TagReleaseCommit` starts the tag pipeline through `createWorkflowDispatch`, so
the run is a `workflow_dispatch` event and GitHub titles it with the workflow's
name instead of the tag. A top-level `run-name` overrides the title without
changing the event:
run-name: ${{ github.ref_type == 'tag' && github.ref_name || '' }}
The empty string is the documented fallback to GitHub's event-specific default,
so pushes keep their commit message as the title and only tag runs are renamed.
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
A merged report never named the host it came from: the unified Testsuite had no field for it, so Testsuite.FromTestsuite() could not pass one on and every writer skipped the attribute it only emits when set. pytest and Ant write 'hostname' on every <testsuite> - 48 of 48 and 4 of 4 of the reference outputs in tests/data - so a merged pyTest-JUnit report without it is something pytest itself would never produce, and the pyTest-JUnit reader rightly rejects it with "Required parameter 'hostname' not found in tag 'testsuite'". Testsuite gains an optional 'hostname' with a matching @readonly property, and it is carried through Testsuite.ToTestsuite(), the four dialects' FromTestsuite() and MergedTestsuite. Merging combines the hostnames: a single value while every input agrees on it, "various" once two inputs disagree. A test suite without a hostname ran somewhere unrecorded rather than somewhere else, so it leaves an otherwise unanimous hostname alone. Two defects in the code this had to touch: * Testsuite.Copy() raised 'TypeError: Parameter 'teardownDuration' is not of type timedelta' for any test suite carrying a status - it passed nine arguments positionally against a signature whose second parameter is 'kind', so everything was shifted by one. It uses keyword arguments now. * MergedTestsuite.__init__() passed 'parent' positionally into the 'testsuites' slot, so the parent was silently dropped. Also keyword arguments now. CTestJUnit wrote str(None), producing hostname="None"; with no hostname recorded it now writes the same 'localhost' default the reader applies for an absent attribute. tests/unit/Unittesting/Hostname.py covers the data model, the six merge cases and both round trips; all 11 testcases fail without this change. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
* 'hostname' sits before 'startTime' in Testsuite.__init__, as it does in the JUnit dialects, and is passed positionally at the call sites. * Copy() is positional again, now listing every field in signature order - the previous list was missing 'kind' and 'testDuration', which is what made it raise. * _MergeHostname is a normal method taking only the other hostname, and its doc-string is compact. * CTestJUnit writes 'unknownhost' rather than 'localhost': a valid hostname would claim knowledge we don't have. * No empty line before the '_hostname' assignment. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
'parent=parent' is now the common style at every hand-over in the unit testing data model, matching how the other data models pass it as the last associated parameter. Five call sites in pyEDAA/Reports/Unittesting/__init__.py passed it positionally. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Ant-JUnit4 and CTest-JUnit root their report at <testsuite>, so its attributes belong to the document itself. Document.Convert() built that test suite from name, timestamp and time only, dropping the hostname the element carries - while the same dialect's _ConvertTestsuite(), used for nested suites, reads it. Found by converting between dialects: an Ant or CTest report written out as pyTest-JUnit could not be read back, because the hostname never reached the model in the first place. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Minor, not patch: Testsuite gained a 'hostname' parameter and a matching read-only property, and the parameter sits before 'startTime' as it does in the JUnit dialects - which shifts anyone passing arguments positionally. run.ps1 carries the version too, and was left at 0.18.0 by the previous bump. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #164 +/- ##
===========================================
- Coverage 70.93% 31.74% -39.19%
===========================================
Files 9 9
Lines 2477 2498 +21
Branches 393 396 +3
===========================================
- Hits 1757 793 -964
- Misses 540 1705 +1165
+ Partials 180 0 -180
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
Incorporates Dependabot's #157, #158, #159, #160 and #161: * twine ~= 6.2 -> ~= 7.0 (dist/requirements.txt) * setuptools >= 83.0 -> >= 84.0.0 (pyproject.toml) * sphinx_reports ~= 0.11.1 -> ~= 0.11.2 (doc/requirements.txt) * pyTooling ~= 8.18 -> ~= 8.19 (pyproject.toml, requirements.txt) * lxml >= 6.1 -> >= 6.1.1 (requirements.txt, tests/typing/requirements.txt) Each requirements file resolves with 'pip install --dry-run', which is what catches a bump that a passing test suite cannot - a resolver conflict between transitive pins. doc/Dependency.rst had drifted from the requirement files. Every version floor is taken from the requirements now, eleven packages that are required but were never listed are added - docstr_coverage, lxml-stubs, docutils, docutils_stubs, sphinx_rtd_theme, sphinxcontrib-mermaid, sphinxcontrib-autoprogram, autoapi, sphinx_design, sphinx-copybutton and sphinx_reports - and two that are no longer required are dropped: sphinx_btd_theme and sphinx_fontawesome, the latter already marked '!!' in the table. Licences and project links for the new rows are from PyPI. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
…ach other The defects fixed in #162 all lived between a writer and a reader, and no test looked there: nothing validated written output against the bundled schemas, and nothing converted one dialect into another. 24 test files and 94 testcases, zero schema assertions. tests/unit/JUnitDialects/ adds that level: * Schemas.py - every reference output in tests/data validates against its dialect's schema, and the reader accepts what the schema accepts. The reference outputs are ground truth: the schemas were reverse-engineered from them. * RoundTrip.py - per dialect: read a reference report, write it in the same dialect, validate it, read it back, and compare test case count, test case names and hostnames. * Translation.py - the 5x5 conversion matrix, each cell validated against the target schema and read back with the target dialect. Where a conversion cannot work today, KNOWN_GAPS names the pair and the reason and the test asserts that it *still* fails, so a fix turns the expectation red instead of passing unnoticed. Six pairs are listed; two of them are format limits rather than defects. The same pattern records that Any-JUnit rejects a <testsuite>-rooted report although it is the permissive dialect. tests/README.md writes down the strategy: the two phases, the four structural levels and how they map onto this repository, why tests/data is evidence rather than fixtures, and the known-gap convention. tests/unit: 98 -> 155 passed, 65 subtests. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
… from pyproject.toml * The version cells list major and minor only. A patch release does not change behaviour under semantic versioning, so the patch number is noise. A 0.0.x version is the exception - there the patch number is the only part that carries information - so docutils_stubs stays at 0.0.22. * requirements.txt: 'pyTooling[terminal] >= 8.19' rather than '>= 8.19.0', per the review suggestion. * The Packaging table listed pyTooling 8.18 and wheel, neither of which builds this package. It is generated from pyproject.toml's [build-system] requires now: setuptools and pyTooling. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
* Dialect uses the ExtendedType metaclass with slots, declares its fields with type hints, and its read-only properties are marked @readonly - including the Dialect property of the three test modules. * readReference() calls Aggregate() before handing the summary over, as the command line does before writing. Two of the four "defects" the matrix reported were this missing call: without it the writers see zero test cases and no duration, so they omitted 'time' and the target schema rejected the result. * KNOWN_GAPS is FORMAT_LIMITS. Every remaining entry names data the target format requires and the source does not carry - a timestamp, or more than the one test suite the format holds. A conversion failing for any other reason is a defect and does not belong in that table. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
CTest-JUnit.xsd and GoogleTest-JUnit.xsd require 'timestamp' - on <testsuite> and <testsuites>, and GoogleTest
down to <testcase>. Both writers emitted the attribute only when the model had a start time, so a report without
one produced a document their own reader and schema reject. GoogleTest was worse: the <testcase> timestamp was
written unguarded, so it raised 'AttributeError: NoneType object has no attribute isoformat' - the line carried a
'TODO: find a value'.
Both raise UnittestException naming the format, the element and what is missing:
The GoogleTest + JUnit format requires a timestamp on <testsuites>, but the report has none.
Refusing is the honest answer here: the value is not ours to invent, and a report without timestamps is not
expressible in these dialects. Deriving a summary's start time from its children would remove the restriction for
sources that do carry timestamps deeper in the hierarchy - worth doing, but that changes what Aggregate() means
and belongs in its own pull-request.
Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
* _DIALECT is declared on the base Document beside _TESTCASE, _TESTCLASS and _TESTSUITE, defaulting to "JUnit"; the dialects override it in the same aligned block, without the stray blank line. * The timestamp check is written where it is used instead of going through a helper - once in CTestJUnit, three times in GoogleTestJUnit, whose schema requires the attribute down to <testcase>. * tests/unit/Unittesting/Hostname.py: the import block is aligned to the longest module path again. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
The base classes derived from TestCase, so unittest collected them and pytest reported 11 skipped testcases that test nothing. They are mixins now - SchemaMixin, RoundTripMixin, TranslationMixin - and each dialect class derives from the mixin and TestCase. They use 'metaclass=ExtendedType' without 'mixin=True': that option raises 'BaseClassWithoutSlotsError: Base-classes TestCase doesn't use __slots__', because unittest.TestCase has no __slots__ and mixin=True requires them from every base class. With the skip guard gone, tests/unit/JUnitDialects reports 57 passed and no skips. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
unittest.TestCase is not created by ExtendedType and has no __slots__, so a mixin created by ExtendedType cannot be combined with it. Classic mixins are the right tool there: plain classes, no metaclass. The doc-strings and tests/README.md say why, so the next reader doesn't 'fix' them back. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
'JUnit' names no dialect - a JUnit XML file is whatever the tool writing it produces. This class is not purely infrastructure either: it is the implementation the command line uses for '--merge=Any-JUnit', so the accurate value is that one. Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New Features
pyEDAA.Reports.Unittesting:Testsuiterecords the host a test suite was executed on: a new optionalhostnameparameter and theread-only property
Testsuite.Hostname. The unified data model had no field for it, so the information wasdropped as soon as a report was read.
"various"once two inputsdisagree. A test suite without a hostname was executed somewhere unrecorded rather than somewhere else, so it
leaves an otherwise unanimous hostname alone.
Breaking Changes
pyEDAA.Reports.Unittesting:Testsuite.__init__takeshostnameas its third parameter, beforestartTime, matching the order the JUnit dialects use. Code constructing aTestsuitewith more than twopositional arguments has to pass
hostnameor switch to keyword arguments:Nothing else in the package or its tests still constructs a test suite positionally past
kind.Changes
pyEDAA.Reports.Unittesting:parent=parentis the common style at every hand-over in the unit testing datamodel, as in the other data models. Five call sites passed it positionally.
Bug Fixes
pyEDAA.Reports.Unittesting.JUnit:Testsuite.FromTestsuite()had nohostname to pass on and every writer emits the attribute only when it is set, so a merged
pyTest-JUnitreportcarried none - and the
pyTest-JUnitreader rejects that withRequired parameter 'hostname' not found in tag 'testsuite', exit code 255. Any two-stage merge hit it, whichis what a CI pipeline does when it merges per platform and then merges the results.
Ant-JUnit4andCTest-JUnitroot their report at<testsuite>, soDocument.Convert()builds that testsuite itself - from name, timestamp and time only. The
hostnameon the root element was dropped, althoughthe same dialect's
_ConvertTestsuite()reads it for nested suites.CTestJUnitwrotestr(testsuite._hostname), so a report with no recorded host got the literalhostname="None".CTest-JUnit.xsdrequires the attribute, so it is written asunknownhostnow.pyEDAA.Reports.Unittesting:Testsuite.Copy()raisedTypeError: Parameter 'teardownDuration' is not of type 'timedelta'for any testsuite carrying a status. It passed nine arguments positionally against a signature whose second parameter is
kind, omittingkindandtestDuration, so every value landed one position too early.MergedTestsuite.__init__()passedparentpositionally into thetestsuitesslot, soMergedTestsuite(suite, parent=x)silently produced a test suite whoseParentisNone.Documentation
doc/Dependency.rstmatches the requirement files again: eleven required packages that were never listed areadded, two that are no longer required are removed, and the version floors are taken from the requirements.
Unit Tests
tests/unit/Unittesting/Hostname.pyis new: 12 testcases covering the data model, the six hostname merge cases,the
<testsuite>-rooted dialects and both round trips.tests/unit: 86 → 98 passed.GitHub Pipeline
PublishTestResultsis enabled again.run-name.Dependencies
pyTooling=8.18 → **=8.19**,lxml>=6.1 → >=6.1.1,setuptools>=83.0 → >=84.0.0,sphinx_reports=0.11.1 → **=0.11.2**,twine=6.2 → **=7.0**.Others
Schema/Coverage/Cobertura.dtdwas added.Related Issues and Pull-Requests
[Dependabot]: Update twine requirement from ~=6.2 to ~=7.0 #157, [Dependabot]: Update setuptools requirement from >=83.0 to >=84.0.0 #158, [Dependabot]: Update sphinx-reports requirement from ~=0.11.1 to ~=0.11.2 #159, [Dependabot]: Update pytooling requirement from ~=8.18 to ~=8.19 #160 and [Dependabot]: Update lxml requirement from <7.0,>=6.1 to >=6.1.1,<7.0 #161, and the
Dependency.rstrepair.level - schema validation, round trips and the 5×5 translation matrix.
testsuite report with
Any-JUnit- can go back to the default dialect once this release is on PyPI.