From f1c388e69c8d95b8ab5b912bdc8bee4f8ee49c5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:16:29 +0000 Subject: [PATCH 1/5] Initial plan From d7900147cb3d30a5d2d193b655bf417b7b784cb8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:21:13 +0000 Subject: [PATCH 2/5] Fix TestOutputHelper lifetime issue by guarding WriteLine calls Co-authored-by: kurtschelfthout <164917+kurtschelfthout@users.noreply.github.com> --- Directory.Packages.props | 1 - src/FsCheck.Xunit/CheckExtensions.fs | 26 +++++++---- src/FsCheck.Xunit/PropertyAttribute.fs | 14 +++++- src/FsCheck.Xunit/Runner.fs | 19 ++++++-- .../FsCheck.Test.CSharp.csproj | 9 ++++ .../TestOutputHelperLifetimeTests.cs | 43 +++++++++++++++++++ 6 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index cba689493..6eeced38c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,7 +4,6 @@ - diff --git a/src/FsCheck.Xunit/CheckExtensions.fs b/src/FsCheck.Xunit/CheckExtensions.fs index e3c48b333..b83f2f75a 100644 --- a/src/FsCheck.Xunit/CheckExtensions.fs +++ b/src/FsCheck.Xunit/CheckExtensions.fs @@ -6,29 +6,39 @@ open FsCheck open Xunit.Abstractions module private Helper = + // Helper to safely write to output, handling case where test may have completed + let private safeWriteLine (testOutputHelper: ITestOutputHelper) (message: string) = + try + testOutputHelper.WriteLine(message) + with + | :? InvalidOperationException -> + // Test has completed, TestOutputHelper is no longer active + // Silently ignore as this is expected when runners outlive test lifetime + () + let private runner (testOutputHelper: ITestOutputHelper) = { new IRunner with member __.OnStartFixture t = - Runner.onStartFixtureToString t |> testOutputHelper.WriteLine + Runner.onStartFixtureToString t |> safeWriteLine testOutputHelper member __.OnArguments (ntest,args, every) = - every ntest args |> testOutputHelper.WriteLine + every ntest args |> safeWriteLine testOutputHelper member __.OnShrink(args, everyShrink) = - everyShrink args |> testOutputHelper.WriteLine + everyShrink args |> safeWriteLine testOutputHelper member __.OnFinished(name,testResult) = - Runner.onFinishedToString name testResult |> testOutputHelper.WriteLine + Runner.onFinishedToString name testResult |> safeWriteLine testOutputHelper } let private throwingRunner (testOutputHelper: ITestOutputHelper) = { new IRunner with member __.OnStartFixture t = - testOutputHelper.WriteLine (Runner.onStartFixtureToString t) + safeWriteLine testOutputHelper (Runner.onStartFixtureToString t) member __.OnArguments (ntest,args, every) = - testOutputHelper.WriteLine (every ntest args) + safeWriteLine testOutputHelper (every ntest args) member __.OnShrink(args, everyShrink) = - testOutputHelper.WriteLine (everyShrink args) + safeWriteLine testOutputHelper (everyShrink args) member __.OnFinished(name,testResult) = match testResult with - | TestResult.Passed _ -> testOutputHelper.WriteLine (Runner.onFinishedToString name testResult) + | TestResult.Passed _ -> safeWriteLine testOutputHelper (Runner.onFinishedToString name testResult) | _ -> failwithf "%s" (Runner.onFinishedToString name testResult) } diff --git a/src/FsCheck.Xunit/PropertyAttribute.fs b/src/FsCheck.Xunit/PropertyAttribute.fs index 9bf940491..080df1f69 100644 --- a/src/FsCheck.Xunit/PropertyAttribute.fs +++ b/src/FsCheck.Xunit/PropertyAttribute.fs @@ -80,6 +80,16 @@ module internal PropertyConfig = { Rnd = Rnd (seed,gamma); Size = size } let toConfig (output : TestOutputHelper) propertyConfig = + // Helper to safely write to output, handling case where test may have completed + let safeWriteLine (message: string) = + try + output.WriteLine(message) + with + | :? InvalidOperationException -> + // Test has completed, TestOutputHelper is no longer active + // Silently ignore as this is expected when closures outlive test lifetime + () + Config.Default .WithReplay( propertyConfig.Replay @@ -100,13 +110,13 @@ module internal PropertyConfig = .WithRunner(XunitRunner()) .WithEvery( if propertyConfig.Verbose |> Option.exists id then - fun n args -> output.WriteLine (Config.Verbose.Every n args); "" + fun n args -> safeWriteLine (Config.Verbose.Every n args); "" else Config.Quick.Every ) .WithEveryShrink( if propertyConfig.Verbose |> Option.exists id then - fun args -> output.WriteLine (Config.Verbose.EveryShrink args); "" + fun args -> safeWriteLine (Config.Verbose.EveryShrink args); "" else Config.Quick.EveryShrink ) diff --git a/src/FsCheck.Xunit/Runner.fs b/src/FsCheck.Xunit/Runner.fs index ab682dc34..cdc4a842e 100644 --- a/src/FsCheck.Xunit/Runner.fs +++ b/src/FsCheck.Xunit/Runner.fs @@ -1,20 +1,31 @@ namespace FsCheck.Xunit open FsCheck +open System /// A runner for FsCheck (i.e. that you can use as Config.Runner) which outputs /// to Xunit's given ITestOutputHelper. /// For example, { Config.QuickThrowOnFailure with Runner = TestOutputRunner(output) } type TestOutputRunner(output: Xunit.Abstractions.ITestOutputHelper) = + // Helper to safely write to output, handling case where test may have completed + let safeWriteLine (message: string) = + try + output.WriteLine(message) + with + | :? InvalidOperationException -> + // Test has completed, TestOutputHelper is no longer active + // Silently ignore as this is expected when runner outlives test lifetime + () + interface IRunner with member _.OnStartFixture t = - output.WriteLine (Runner.onStartFixtureToString t) + safeWriteLine (Runner.onStartFixtureToString t) member _.OnArguments (ntest, args, every) = - output.WriteLine (every ntest args) + safeWriteLine (every ntest args) member _.OnShrink(args, everyShrink) = - output.WriteLine (everyShrink args) + safeWriteLine (everyShrink args) member _.OnFinished(name,testResult) = let resultText = Runner.onFinishedToString name testResult match testResult with - | TestResult.Passed _ -> resultText |> output.WriteLine + | TestResult.Passed _ -> resultText |> safeWriteLine | _ -> failwithf "%s" resultText \ No newline at end of file diff --git a/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj b/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj index 1e3bf162d..e1928ef60 100644 --- a/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj +++ b/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj @@ -6,4 +6,13 @@ false + + + + + + + + + diff --git a/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs b/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs new file mode 100644 index 000000000..afbd6cb5f --- /dev/null +++ b/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs @@ -0,0 +1,43 @@ +using Xunit; +using Xunit.Abstractions; + +namespace FsCheck.Test.CSharp +{ + /// + /// Reproduction test for GitHub issue: Lifetime problem with Xunit: InvalidOperationException: There is no currently active test. + /// This test class verifies that mixing Property and Fact tests with ITestOutputHelper doesn't cause lifetime issues. + /// + public class TestOutputHelperLifetimeTests + { + private readonly ITestOutputHelper _testOutputHelper; + + public TestOutputHelperLifetimeTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + [FsCheck.Xunit.Property] + public void Test1() + { + _testOutputHelper.WriteLine($"{nameof(Test1)}"); + } + + [Fact] + public void Test2() + { + _testOutputHelper.WriteLine($"{nameof(Test2)}"); + } + + [FsCheck.Xunit.Property] + public void Test3() + { + _testOutputHelper.WriteLine($"{nameof(Test3)}"); + } + + [Fact] + public void Test4() + { + _testOutputHelper.WriteLine($"{nameof(Test4)}"); + } + } +} From afa63378b85399b224c7c30ff87a270970c7ea5a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:22:42 +0000 Subject: [PATCH 3/5] Add test runner reference and verify fix works Co-authored-by: kurtschelfthout <164917+kurtschelfthout@users.noreply.github.com> --- tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj b/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj index e1928ef60..1074563b4 100644 --- a/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj +++ b/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj @@ -13,6 +13,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + From 4318c3cd818cdfb13274eec82bbab735a8fee310 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:26:00 +0000 Subject: [PATCH 4/5] Improve test to exercise property-based testing and verbose mode Co-authored-by: kurtschelfthout <164917+kurtschelfthout@users.noreply.github.com> --- .../TestOutputHelperLifetimeTests.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs b/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs index afbd6cb5f..08714a655 100644 --- a/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs +++ b/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs @@ -17,9 +17,9 @@ public TestOutputHelperLifetimeTests(ITestOutputHelper testOutputHelper) } [FsCheck.Xunit.Property] - public void Test1() + public void Test1(int x) { - _testOutputHelper.WriteLine($"{nameof(Test1)}"); + _testOutputHelper.WriteLine($"{nameof(Test1)}: {x}"); } [Fact] @@ -29,9 +29,9 @@ public void Test2() } [FsCheck.Xunit.Property] - public void Test3() + public void Test3(string s) { - _testOutputHelper.WriteLine($"{nameof(Test3)}"); + _testOutputHelper.WriteLine($"{nameof(Test3)}: {s ?? "null"}"); } [Fact] @@ -39,5 +39,16 @@ public void Test4() { _testOutputHelper.WriteLine($"{nameof(Test4)}"); } + + /// + /// This test specifically exercises the Every and EveryShrink callbacks by enabling Verbose mode. + /// These callbacks capture the TestOutputHelper in closures, which was the root cause of the lifetime issue. + /// + [FsCheck.Xunit.Property(Verbose = true, MaxTest = 5)] + public bool Test5_VerboseMode(int x, int y) + { + _testOutputHelper.WriteLine($"{nameof(Test5_VerboseMode)}: x={x}, y={y}"); + return true; // Always pass + } } } From 81dad6e22beba82be00df4972702a1c269ceea39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:13:49 +0000 Subject: [PATCH 5/5] Refactor: Create Helpers module and move tests to F# - Created Helpers.fs with centralized safeWriteLine function - Updated PropertyAttribute.fs, CheckExtensions.fs, and Runner.fs to use the helper - Moved TestOutputHelperLifetimeTests from C# to F# in PropertyAttributeTests.fs - Reverted unnecessary C# test project changes Co-authored-by: kurtschelfthout <164917+kurtschelfthout@users.noreply.github.com> --- src/FsCheck.Xunit/CheckExtensions.fs | 26 +++------ src/FsCheck.Xunit/FsCheck.Xunit.fsproj | 1 + src/FsCheck.Xunit/Helpers.fs | 19 +++++++ src/FsCheck.Xunit/PropertyAttribute.fs | 14 +---- src/FsCheck.Xunit/Runner.fs | 18 ++----- .../FsCheck.Test.CSharp.csproj | 13 ----- .../TestOutputHelperLifetimeTests.cs | 54 ------------------- .../Fscheck.XUnit/PropertyAttributeTests.fs | 33 ++++++++++++ 8 files changed, 67 insertions(+), 111 deletions(-) create mode 100644 src/FsCheck.Xunit/Helpers.fs delete mode 100644 tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs diff --git a/src/FsCheck.Xunit/CheckExtensions.fs b/src/FsCheck.Xunit/CheckExtensions.fs index b83f2f75a..20632106e 100644 --- a/src/FsCheck.Xunit/CheckExtensions.fs +++ b/src/FsCheck.Xunit/CheckExtensions.fs @@ -6,39 +6,29 @@ open FsCheck open Xunit.Abstractions module private Helper = - // Helper to safely write to output, handling case where test may have completed - let private safeWriteLine (testOutputHelper: ITestOutputHelper) (message: string) = - try - testOutputHelper.WriteLine(message) - with - | :? InvalidOperationException -> - // Test has completed, TestOutputHelper is no longer active - // Silently ignore as this is expected when runners outlive test lifetime - () - let private runner (testOutputHelper: ITestOutputHelper) = { new IRunner with member __.OnStartFixture t = - Runner.onStartFixtureToString t |> safeWriteLine testOutputHelper + Runner.onStartFixtureToString t |> Helpers.safeWriteLine testOutputHelper member __.OnArguments (ntest,args, every) = - every ntest args |> safeWriteLine testOutputHelper + every ntest args |> Helpers.safeWriteLine testOutputHelper member __.OnShrink(args, everyShrink) = - everyShrink args |> safeWriteLine testOutputHelper + everyShrink args |> Helpers.safeWriteLine testOutputHelper member __.OnFinished(name,testResult) = - Runner.onFinishedToString name testResult |> safeWriteLine testOutputHelper + Runner.onFinishedToString name testResult |> Helpers.safeWriteLine testOutputHelper } let private throwingRunner (testOutputHelper: ITestOutputHelper) = { new IRunner with member __.OnStartFixture t = - safeWriteLine testOutputHelper (Runner.onStartFixtureToString t) + Helpers.safeWriteLine testOutputHelper (Runner.onStartFixtureToString t) member __.OnArguments (ntest,args, every) = - safeWriteLine testOutputHelper (every ntest args) + Helpers.safeWriteLine testOutputHelper (every ntest args) member __.OnShrink(args, everyShrink) = - safeWriteLine testOutputHelper (everyShrink args) + Helpers.safeWriteLine testOutputHelper (everyShrink args) member __.OnFinished(name,testResult) = match testResult with - | TestResult.Passed _ -> safeWriteLine testOutputHelper (Runner.onFinishedToString name testResult) + | TestResult.Passed _ -> Helpers.safeWriteLine testOutputHelper (Runner.onFinishedToString name testResult) | _ -> failwithf "%s" (Runner.onFinishedToString name testResult) } diff --git a/src/FsCheck.Xunit/FsCheck.Xunit.fsproj b/src/FsCheck.Xunit/FsCheck.Xunit.fsproj index 9f41ecf07..d3fe51a75 100644 --- a/src/FsCheck.Xunit/FsCheck.Xunit.fsproj +++ b/src/FsCheck.Xunit/FsCheck.Xunit.fsproj @@ -14,6 +14,7 @@ + diff --git a/src/FsCheck.Xunit/Helpers.fs b/src/FsCheck.Xunit/Helpers.fs new file mode 100644 index 000000000..6bf444dae --- /dev/null +++ b/src/FsCheck.Xunit/Helpers.fs @@ -0,0 +1,19 @@ +namespace FsCheck.Xunit + +open System +open Xunit.Abstractions + +module internal Helpers = + /// + /// Safely writes to a TestOutputHelper, handling cases where the test may have completed + /// and the helper is no longer active. This prevents InvalidOperationException when + /// closures that capture the TestOutputHelper are called after the test lifetime ends. + /// + let safeWriteLine (output: ITestOutputHelper) (message: string) = + try + output.WriteLine(message) + with + | :? InvalidOperationException -> + // Test has completed, TestOutputHelper is no longer active + // Silently ignore as this is expected when closures outlive test lifetime + () diff --git a/src/FsCheck.Xunit/PropertyAttribute.fs b/src/FsCheck.Xunit/PropertyAttribute.fs index 080df1f69..19d141cf4 100644 --- a/src/FsCheck.Xunit/PropertyAttribute.fs +++ b/src/FsCheck.Xunit/PropertyAttribute.fs @@ -80,16 +80,6 @@ module internal PropertyConfig = { Rnd = Rnd (seed,gamma); Size = size } let toConfig (output : TestOutputHelper) propertyConfig = - // Helper to safely write to output, handling case where test may have completed - let safeWriteLine (message: string) = - try - output.WriteLine(message) - with - | :? InvalidOperationException -> - // Test has completed, TestOutputHelper is no longer active - // Silently ignore as this is expected when closures outlive test lifetime - () - Config.Default .WithReplay( propertyConfig.Replay @@ -110,13 +100,13 @@ module internal PropertyConfig = .WithRunner(XunitRunner()) .WithEvery( if propertyConfig.Verbose |> Option.exists id then - fun n args -> safeWriteLine (Config.Verbose.Every n args); "" + fun n args -> Helpers.safeWriteLine output (Config.Verbose.Every n args); "" else Config.Quick.Every ) .WithEveryShrink( if propertyConfig.Verbose |> Option.exists id then - fun args -> safeWriteLine (Config.Verbose.EveryShrink args); "" + fun args -> Helpers.safeWriteLine output (Config.Verbose.EveryShrink args); "" else Config.Quick.EveryShrink ) diff --git a/src/FsCheck.Xunit/Runner.fs b/src/FsCheck.Xunit/Runner.fs index cdc4a842e..1f9c6f503 100644 --- a/src/FsCheck.Xunit/Runner.fs +++ b/src/FsCheck.Xunit/Runner.fs @@ -7,25 +7,15 @@ open System /// to Xunit's given ITestOutputHelper. /// For example, { Config.QuickThrowOnFailure with Runner = TestOutputRunner(output) } type TestOutputRunner(output: Xunit.Abstractions.ITestOutputHelper) = - // Helper to safely write to output, handling case where test may have completed - let safeWriteLine (message: string) = - try - output.WriteLine(message) - with - | :? InvalidOperationException -> - // Test has completed, TestOutputHelper is no longer active - // Silently ignore as this is expected when runner outlives test lifetime - () - interface IRunner with member _.OnStartFixture t = - safeWriteLine (Runner.onStartFixtureToString t) + Helpers.safeWriteLine output (Runner.onStartFixtureToString t) member _.OnArguments (ntest, args, every) = - safeWriteLine (every ntest args) + Helpers.safeWriteLine output (every ntest args) member _.OnShrink(args, everyShrink) = - safeWriteLine (everyShrink args) + Helpers.safeWriteLine output (everyShrink args) member _.OnFinished(name,testResult) = let resultText = Runner.onFinishedToString name testResult match testResult with - | TestResult.Passed _ -> resultText |> safeWriteLine + | TestResult.Passed _ -> resultText |> Helpers.safeWriteLine output | _ -> failwithf "%s" resultText \ No newline at end of file diff --git a/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj b/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj index 1074563b4..1e3bf162d 100644 --- a/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj +++ b/tests/FsCheck.Test.CSharp/FsCheck.Test.CSharp.csproj @@ -6,17 +6,4 @@ false - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - diff --git a/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs b/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs deleted file mode 100644 index 08714a655..000000000 --- a/tests/FsCheck.Test.CSharp/TestOutputHelperLifetimeTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Xunit; -using Xunit.Abstractions; - -namespace FsCheck.Test.CSharp -{ - /// - /// Reproduction test for GitHub issue: Lifetime problem with Xunit: InvalidOperationException: There is no currently active test. - /// This test class verifies that mixing Property and Fact tests with ITestOutputHelper doesn't cause lifetime issues. - /// - public class TestOutputHelperLifetimeTests - { - private readonly ITestOutputHelper _testOutputHelper; - - public TestOutputHelperLifetimeTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - - [FsCheck.Xunit.Property] - public void Test1(int x) - { - _testOutputHelper.WriteLine($"{nameof(Test1)}: {x}"); - } - - [Fact] - public void Test2() - { - _testOutputHelper.WriteLine($"{nameof(Test2)}"); - } - - [FsCheck.Xunit.Property] - public void Test3(string s) - { - _testOutputHelper.WriteLine($"{nameof(Test3)}: {s ?? "null"}"); - } - - [Fact] - public void Test4() - { - _testOutputHelper.WriteLine($"{nameof(Test4)}"); - } - - /// - /// This test specifically exercises the Every and EveryShrink callbacks by enabling Verbose mode. - /// These callbacks capture the TestOutputHelper in closures, which was the root cause of the lifetime issue. - /// - [FsCheck.Xunit.Property(Verbose = true, MaxTest = 5)] - public bool Test5_VerboseMode(int x, int y) - { - _testOutputHelper.WriteLine($"{nameof(Test5_VerboseMode)}: x={x}, y={y}"); - return true; // Always pass - } - } -} diff --git a/tests/FsCheck.Test/Fscheck.XUnit/PropertyAttributeTests.fs b/tests/FsCheck.Test/Fscheck.XUnit/PropertyAttributeTests.fs index ca998d2f0..50dca47d4 100644 --- a/tests/FsCheck.Test/Fscheck.XUnit/PropertyAttributeTests.fs +++ b/tests/FsCheck.Test/Fscheck.XUnit/PropertyAttributeTests.fs @@ -91,3 +91,36 @@ module ``when type implements IAsyncLifetime`` = [] member this.``then InitializeAsync() is invoked``() = executed = true + +/// Reproduction test for GitHub issue: Lifetime problem with Xunit: InvalidOperationException: There is no currently active test. +/// This test class verifies that mixing Property and Fact tests with ITestOutputHelper doesn't cause lifetime issues. +module ``when mixing Property and Fact tests with ITestOutputHelper`` = + open Xunit.Abstractions + + type TestOutputHelperLifetimeTests(output: ITestOutputHelper) = + + [] + member _.``Property test with parameter writes to output`` (x: int) = + output.WriteLine($"Property test with parameter: {x}") + true + + [] + member _.``Fact test writes to output`` () = + output.WriteLine("Fact test") + + [] + member _.``Property test with string parameter writes to output`` (s: string) = + let str = if isNull s then "null" else s + output.WriteLine($"Property test with string: {str}") + true + + [] + member _.``Another fact test writes to output`` () = + output.WriteLine("Another fact test") + + /// This test specifically exercises the Every and EveryShrink callbacks by enabling Verbose mode. + /// These callbacks capture the TestOutputHelper in closures, which was the root cause of the lifetime issue. + [] + member _.``Verbose property test exercises Every and EveryShrink callbacks`` (x: int) (y: int) = + output.WriteLine($"Verbose mode test: x={x}, y={y}") + true