Skip to content

Commit

Permalink
Add typed aliases around Xunit (#203)
Browse files Browse the repository at this point in the history
* Add typed aliases around Xunit

* Add typed tests

* Add missing line

* Update doc

* Include in fsproj files

* Trying to get it to compile - GitHub please tell me if this worked

* Fix syntax error

* Fix more errors

* Fix contains error

* Fix more errors

* Fix brackets

* Pipeline, please tell me what exception gets thrown

* feat: fantomas format

* Fix all but a couple of equality tests

* Format

* Fix remaining tests

* Push tests that demonstrate inconsistency

* Document bug 207

* And document instance in XUnit typed test

* Lint nits

* fix: actual/expected naming

* Revert tests which demonstrated the fixed bug

* fix: remove outdated comment

Co-authored-by: Sergey Tihon <[email protected]>
  • Loading branch information
Smaug123 and sergey-tihon authored Apr 6, 2022
1 parent 4fe7a5b commit 736b7a1
Show file tree
Hide file tree
Showing 15 changed files with 412 additions and 5 deletions.
4 changes: 2 additions & 2 deletions docs/FsUnitTyped.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ What is FsUnitTyped?
===============
**FsUnitTyped** is a statically typed set of FsUnit operators that makes
unit-testing with `FsUnit` even more safe and enjoyable (Available only for `NUnit`).
unit-testing with `FsUnit` even more safe and enjoyable (Available only for `NUnit` and `Xunit`).
No more untyped constrains and tests like
No more untyped constraints and tests like
1 |> should equal "1"
Expand Down
3 changes: 2 additions & 1 deletion src/FsUnit.Xunit/FsUnit.Xunit.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
</Compile>
<Compile Include="CustomMatchers.fs" />
<Compile Include="FsUnit.fs" />
<Compile Include="FsUnitTyped.fs" />
<None Include="paket.references" />
<None Include="paket.template" />
<None Include="FsUnitSample.fs.pp">
Expand All @@ -22,4 +23,4 @@
<None Include="sample.paket.template" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
</Project>
62 changes: 62 additions & 0 deletions src/FsUnit.Xunit/FsUnitTyped.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace FsUnitTyped

open System.Diagnostics
open Xunit
open FsUnit.Xunit

[<AutoOpen>]
module TopLevelOperators =

/// Asserts that `expected` is equal to `actual`.
/// The equality instance on `actual` is used, if available.
[<DebuggerStepThrough>]
let shouldEqual<'a> (expected: 'a) (actual: 'a) =
actual |> should equal expected

/// Asserts that `expected` is not equal to `actual`.
/// The equality instance on `actual` is used, if available.
[<DebuggerStepThrough>]
let shouldNotEqual<'a> (expected: 'a) (actual: 'a) =
actual |> should not' (equal expected)

[<DebuggerStepThrough>]
let shouldContain<'a when 'a: equality> (expected: 'a) (actual: 'a seq) =
actual |> should contain expected

[<DebuggerStepThrough>]
let shouldBeEmpty<'a>(actual: 'a seq) =
Assert.Empty actual

[<DebuggerStepThrough>]
let shouldNotContain<'a when 'a: equality> (expected: 'a) (actual: 'a seq) =
if Seq.exists ((=) expected) actual then
failwith $"Seq %A{actual} should not contain %A{expected}"

[<DebuggerStepThrough>]
let shouldBeSmallerThan<'a when 'a: comparison> (expected: 'a) (actual: 'a) =
actual |> should be (lessThan expected)

[<DebuggerStepThrough>]
let shouldBeGreaterThan<'a when 'a: comparison> (expected: 'a) (actual: 'a) =
actual |> should be (greaterThan expected)

[<DebuggerStepThrough>]
let shouldFail<'exn when 'exn :> exn>(f: unit -> unit) =
f |> should throw typeof<'exn>

[<DebuggerStepThrough>]
let shouldContainText (expected: string) (actual: string) =
if actual.Contains(expected) |> not then
failwith $"\"{expected}\" is not a substring of \"{actual}\""

