From 7fafaaa2d1c1556d0d769d574a86758aad9052ef Mon Sep 17 00:00:00 2001 From: Beforerr Date: Thu, 30 Apr 2026 13:28:17 -0700 Subject: [PATCH] feat: make Test.jl exception handling preserves native output format --- go/client_test.go | 38 ++++++++++++++++++++++++++++++++++++ go/daemon.go | 7 +++++++ go/julia_client_runtime.jl | 24 +++++++++++++++++++++-- skills/julia-client/SKILL.md | 2 +- 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/go/client_test.go b/go/client_test.go index d6d18e1..005c2fa 100644 --- a/go/client_test.go +++ b/go/client_test.go @@ -273,6 +273,44 @@ func TestEvalErrorTraceSaved(t *testing.T) { require.Contains(t, resp.Error, "Stacktrace:") } +func TestEvalTestFailureKeepsNativeNoiseLevel(t *testing.T) { + socketPath, stop, _ := startTestDaemon(t) + defer stop() + + cwd, err := os.Getwd() + require.NoError(t, err) + + resp := sendRequest(t, socketPath, protocolRequest{ + Action: "eval", + Code: `using Test; @testset "x" begin @test false end`, + Cwd: cwd, + }) + require.Contains(t, resp.Output, "x: Test Failed") + require.Contains(t, resp.Output, "Test Summary:") + require.Equal(t, "ERROR: Some tests did not pass: 0 passed, 1 failed, 0 errored, 0 broken.", resp.Error) + require.NotContains(t, resp.Error, "Stacktrace:") + require.NotContains(t, resp.Error, "Trace saved") + require.NotContains(t, resp.Error, "TestSetException") + + trace := sendRequest(t, socketPath, protocolRequest{ + Action: "trace", + Cwd: cwd, + TraceLevel: "full", + }) + require.Empty(t, trace.Error) + require.Contains(t, trace.Output, "TestSetException") + + resp = sendRequest(t, socketPath, protocolRequest{ + Action: "eval", + Code: `using Test; @test false`, + Cwd: cwd, + }) + require.Contains(t, resp.Output, "Test Failed") + require.Equal(t, "ERROR: There was an error during testing", resp.Error) + require.NotContains(t, resp.Error, "Stacktrace:") + require.NotContains(t, resp.Error, "FallbackTestSetException") +} + func TestRevisePicksUpPackageChanges(t *testing.T) { socketPath, stop, _ := startTestDaemon(t) defer stop() diff --git a/go/daemon.go b/go/daemon.go index 728bf51..a8e02b6 100644 --- a/go/daemon.go +++ b/go/daemon.go @@ -123,12 +123,19 @@ func normalizedTraceLevel(level string) string { } func formatJuliaError(err *juliaEvalError, level string) string { + traceHint := strings.TrimSpace(err.smart) != strings.TrimSpace(err.short) switch normalizedTraceLevel(level) { case "short": + if !traceHint { + return err.short + } return err.short + "\n\nTrace saved: run `julia-client trace --trace [smart|full]` to inspect" case "full": return err.full default: + if !traceHint { + return err.short + } return err.smart + "Trace saved: run `julia-client trace` to inspect" } } diff --git a/go/julia_client_runtime.jl b/go/julia_client_runtime.jl index 3fbced9..0f1b41c 100644 --- a/go/julia_client_runtime.jl +++ b/go/julia_client_runtime.jl @@ -138,18 +138,38 @@ function _display_error(err) return err end +function _is_test_summary_exception(err) + err = _display_error(err) + name = nameof(typeof(err)) + mod = parentmodule(typeof(err)) + return string(nameof(mod)) == "Test" && string(name) in ("TestSetException", "FallbackTestSetException") +end + function _render_error(err, bt) frames = stacktrace(bt) cut = findfirst(frame -> frame.func === :include_string || String(frame.file) == "none", frames) cut === nothing || (frames = frames[1:max(cut - 2, 1)]) display_err = _display_error(err) - short = "ERROR: " * sprint(showerror, display_err) - smart = short * "\n" * _render_selected(frames; include_omitted=true) + test_exception = _is_test_summary_exception(display_err) + short_body = if test_exception + sprint() do io + Base.invokelatest(showerror, io, display_err, bt) + end + else + sprint(showerror, display_err) + end + short = "ERROR: " * short_body + if test_exception + smart = short + else + smart = short * "\n" * _render_selected(frames; include_omitted=true) + end full = sprint(showerror, err, bt) return short, smart, full end function _write_error(start_marker, end_marker, short, smart, full) + flush(stderr) write(stdout, "\n") println(stdout, start_marker) println(stdout, bytes2hex(Vector{UInt8}(codeunits(short)))) diff --git a/skills/julia-client/SKILL.md b/skills/julia-client/SKILL.md index 3d4d94b..10cb331 100644 --- a/skills/julia-client/SKILL.md +++ b/skills/julia-client/SKILL.md @@ -6,7 +6,7 @@ description: "Run Julia code with session state persistence, project env auto-de ## Running code ```bash -julia-client -e 'x=1' # Evaluate +julia-client -e 'x=setupOnce()' # Evaluate julia-client -E 'x' # Evaluate and display # Long-running tasks (pkg install, compile, plot, heavy compute): set longer timeout or disable timeout (0)