diff --git a/Expecto.FsCheck/FsCheck.fs b/Expecto.FsCheck/FsCheck.fs index 3758cd20..f0f29823 100644 --- a/Expecto.FsCheck/FsCheck.fs +++ b/Expecto.FsCheck/FsCheck.fs @@ -42,7 +42,9 @@ module ExpectoFsCheck = | xs -> sprintf "%s\n" (String.concat "\n" xs) match testResult with - | TestResult.True (_testData,_b) -> () + | TestResult.True (data, suppressOutput) -> + if not suppressOutput && config.logger.IsSome then + config.logger.Value.log Logging.LogLevel.Info (Logging.Message.eventX $"Passed {numTests data.NumberOfTests}.\n{stampsToString data.Stamps}") |> Async.RunSynchronously | TestResult.False (_,_,_, Outcome.Exception (:? IgnoreException as e),_) -> raise e @@ -89,14 +91,14 @@ module ExpectoFsCheck = let test (config: FsCheckConfig) = let config = { MaxTest = config.maxTest - MaxFail = 1000 + MaxFail = config.maxRejected // We're converting uint64s to a smaller type, but it shouldn't be an issue because users are only using the // values given in the test output, which are only ints when running FsCheck 2 Replay = Option.map Random.StdGen (config.replay |> Option.map (fun (seed, gamma) -> int seed, int gamma)) Name = name StartSize = config.startSize EndSize = config.endSize - QuietOnSuccess = true + QuietOnSuccess = config.quietOnSuccess Every = fun _ _ -> String.Empty EveryShrink = fun _ -> String.Empty Arbitrary = config.arbitrary diff --git a/Expecto.FsCheck3/FsCheck3.fs b/Expecto.FsCheck3/FsCheck3.fs index 55c8e4c4..2a8969d0 100644 --- a/Expecto.FsCheck3/FsCheck3.fs +++ b/Expecto.FsCheck3/FsCheck3.fs @@ -42,7 +42,9 @@ module ExpectoFsCheck = | xs -> sprintf "%s\n" (String.concat "\n" xs) match testResult with - | TestResult.Passed (_testData,_b) -> () + | TestResult.Passed (data, suppressOutput) -> + if not suppressOutput && config.logger.IsSome then + config.logger.Value.log Logging.LogLevel.Info (Logging.Message.eventX $"Passed {numTests data.NumberOfTests}.\n{stampsToString data.Stamps}") |> Async.RunSynchronously | TestResult.Failed (_,_,_, Outcome.Failed (:? IgnoreException as e),_,_,_) -> raise e @@ -95,9 +97,10 @@ module ExpectoFsCheck = .WithName(name) .WithStartSize(config.startSize) .WithEndSize(config.endSize) - .WithQuietOnSuccess(true) + .WithQuietOnSuccess(config.quietOnSuccess) .WithArbitrary(config.arbitrary) .WithRunner(runner config) + .WithMaxRejected(config.maxRejected) Check.One(config, property) diff --git a/Expecto/Model.fs b/Expecto/Model.fs index aeb3c7dd..6e866ea7 100644 --- a/Expecto/Model.fs +++ b/Expecto/Model.fs @@ -9,8 +9,8 @@ type SourceLocation = static member empty = { sourcePath = ""; lineNumber = 0 } type FsCheckConfig = - /// The maximum number of tests that are run. - { maxTest: int + { /// The maximum number of tests that are run. + maxTest: int /// The size to use for the first test. startSize: int /// The size to use for the last test, when all the tests are passing. The size increases linearly between Start- and EndSize. @@ -36,6 +36,12 @@ type FsCheckConfig = finishedTest: FsCheckConfig -> (* test name *) string -> Async + /// If set, suppresses the output from the test if the test is successful. + quietOnSuccess: bool + /// The maximum number of tests where values are rejected, e.g. as the result of ==> + maxRejected: int + /// If set, this logger is used to show test information for passing tests. + logger: Logging.Logger option } static member defaultConfig = @@ -47,6 +53,9 @@ type FsCheckConfig = receivedArgs = fun _ _ _ _ -> async.Return () successfulShrink = fun _ _ _ -> async.Return () finishedTest = fun _ _ -> async.Return () + quietOnSuccess = true + maxRejected = 1000 + logger = None } /// Actual test function; either an async one, or a synchronous one. diff --git a/README.md b/README.md index f1b33efd..b8ac8053 100644 --- a/README.md +++ b/README.md @@ -718,14 +718,14 @@ like the following. ```fsharp type FsCheckConfig = - /// The maximum number of tests that are run. - { maxTest: int + { /// The maximum number of tests that are run. + maxTest: int /// The size to use for the first test. startSize: int /// The size to use for the last test, when all the tests are passing. The size increases linearly between Start- and EndSize. endSize: int /// If set, the seed to use to start testing. Allows reproduction of previous runs. - replay: (uint64 * uint64) option + replay: (uint64 * uint64 * int) option /// The Arbitrary instances on this class will be merged in back to front order, i.e. instances for the same generated type at the front /// of the list will override those at the back. The instances on Arb.Default are always known, and are at the back (so they can always be /// overridden) @@ -745,6 +745,10 @@ type FsCheckConfig = finishedTest: FsCheckConfig -> (* test name *) string -> Async + /// If set, suppresses the output from the test if the test is successful. + quietOnSuccess: bool + /// The maximum number of tests where values are rejected, e.g. as the result of ==> + maxRejected: int } ``` diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 61192c29..60156d41 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,6 @@ +### 11.0.0-alpha4 - 2024-12-16 +* Allow quietOnSuccess and maxRejected fscheck config + ### 11.0.0-alpha3 - 2024-10-13 * Add testParamAsync and testParamTask (#512), thanks @1eyewonder