Repository navigation
Conversation
…d merge_results()
rcasia
marked this pull request as ready for review
September 5, 2026 10:38
JunitResult still had a private create_file_with_content function doing real I/O (nio.fn.tempname, io.open, write, close), called directly from :result() and merge_results(). This tangled 'what happened in this test' (domain logic) with 'persist this output for neotest to read' (I/O concern) in the same class. - New neotest-java.util.output_writer: the only module that knows about io.open/nio.fn.tempname now. Function-as-constructor DI, injectable tempname_fn/open_file/run for fully I/O-free unit testing. - model/junit_result.lua is now pure: no nio/io requires at all. :result() and .merge_results() return plain data (status/output_lines/errors/short) instead of a neotest.Result with a file path already written. SKIPPED/ERROR do the same. - core/result_builder.lua composes the final neotest.Result via a new to_neotest_result(data, output_writer) helper, calling output_writer.write(data.output_lines) — it already owned tempname_fn in its deps, so it's the natural place to own this conversion. - core/junit_result_reader.lua no longer threads tempname_fn through to JunitResult:new (JunitResult has no use for it anymore); dropped the now-unused nio require. - Added tests/unit/test_output_writer_spec.lua (new module, fully I/O-free via injected open_file/run) and tests/unit/test_junit_result_spec.lua (JunitResult had no dedicated spec file before this refactor — now covers id/status/errors/output/result/merge_results/SKIPPED/ERROR directly, asserting no 'output' filepath leaks out of the pure data shape). - Updated existing reader/result-builder tests that referenced the removed tempname threading (JunitResult no longer stores .tempname). 203 test cases, 0 fails. luacheck: 0 warnings across 83 files.
- OutputWriter.write's data param: string | string[] | table -> string | table | nil, matching how it's actually called (nil is a valid no-op input, and output_lines mixes strings and nested tables, which the strict string[] annotation didn't represent). - JunitResultData.output_lines: string[] -> string | string[], since JunitResult.ERROR can set it directly to a raw string (process output). - Added nil-narrowing asserts in test_junit_result_spec.lua before indexing :errors() (typed as possibly nil).
rcasia
enabled auto-merge (squash)
September 5, 2026 11:47
rcasia
disabled auto-merge
September 5, 2026 11:47
… claims
Per feedback that the new tests weren't helpful/understandable, rewrote
both test_output_writer_spec.lua and test_junit_result_spec.lua:
- test_output_writer_spec.lua: replaced the ad-hoc filepath->content map
(which required tracing through a mutable closure to understand) with
a plain ordered list of {filepath, data} entries returned
directly from make_writer(). 'joins lines with a separator' and
'flattens nested tables' previously only checked that both substrings
existed independently, which would pass even without a separator or
in the wrong order — now they assert the exact expected concatenated
string.
- test_junit_result_spec.lua: replaced weak assertions
(type(x) == "table", eq(nil, data.output) checking a field that never
existed in the first place) with exact whole-table checks
against the full expected shape, so each test documents the complete
contract instead of a handful of disconnected field checks. Removed
the misleading 'delegates to junit_status.derive'/'without touching
disk' framings that didn't actually verify what their names claimed;
replaced with direct behavioral assertions (PASSED/FAILED + failures
content, exact merged output ordering, exact error messages).
lua-language-server, stylua, luacheck all clean. Full suite: 204 cases,
0 fails.
…review/split-junit-result
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.
Summary
Decomposes
model/junit_result.lua(the largest file in the codebase)by responsibility. Two rounds:
Round 1 — split pure JUnit-XML parsing concerns out of the class:
model/junit_failure.lua: failure/error XML node parsing + stack-traceline-number scraping
model/junit_status.lua: pass/fail/skip status derivationRound 2 (based on review feedback) — separated the remaining
file-writing responsibility out of the class entirely:
JunitResulthad a privatecreate_file_with_contentdoing real I/O(
nio.fn.tempname,io.open, write, close), called directly from:result()/merge_results(). This tangled 'what happened in thistest' (domain logic) with 'persist this output for neotest to read' (an
I/O concern) in the same class.
util/output_writer.lua: the only module that knows aboutio.open/nio.fn.tempnamenow. Function-as-constructor DI,fully unit-testable without touching disk.
model/junit_result.luais now pure — nonio/iorequires at all.:result()/.merge_results()/SKIPPED/ERRORreturn plain data(
status/output_lines/errors/short) instead of aneotest.Resultwith an already-written file path.core/result_builder.luacomposes the finalneotest.Resultvia a newto_neotest_result(data, output_writer), since it already ownedtempname_fnin its deps — the natural place for this conversion.tests/unit/test_output_writer_spec.lua(new module) andtests/unit/test_junit_result_spec.lua(JunitResult had no dedicatedspec file before this refactor — closed that gap).
Result
model/junit_result.lua: 324 -> 229 lines, zero I/Omodel/junit_failure.lua(81),model/junit_status.lua(37),util/output_writer.lua(69)JunitResultchanged::result()/.merge_results()/SKIPPED/ERRORnow return plain data, not aneotest.Resultwith afile path — callers (only
result_builder.lua) must pass it throughoutput_writer.write(...).Todo
Follow-up: separate file-writing from JunitResult (per review feedback)