[<DebuggerStepThrough>]
let shouldNotContainText (expected: string) (actual: string) =
if actual.Contains(expected) then
failwith $"\"{expected}\" is a substring of \"{actual}\""

[<DebuggerStepThrough>]
let shouldHaveLength<'a> (expected: int) (actual: 'a seq) =
let actual = Seq.length actual

if actual <> expected then
failwith $"Invalid length in %A{actual}\r\nExpected: {expected}\r\nActual: {actual}"
11 changes: 10 additions & 1 deletion tests/FsUnit.Xunit.Test/FsUnit.Xunit.Test.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@
<Compile Include="instanceOfTests.fs" />
<Compile Include="NaNTests.fs" />
<Compile Include="beUniqueTests.fs" />
<Compile Include="typed.beEmptyTests.fs" />
<Compile Include="typed.haveLengthTests.fs" />
<Compile Include="typed.shouldBeGreaterThanTests.fs" />
<Compile Include="typed.shouldBeSmallerThanTests.fs" />
<Compile Include="typed.shouldContainTests.fs" />
<Compile Include="typed.shouldContainText.fs" />
<Compile Include="typed.shouldEqualNullTests.fs" />
<Compile Include="typed.shouldFailTests.fs" />
<Compile Include="typed.shouldEqualTests.fs" />
<None Include="paket.references" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../src/FsUnit.Xunit/FsUnit.Xunit.fsproj" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
</Project>
8 changes: 8 additions & 0 deletions tests/FsUnit.Xunit.Test/equalTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ type ``equal Tests``() =
member __.``reference type should fail to not equal itself``() =
anObj |> should equal anObj

[<Fact>]
member __.``should pass when Equals returns true``() =
anObj |> should equal (box(new AlwaysEqual()))

[<Fact>]
member __.``should fail when Equals returns false``() =
anObj |> should not' (equal(NeverEqual()))
Expand All @@ -69,6 +73,10 @@ type ``equal Tests``() =
member __.``should pass when negated and Equals returns false``() =
anObj |> should not' (equal(NeverEqual()))

