From 53f515f30551baaec9825bb3b97db31d68c59eaa Mon Sep 17 00:00:00 2001 From: John Cobbler <44442232+JohnCobbler@users.noreply.github.com> Date: Sat, 6 Jun 2026 01:17:37 +0000 Subject: [PATCH 1/2] Record a failing @test_logs as a failure instead of erroring A failing @test_logs produces a Test.LogTestFailure, which is not a Fail/Error/Broken, so ReTestSet has no record method for it and the failure throws a MethodError instead of being reported. Convert it to a Fail in record, as Test.DefaultTestSet does, so it is counted and printed like any other failure. Co-authored-by: Claude --- src/testset.jl | 5 +++++ test/runtests.jl | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/testset.jl b/src/testset.jl index a0de8bd..7edf795 100644 --- a/src/testset.jl +++ b/src/testset.jl @@ -93,6 +93,11 @@ ReTestSet(desc::String; verbose::Bool=false) = # For a non-passed result, simply store the result record(ts::ReTestSet, t::Union{Broken,Fail,Error}) = (push!(ts.results, t); t) +# `@test_logs` produces a `LogTestFailure` on failure, which is not a `Fail`. +# Convert it to `Fail` so the result counting and reporting below treat it as a +# failure, mirroring how `Test.DefaultTestSet` records it. +record(ts::ReTestSet, t::Test.LogTestFailure) = + (push!(ts.results, Fail(:test, t.orig_expr, t.logs, nothing, nothing, t.source, false)); t) # For a passed result, do not store the result since it uses a lot of memory record(ts::ReTestSet, t::Pass) = (ts.n_passed += 1; t) diff --git a/test/runtests.jl b/test/runtests.jl index 2f65ca7..8c9a8e9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1883,3 +1883,28 @@ end end @test Hijack.RUN == [1, 2, 3, 2, 3] end + +Test.@testset "record(::ReTestSet, ::LogTestFailure)" begin + ReTestSet = ReTest.Testset.ReTestSet + record = ReTest.Testset.record + anyfailed = ReTest.Testset.anyfailed + get_test_counts = ReTest.Testset.get_test_counts + + logfail = Test.LogTestFailure(:(@info "x"), LineNumberNode(1, :file), + Any[(:info, "x")], Any[]) + + # A failing `@test_logs` is recordable, and counts as a failure. + ts = ReTestSet(Main, "lt") + Test.@test record(ts, logfail) === logfail + Test.@test anyfailed(ts) + _, fails, errors, _ = get_test_counts(ts) + Test.@test fails == 1 + Test.@test errors == 0 + + # A testset with no failing result reports none. + ts2 = ReTestSet(Main, "lt_empty") + Test.@test !anyfailed(ts2) + _, fails2, errors2, _ = get_test_counts(ts2) + Test.@test fails2 == 0 + Test.@test errors2 == 0 +end From c601b459cbc6f131b17340d7fef485c0ad59dba5 Mon Sep 17 00:00:00 2001 From: John Cobbler <44442232+JohnCobbler@users.noreply.github.com> Date: Fri, 24 Jul 2026 15:30:53 +0000 Subject: [PATCH 2/2] test: failing @test_logs records as TestSetException (#50) Integration module FailingTestLogs asserts retest throws TestSetException instead of MethodError when @test_logs fails. --- test/runtests.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 8c9a8e9..f1f4860 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1280,6 +1280,25 @@ end # Failing """) end + +# * Failing @test_logs (#50) ................................................. +# A failing `@test_logs` must record as a failure (TestSetException), not +# MethodError from a missing record(::LogTestFailure) method. + +module FailingTestLogs +using ReTest +using Test: @test_logs + +@testset "logs fail" begin + # pattern expects "x", actual log is "y" → LogTestFailure + @test_logs (:info, "x") @info "y" +end +end # FailingTestLogs + +@chapter FailingTestLogs begin + @test_throws Test.TestSetException retest(FailingTestLogs) +end + module FailingLoops # we test that toplevel testset-for don't make retest unresponsive