From d882e1badf1085113b5d52c8031de81e971d7ca2 Mon Sep 17 00:00:00 2001 From: XperiAndri Date: Tue, 20 Oct 2026 17:09:39 +0200 Subject: [PATCH 1/3] test: assertions that unwrap options, value options and results Extend the `Assert` class of MSTest with members for the F# option, value option and result types, so that a test unwraps a value in one expression instead of matching on it and failing by hand: * `WantSome`, `WantValueSome`, `WantOk` and `WantError` return the unwrapped value or fail the test with the message of the caller; the two result assertions add the error or the value to it. * `IsSome`, `IsNone`, `IsValueSome`, `IsValueNone`, `IsOk` and `IsError` check the case and discard the value. * `IsDefaultOf`, `OkEquals` and `ErrorEquals` compare a value with the default of its type or with the content of a result. MSTest takes the message of a failure as a text that is not null, while an optional message that the caller omitted is null, so the assertions that fail pass an empty text then. `AssertExtensionsTests` checks that each member passes on the expected case and fails with its message on the other one; a test category names the area. Co-Authored-By: Claude Sonnet 5.5 --- .../Assert.fs | 136 +++++++++++++++ .../AssertExtensionsTests.fs | 156 ++++++++++++++++++ .../FSharp.Collections.Immutable.Tests.fsproj | 2 + .../TestCategories.fs | 6 + 4 files changed, 300 insertions(+) create mode 100644 tests/FSharp.Collections.Immutable.Tests/Assert.fs create mode 100644 tests/FSharp.Collections.Immutable.Tests/AssertExtensionsTests.fs diff --git a/tests/FSharp.Collections.Immutable.Tests/Assert.fs b/tests/FSharp.Collections.Immutable.Tests/Assert.fs new file mode 100644 index 00000000..00f1a271 --- /dev/null +++ b/tests/FSharp.Collections.Immutable.Tests/Assert.fs @@ -0,0 +1,136 @@ +namespace FSharp.Collections.Immutable.Tests + +open System.Runtime.InteropServices +open Microsoft.VisualStudio.TestTools.UnitTesting + +/// +/// Assertions on F# , +/// and +/// values as extensions of . +/// +/// The assertions whose names start with Want return the unwrapped value or fail the test; their Is +/// twins discard the value. +/// +/// +[] +module AssertExtensions = + + // MSTest takes the message of a failure as a text that is not null, while an optional message that the caller + // omitted is null. + let private messageOrEmpty (message : string | null) : string = + match message with + | null -> "" + | message -> message + + type Assert with + + /// + /// Returns the value of ; fails the test with + /// on . + /// + static member WantSome (value, [] message : string | null) = + match value with + | Some some -> some + | None -> + Assert.Fail (messageOrEmpty message) + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsSome (value, [] message : string | null) = Assert.WantSome (value, message) |> ignore + + /// + /// Fails the test with unless is + /// . + /// + static member IsNone (value, [] message : string | null) = + match value with + | Some _ -> Assert.Fail (messageOrEmpty message) + | None -> () + + /// + /// Returns the value of ; fails the test + /// with on . + /// + static member WantValueSome (value, [] message : string | null) = + match value with + | ValueSome some -> some + | ValueNone -> + Assert.Fail (messageOrEmpty message) + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsValueSome (value, [] message : string | null) = Assert.WantValueSome (value, message) |> ignore + + /// + /// Fails the test with unless is + /// . + /// + static member IsValueNone (value, [] message : string | null) = + match value with + | ValueSome _ -> Assert.Fail (messageOrEmpty message) + | ValueNone -> () + + /// + /// Returns the value of ; fails the test with + /// and the error on . + /// + static member WantOk (value, [] message : string | null) = + match value with + | Ok ok -> ok + | Error error -> + match message with + | null -> Assert.Fail (string error) + | message -> Assert.Fail ($"'{message}': {error}") + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsOk (value, [] message : string | null) = Assert.WantOk (value, message) |> ignore + + /// + /// Returns the error of ; fails the test with + /// and the value on . + /// + static member WantError (value, [] message : string | null) = + match value with + | Error error -> error + | Ok value -> + match message with + | null -> Assert.Fail (string value) + | message -> Assert.Fail ($"'{message}': {value}") + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsError (value, [] message : string | null) = Assert.WantError (value, message) |> ignore + + /// + /// Fails the test with unless is the default value of its + /// type. + /// + static member inline IsDefaultOf< ^T> (value : ^T, [] message : string) = + Assert.AreEqual (box value, box Unchecked.defaultof< ^T>, message) + + /// + /// Fails the test with unless is + /// holding . + /// + static member inline OkEquals< ^R, 'E> (expected : ^R, actual : Result< ^R, 'E >, [] message : string | null) = + Assert.AreEqual (box expected, box (Assert.WantOk (actual, message)), message) + + /// + /// Fails the test with unless is + /// holding . + /// + static member inline ErrorEquals<'R, ^E> (expected : ^E, actual : Result<'R, ^E>, [] message : string | null) = + Assert.AreEqual (box expected, box (Assert.WantError (actual, message)), message) diff --git a/tests/FSharp.Collections.Immutable.Tests/AssertExtensionsTests.fs b/tests/FSharp.Collections.Immutable.Tests/AssertExtensionsTests.fs new file mode 100644 index 00000000..571324da --- /dev/null +++ b/tests/FSharp.Collections.Immutable.Tests/AssertExtensionsTests.fs @@ -0,0 +1,156 @@ +namespace FSharp.Collections.Immutable.Tests + +open System +open Microsoft.VisualStudio.TestTools.UnitTesting + +/// +/// The assertions on options, value options and results that extend +/// . +/// +[] +type AssertExtensionsTests () = + + /// The message of the failure that an assertion raises. + static let failureOf (assertion : unit -> unit) : string = + let failure = Assert.Throws(Action assertion, "The assertion must fail") + failure.Message + + static let assertContains (failure : string) (expected : string) (message : string) = + StringAssert.Contains (failure, expected, StringComparison.Ordinal, message) + + // The empty option and value option of a known type: a type annotation cannot sit in a tuple of arguments. + static let noInt : int option = None + static let noValueInt : int voption = ValueNone + + // ---- option ---- + + [] + member _.``WantSome returns the value of Some`` () = + Assert.AreEqual(5, Assert.WantSome (Some 5, "message"), "WantSome must return the value of Some") + + [] + member _.``WantSome fails with the message on None`` () = + let failure = failureOf (fun () -> Assert.WantSome (noInt, "the value is missing") |> ignore) + assertContains failure "the value is missing" "WantSome must fail with its message on None" + + [] + member _.``IsSome passes for Some and fails for None`` () = + Assert.IsSome (Some 5, "message") + let failure = failureOf (fun () -> Assert.IsSome (noInt, "the value is missing")) + assertContains failure "the value is missing" "IsSome must fail with its message on None" + + [] + member _.``IsNone passes for None and fails for Some`` () = + Assert.IsNone (noInt, "message") + let failure = failureOf (fun () -> Assert.IsNone (Some 5, "the value is there")) + assertContains failure "the value is there" "IsNone must fail with its message on Some" + + // ---- voption ---- + + [] + member _.``WantValueSome returns the value of ValueSome`` () = + Assert.AreEqual(5, Assert.WantValueSome (ValueSome 5, "message"), "WantValueSome must return the value") + + [] + member _.``WantValueSome fails with the message on ValueNone`` () = + let failure = + failureOf (fun () -> + Assert.WantValueSome (noValueInt, "the value is missing") + |> ignore + ) + + assertContains failure "the value is missing" "WantValueSome must fail with its message on ValueNone" + + [] + member _.``IsValueSome passes for ValueSome and fails for ValueNone`` () = + Assert.IsValueSome (ValueSome 5, "message") + let failure = failureOf (fun () -> Assert.IsValueSome (noValueInt, "the value is missing")) + assertContains failure "the value is missing" "IsValueSome must fail with its message on ValueNone" + + [] + member _.``IsValueNone passes for ValueNone and fails for ValueSome`` () = + Assert.IsValueNone (noValueInt, "message") + let failure = failureOf (fun () -> Assert.IsValueNone (ValueSome 5, "the value is there")) + assertContains failure "the value is there" "IsValueNone must fail with its message on ValueSome" + + // ---- result ---- + + [] + member _.``WantOk returns the value of Ok`` () = + let result : Result = Ok 5 + Assert.AreEqual(5, Assert.WantOk (result, "message"), "WantOk must return the value of Ok") + + [] + member _.``WantOk fails with the message and the error on Error`` () = + let result : Result = Error "the error" + let failure = failureOf (fun () -> Assert.WantOk (result, "the call must succeed") |> ignore) + assertContains failure "the call must succeed" "WantOk must fail with its message on Error" + assertContains failure "the error" "WantOk must fail with the error" + + [] + member _.``WantOk fails with the error alone when it has no message`` () = + let result : Result = Error "the error" + let failure = failureOf (fun () -> Assert.WantOk (result) |> ignore) + assertContains failure "the error" "WantOk must fail with the error" + + [] + member _.``IsOk passes for Ok and fails for Error`` () = + let ok : Result = Ok 5 + let error : Result = Error "the error" + Assert.IsOk (ok, "message") + let failure = failureOf (fun () -> Assert.IsOk (error, "the call must succeed")) + assertContains failure "the call must succeed" "IsOk must fail with its message on Error" + + [] + member _.``WantError returns the error of Error`` () = + let result : Result = Error "the error" + Assert.AreEqual("the error", Assert.WantError (result, "message"), "WantError must return the error") + + [] + member _.``WantError fails with the message and the value on Ok`` () = + let result : Result = Ok 5 + let failure = failureOf (fun () -> Assert.WantError (result, "the call must fail") |> ignore) + assertContains failure "the call must fail" "WantError must fail with its message on Ok" + assertContains failure "5" "WantError must fail with the value" + + [] + member _.``IsError passes for Error and fails for Ok`` () = + let ok : Result = Ok 5 + let error : Result = Error "the error" + Assert.IsError (error, "message") + let failure = failureOf (fun () -> Assert.IsError (ok, "the call must fail")) + assertContains failure "the call must fail" "IsError must fail with its message on Ok" + + [] + member _.``OkEquals passes for the expected value and fails for another value or for Error`` () = + let ok : Result = Ok 5 + Assert.OkEquals (5, ok, "message") + let other : Result = Ok 6 + let different = failureOf (fun () -> Assert.OkEquals (5, other, "the value must be 5")) + assertContains different "the value must be 5" "OkEquals must fail with its message on another value" + let error : Result = Error "the error" + let failure = failureOf (fun () -> Assert.OkEquals (5, error, "the call must succeed")) + assertContains failure "the error" "OkEquals must fail with the error on Error" + + [] + member _.``ErrorEquals passes for the expected error and fails for another error or for Ok`` () = + let error : Result = Error "the error" + Assert.ErrorEquals ("the error", error, "message") + let other : Result = Error "another error" + let different = + failureOf (fun () -> Assert.ErrorEquals ("the error", other, "the error must be the expected one")) + assertContains different "the error must be the expected one" "ErrorEquals must fail with its message on another error" + let ok : Result = Ok 5 + let failure = failureOf (fun () -> Assert.ErrorEquals ("the error", ok, "the call must fail")) + assertContains failure "5" "ErrorEquals must fail with the value on Ok" + + // ---- default values ---- + + [] + member _.``IsDefaultOf passes for the default value and fails for another one`` () = + Assert.IsDefaultOf (0, "message") + Assert.IsDefaultOf (noInt, "message") + let number = failureOf (fun () -> Assert.IsDefaultOf (1, "the number must be the default")) + assertContains number "the number must be the default" "IsDefaultOf must fail with its message on a non-default number" + let option = failureOf (fun () -> Assert.IsDefaultOf (Some 1, "the option must be the default")) + assertContains option "the option must be the default" "IsDefaultOf must fail with its message on a non-default option" diff --git a/tests/FSharp.Collections.Immutable.Tests/FSharp.Collections.Immutable.Tests.fsproj b/tests/FSharp.Collections.Immutable.Tests/FSharp.Collections.Immutable.Tests.fsproj index 42889292..ff9cc792 100644 --- a/tests/FSharp.Collections.Immutable.Tests/FSharp.Collections.Immutable.Tests.fsproj +++ b/tests/FSharp.Collections.Immutable.Tests/FSharp.Collections.Immutable.Tests.fsproj @@ -30,7 +30,9 @@ + + diff --git a/tests/FSharp.Collections.Immutable.Tests/TestCategories.fs b/tests/FSharp.Collections.Immutable.Tests/TestCategories.fs index 49796ff7..6c2bbb9e 100644 --- a/tests/FSharp.Collections.Immutable.Tests/TestCategories.fs +++ b/tests/FSharp.Collections.Immutable.Tests/TestCategories.fs @@ -8,6 +8,12 @@ open Microsoft.VisualStudio.TestTools.UnitTesting // The attributes go on the test classes only, for the collection and the area that a class examines; test methods carry // no categories (ADR 0001, D8). +/// The assertions that extend `Assert` (`Assert.fs`). +type AssertExtensionsTestCategoryAttribute () = + inherit TestCategoryBaseAttribute () + static let categories : IList = [| "Assert extensions" |] + override _.TestCategories = categories + /// The builder functions and the builder modules. type BuilderTestCategoryAttribute () = inherit TestCategoryBaseAttribute () From 1eb42a3dc542238a7ccdd9158313e74d69052e40 Mon Sep 17 00:00:00 2001 From: XperiAndri Date: Tue, 20 Oct 2026 17:48:05 +0200 Subject: [PATCH 2/3] fixup! test: assertions that unwrap options, value options and results Declare `AssertExtensions` as the root module of `Assert.fs`, as the other files of the tests and the library that hold one module do. Co-Authored-By: Claude Sonnet 5.5 --- .../Assert.fs | 250 +++++++++--------- 1 file changed, 124 insertions(+), 126 deletions(-) diff --git a/tests/FSharp.Collections.Immutable.Tests/Assert.fs b/tests/FSharp.Collections.Immutable.Tests/Assert.fs index 00f1a271..17b27fe3 100644 --- a/tests/FSharp.Collections.Immutable.Tests/Assert.fs +++ b/tests/FSharp.Collections.Immutable.Tests/Assert.fs @@ -1,8 +1,3 @@ -namespace FSharp.Collections.Immutable.Tests - -open System.Runtime.InteropServices -open Microsoft.VisualStudio.TestTools.UnitTesting - /// /// Assertions on F# , /// and @@ -13,124 +8,127 @@ open Microsoft.VisualStudio.TestTools.UnitTesting /// /// [] -module AssertExtensions = - - // MSTest takes the message of a failure as a text that is not null, while an optional message that the caller - // omitted is null. - let private messageOrEmpty (message : string | null) : string = - match message with - | null -> "" - | message -> message - - type Assert with - - /// - /// Returns the value of ; fails the test with - /// on . - /// - static member WantSome (value, [] message : string | null) = - match value with - | Some some -> some - | None -> - Assert.Fail (messageOrEmpty message) - Unchecked.defaultof<_> - - /// - /// Fails the test with unless is - /// . - /// - static member IsSome (value, [] message : string | null) = Assert.WantSome (value, message) |> ignore - - /// - /// Fails the test with unless is - /// . - /// - static member IsNone (value, [] message : string | null) = - match value with - | Some _ -> Assert.Fail (messageOrEmpty message) - | None -> () - - /// - /// Returns the value of ; fails the test - /// with on . - /// - static member WantValueSome (value, [] message : string | null) = - match value with - | ValueSome some -> some - | ValueNone -> - Assert.Fail (messageOrEmpty message) - Unchecked.defaultof<_> - - /// - /// Fails the test with unless is - /// . - /// - static member IsValueSome (value, [] message : string | null) = Assert.WantValueSome (value, message) |> ignore - - /// - /// Fails the test with unless is - /// . - /// - static member IsValueNone (value, [] message : string | null) = - match value with - | ValueSome _ -> Assert.Fail (messageOrEmpty message) - | ValueNone -> () - - /// - /// Returns the value of ; fails the test with - /// and the error on . - /// - static member WantOk (value, [] message : string | null) = - match value with - | Ok ok -> ok - | Error error -> - match message with - | null -> Assert.Fail (string error) - | message -> Assert.Fail ($"'{message}': {error}") - Unchecked.defaultof<_> - - /// - /// Fails the test with unless is - /// . - /// - static member IsOk (value, [] message : string | null) = Assert.WantOk (value, message) |> ignore - - /// - /// Returns the error of ; fails the test with - /// and the value on . - /// - static member WantError (value, [] message : string | null) = - match value with - | Error error -> error - | Ok value -> - match message with - | null -> Assert.Fail (string value) - | message -> Assert.Fail ($"'{message}': {value}") - Unchecked.defaultof<_> - - /// - /// Fails the test with unless is - /// . - /// - static member IsError (value, [] message : string | null) = Assert.WantError (value, message) |> ignore - - /// - /// Fails the test with unless is the default value of its - /// type. - /// - static member inline IsDefaultOf< ^T> (value : ^T, [] message : string) = - Assert.AreEqual (box value, box Unchecked.defaultof< ^T>, message) - - /// - /// Fails the test with unless is - /// holding . - /// - static member inline OkEquals< ^R, 'E> (expected : ^R, actual : Result< ^R, 'E >, [] message : string | null) = - Assert.AreEqual (box expected, box (Assert.WantOk (actual, message)), message) - - /// - /// Fails the test with unless is - /// holding . - /// - static member inline ErrorEquals<'R, ^E> (expected : ^E, actual : Result<'R, ^E>, [] message : string | null) = - Assert.AreEqual (box expected, box (Assert.WantError (actual, message)), message) +module FSharp.Collections.Immutable.Tests.AssertExtensions + +open System.Runtime.InteropServices +open Microsoft.VisualStudio.TestTools.UnitTesting + +// MSTest takes the message of a failure as a text that is not null, while an optional message that the caller +// omitted is null. +let private messageOrEmpty (message : string | null) : string = + match message with + | null -> "" + | message -> message + +type Assert with + + /// + /// Returns the value of ; fails the test with + /// on . + /// + static member WantSome (value, [] message : string | null) = + match value with + | Some some -> some + | None -> + Assert.Fail (messageOrEmpty message) + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsSome (value, [] message : string | null) = Assert.WantSome (value, message) |> ignore + + /// + /// Fails the test with unless is + /// . + /// + static member IsNone (value, [] message : string | null) = + match value with + | Some _ -> Assert.Fail (messageOrEmpty message) + | None -> () + + /// + /// Returns the value of ; fails the test + /// with on . + /// + static member WantValueSome (value, [] message : string | null) = + match value with + | ValueSome some -> some + | ValueNone -> + Assert.Fail (messageOrEmpty message) + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsValueSome (value, [] message : string | null) = Assert.WantValueSome (value, message) |> ignore + + /// + /// Fails the test with unless is + /// . + /// + static member IsValueNone (value, [] message : string | null) = + match value with + | ValueSome _ -> Assert.Fail (messageOrEmpty message) + | ValueNone -> () + + /// + /// Returns the value of ; fails the test with + /// and the error on . + /// + static member WantOk (value, [] message : string | null) = + match value with + | Ok ok -> ok + | Error error -> + match message with + | null -> Assert.Fail (string error) + | message -> Assert.Fail ($"'{message}': {error}") + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsOk (value, [] message : string | null) = Assert.WantOk (value, message) |> ignore + + /// + /// Returns the error of ; fails the test with + /// and the value on . + /// + static member WantError (value, [] message : string | null) = + match value with + | Error error -> error + | Ok value -> + match message with + | null -> Assert.Fail (string value) + | message -> Assert.Fail ($"'{message}': {value}") + Unchecked.defaultof<_> + + /// + /// Fails the test with unless is + /// . + /// + static member IsError (value, [] message : string | null) = Assert.WantError (value, message) |> ignore + + /// + /// Fails the test with unless is the default value of its + /// type. + /// + static member inline IsDefaultOf< ^T> (value : ^T, [] message : string) = + Assert.AreEqual (box value, box Unchecked.defaultof< ^T>, message) + + /// + /// Fails the test with unless is + /// holding . + /// + static member inline OkEquals< ^R, 'E> (expected : ^R, actual : Result< ^R, 'E >, [] message : string | null) = + Assert.AreEqual (box expected, box (Assert.WantOk (actual, message)), message) + + /// + /// Fails the test with unless is + /// holding . + /// + static member inline ErrorEquals<'R, ^E> (expected : ^E, actual : Result<'R, ^E>, [] message : string | null) = + Assert.AreEqual (box expected, box (Assert.WantError (actual, message)), message) From dbdcd68bdecddf895f2251006206b82c05ef7918 Mon Sep 17 00:00:00 2001 From: XperiAndri Date: Tue, 20 Oct 2026 17:48:06 +0200 Subject: [PATCH 3/3] test: unwrap options in the existing tests with the assertions of `AssertExtensions` The tests that took the value out of an option or a value option by hand, or checked its case by hand, use the assertions of `AssertExtensions` now: * The expected elements of `replace` and `replaceWith` of `FlatList` and `FlatListBuilder` come from `Assert.WantValueSome` where they came from `ValueOption.get`, so test data without a value to replace fails the test with a message. * `FlatListOracles.messageDetail` fails the test, where it threw `InvalidOperationException`, when the action does not throw. * `tryTail` of the sequence-like access contract and of the `Option` namespace tests asserts the case and takes the tail in one expression with `Assert.IsValueNone`, `Assert.WantValueSome` and `Assert.WantSome`. Co-Authored-By: Claude Sonnet 5.5 --- .../SeqLike/SeqLikeAccessContract.fs | 15 +++++-------- .../FlatList/FlatListBuilderTests.fs | 12 ++++++---- .../FlatList/FlatListOptionTests.fs | 22 ++++++++++--------- .../FlatList/FlatListOracles.fs | 12 +++++----- .../FlatList/FlatListTests.fs | 12 ++++++---- 5 files changed, 40 insertions(+), 33 deletions(-) diff --git a/tests/FSharp.Collections.Immutable.Tests/Contracts/SeqLike/SeqLikeAccessContract.fs b/tests/FSharp.Collections.Immutable.Tests/Contracts/SeqLike/SeqLikeAccessContract.fs index 8fee7d72..8f9ba026 100644 --- a/tests/FSharp.Collections.Immutable.Tests/Contracts/SeqLike/SeqLikeAccessContract.fs +++ b/tests/FSharp.Collections.Immutable.Tests/Contracts/SeqLike/SeqLikeAccessContract.fs @@ -150,18 +150,15 @@ type SeqLikeAccessContract<'C> (ops : SeqOps<'C>) = let struct (collection, elements) = this.Create input let tail = ops.TryTail collection - Assert.AreEqual( - not (Array.isEmpty elements), - tail.IsSome, - $"%s{ops.Name}.tryTail must return a tail exactly for a collection with elements" - ) + if Array.isEmpty elements then + Assert.IsValueNone (tail, $"%s{ops.Name}.tryTail must return nothing for an empty collection") + else + let tail = + Assert.WantValueSome (tail, $"%s{ops.Name}.tryTail must return a tail for a collection with elements") - // CollectionAssert compares the elements of the tail and reports the first one that differs - match tail with - | ValueSome tail -> + // CollectionAssert compares the elements of the tail and reports the first one that differs CollectionAssert.AreEqual ( Array.tail elements, ops.ToArray tail, $"%s{ops.Name}.tryTail must return the elements after the first one" ) - | ValueNone -> () diff --git a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListBuilderTests.fs b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListBuilderTests.fs index b9e80eb2..5a1f07bc 100644 --- a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListBuilderTests.fs +++ b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListBuilderTests.fs @@ -599,8 +599,10 @@ type FlatListBuilderTests () = FlatListBuilder.replace oldValue 99 builder |> ignore CollectionAssert.AreEqual ( - FlatListOracles.replaceFirst (=) oldValue 99 input - |> ValueOption.get, + Assert.WantValueSome ( + FlatListOracles.replaceFirst (=) oldValue 99 input, + "The test data must contain the value to replace" + ), Seq.toArray builder, "FlatListBuilder.replace must replace the first equal element" ) @@ -626,8 +628,10 @@ type FlatListBuilderTests () = |> ignore CollectionAssert.AreEqual ( - FlatListOracles.replaceFirst FlatListOracles.equalIgnoringCase oldValue "X" names - |> ValueOption.get, + Assert.WantValueSome ( + FlatListOracles.replaceFirst FlatListOracles.equalIgnoringCase oldValue "X" names, + "The test data must contain a string that the comparer finds equal" + ), Seq.toArray builder, "FlatListBuilder.replaceWith must replace the first element that the comparer finds equal" ) diff --git a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOptionTests.fs b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOptionTests.fs index 17554b8b..dfb1a9cb 100644 --- a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOptionTests.fs +++ b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOptionTests.fs @@ -67,19 +67,21 @@ type FlatListOptionTests () = [] member _.``tryTail returns an option`` () = - let expected = FSharp.Collections.Immutable.FlatList.tryTail array + let expected = + Assert.WantValueSome ( + FSharp.Collections.Immutable.FlatList.tryTail array, + "FlatList.tryTail must return a tail for a flat list with elements" + ) + let found : FlatList option = FlatList.tryTail array - Assert.AreEqual(expected.IsSome, found.IsSome, "Option.FlatList.tryTail must return a tail when the default does") + let tail = Assert.WantSome (found, "Option.FlatList.tryTail must return a tail when the default does") // The tails are compared element by element - match expected, found with - | ValueSome expected, Some found -> - CollectionAssert.AreEqual ( - FlatList.toArray expected, - FlatList.toArray found, - "Option.FlatList.tryTail must return the tail of the default" - ) - | _ -> () + CollectionAssert.AreEqual ( + FlatList.toArray expected, + FlatList.toArray tail, + "Option.FlatList.tryTail must return the tail of the default" + ) [] member _.``pick takes a chooser of options`` () = diff --git a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOracles.fs b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOracles.fs index e55f5207..4ce92320 100644 --- a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOracles.fs +++ b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListOracles.fs @@ -4,6 +4,7 @@ module FSharp.Collections.Immutable.Tests.FlatListOracles open System open System.Collections.Generic +open Microsoft.VisualStudio.TestTools.UnitTesting open FSharp.Collections.Immutable /// A flat list of strings as a sequence of objects. A flat list of strings is also a sequence of objects, by the @@ -59,12 +60,11 @@ let messageDetail (action : unit -> unit) = with ex -> ValueSome ex - match thrown with - | ValueSome ex -> - match ex.Message.IndexOf '\n' with - | -1 -> "" - | newline -> ex.Message.Substring (newline + 1) - | ValueNone -> invalidOp "The action must throw" + let ex = Assert.WantValueSome (thrown, "The action must throw") + + match ex.Message.IndexOf '\n' with + | -1 -> "" + | newline -> ex.Message.Substring (newline + 1) /// The index of the first element of a range that the equality finds equal to the value, or -1: the oracle of the /// searches from the front. diff --git a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListTests.fs b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListTests.fs index 560bd80e..1114f0dc 100644 --- a/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListTests.fs +++ b/tests/FSharp.Collections.Immutable.Tests/FlatList/FlatListTests.fs @@ -1089,8 +1089,10 @@ type FlatListTests () = [] member _.``replace replaces the first equal element`` (input : int array, oldValue : int) = CollectionAssert.AreEqual ( - FlatListOracles.replaceFirst (=) oldValue 99 input - |> ValueOption.get, + Assert.WantValueSome ( + FlatListOracles.replaceFirst (=) oldValue 99 input, + "The test data must contain the value to replace" + ), FlatList.toArray (FlatList.replace oldValue 99 (FlatList.ofArray input)), "FlatList.replace must replace the first equal element" ) @@ -1130,8 +1132,10 @@ type FlatListTests () = let names = FlatListOracles.names () CollectionAssert.AreEqual ( - FlatListOracles.replaceFirst FlatListOracles.equalIgnoringCase oldValue "X" names - |> ValueOption.get, + Assert.WantValueSome ( + FlatListOracles.replaceFirst FlatListOracles.equalIgnoringCase oldValue "X" names, + "The test data must contain a string that the comparer finds equal" + ), FlatList.toArray (FlatList.replaceWith StringComparer.OrdinalIgnoreCase oldValue "X" (FlatList.ofArray names)), "FlatList.replaceWith must replace the first element that the comparer finds equal" )