[<Fact>]
member __.``should fail when negated and Equals returns true``() =
shouldFail(fun () -> anObj |> should not' (equal(box(AlwaysEqual()))))

[<Fact>]
member __.``should pass when comparing two lists that have the same values``() =
[ 1 ] |> should equal [ 1 ]
Expand Down
2 changes: 1 addition & 1 deletion tests/FsUnit.Xunit.Test/shouldFailTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type ``shouldFail tests``() =
shouldFail(fun () -> shouldFail id)

[<Fact>]
member __.``shouldFaild should throw an exception``() =
member __.``shouldFail should throw an exception``() =
(fun () -> shouldFail id) |> should throw typeof<MatchException>

[<Fact>]
Expand Down
29 changes: 29 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.beEmptyTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace FsUnit.Typed.Test

open Xunit
open FsUnitTyped

type ``shouldBeEmpty tests``() =
[<Fact>]
member __.``empty List should be Empty``() =
[] |> shouldBeEmpty

[<Fact>]
member __.``non-empty List should fail to be Empty``() =
shouldFail(fun () -> [ 1 ] |> shouldBeEmpty)

[<Fact>]
member __.``empty Array should be Empty``() =
[||] |> shouldBeEmpty

[<Fact>]
member __.``non-empty Array should fail to be Empty``() =
shouldFail(fun () -> [| 1 |] |> shouldBeEmpty)

[<Fact>]
member __.``empty Seq should be Empty``() =
Seq.empty |> shouldBeEmpty

[<Fact>]
member __.``non-empty Seq should fail to be Empty``() =
shouldFail(fun () -> seq { 1 } |> shouldBeEmpty)
23 changes: 23 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.haveLengthTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace FsUnit.Typed.Test

open Xunit
open FsUnitTyped

type ``haveLength tests``() =
// F# List
[<Fact>]
member __.``List with 1 item should have Length 1``() =
[ 1 ] |> shouldHaveLength 1

[<Fact>]
member __.``empty List should fail to have Length 1``() =
shouldFail(fun () -> [] |> shouldHaveLength 1)

// Array
[<Fact>]
member __.``Array with 1 item should have Length 1``() =
[| 1 |] |> shouldHaveLength 1

[<Fact>]
member __.``empty Array should fail to have Length 1``() =
shouldFail(fun () -> [||] |> shouldHaveLength 1)
13 changes: 13 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.shouldBeGreaterThanTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace FsUnit.Typed.Test

open Xunit
open FsUnitTyped

type ``shouldBeGreaterThan tests``() =
[<Fact>]
member __.``11 should be greater than 10``() =
11 |> shouldBeGreaterThan 10

[<Fact>]
member __.``11[dot]1 should be greater than 11[dot]0``() =
11.1 |> shouldBeGreaterThan 11.0
24 changes: 24 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.shouldBeSmallerThanTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace FsUnit.Typed.Test

open FsUnit.Xunit
open Xunit
open FsUnitTyped

type ``shouldBeSmallerThan tests``() =
[<Fact>]
member __.``10 should be less than 11``() =
10 |> shouldBeSmallerThan 11

[<Fact>]
member __.``10 should not be less than 10``() =
(fun () -> 10 |> shouldBeSmallerThan 10) |> shouldFail<MatchException>

[<Fact>]
member __.``10[dot]0 should be less than 10[dot]1``() =
10.0 |> shouldBeSmallerThan 10.1

[<Fact>]
member __.``10[dot]0 should not be less than 10[dot]0``() =
(fun () -> 10.0 |> shouldBeSmallerThan 10.0)
|> should throw typeof<MatchException>
//|> shouldFail<MatchException>
53 changes: 53 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.shouldContainTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
namespace FsUnit.Typed.Test

open Xunit
open FsUnitTyped

type ``shouldContain tests``() =
[<Fact>]
member __.``List with item should contain item``() =
[ 1 ] |> shouldContain 1

[<Fact>]
member __.``empty List should fail to contain item``() =
shouldFail(fun () -> [] |> shouldContain 1)

[<Fact>]
member __.``empty List should not contain item``() =
[] |> shouldNotContain 1

[<Fact>]
member __.``List with item should fail to not contain item``() =
shouldFail(fun () -> [ 1 ] |> shouldNotContain 1)

[<Fact>]
member __.``Array with item should contain item``() =
[| 1 |] |> shouldContain 1

[<Fact>]
member __.``empty Array should fail to contain item``() =
shouldFail(fun () -> [||] |> shouldContain 1)

[<Fact>]
member __.``empty Array should not contain item``() =
[||] |> shouldNotContain 1

[<Fact>]
member __.``Array with item should fail to not contain item``() =
shouldFail(fun () -> [| 1 |] |> shouldNotContain 1)

[<Fact>]
member __.``Seq with item should contain item``() =
seq { 1 } |> shouldContain 1

[<Fact>]
member __.``empty Seq should fail to contain item``() =
shouldFail(fun () -> Seq.empty |> shouldContain 1)

[<Fact>]
member __.``empty Seq should not contain item``() =
Seq.empty |> shouldNotContain 1

[<Fact>]
member __.``Seq with item should fail to not contain item``() =
shouldFail(fun () -> seq { 1 } |> shouldNotContain 1)
13 changes: 13 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.shouldContainText.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace FsUnit.Typed.Test

open Xunit
open FsUnitTyped

type ``shouldContainText tests``() =
[<Fact>]
member __.``empty string should contain ""``() =
"" |> shouldContainText ""

[<Fact>]
member __.``ships should contain hip``() =
"ships" |> shouldContainText "hip"
13 changes: 13 additions & 0 deletions tests/FsUnit.Xunit.Test/typed.shouldEqualNullTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace FsUnit.Typed.Test

open Xunit
open FsUnitTyped

type ``Typed: shouldEqual null tests``() =
[<Fact>]
member __.``null should be null``() =
null |> shouldEqual null

[<Fact>]
member __.``null should fail to not be null``() =
shouldFail(fun () -> null |> shouldNotEqual null)
Loading

0 comments on commit 736b7a1

Please sign in to comment.