diff --git a/FsUnit.sln b/FsUnit.sln index 16c0cf10..7b0beab0 100644 --- a/FsUnit.sln +++ b/FsUnit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsUnit.NUnit", "src\FsUnit.NUnit\FsUnit.NUnit.fsproj", "{3890DC0F-5225-4ADF-9B9E-F6A482046A9E}" EndProject @@ -32,6 +32,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{0BEF7A55-F158-4691-886C-1AF2FE12DD7C}" ProjectSection(SolutionItems) = preProject docs\content\FsCheck.fsx = docs\content\FsCheck.fsx + docs\content\FsUnitTyped.fsx = docs\content\FsUnitTyped.fsx docs\content\index.fsx = docs\content\index.fsx docs\content\MbUnit.fsx = docs\content\MbUnit.fsx docs\content\MsTest.fsx = docs\content\MsTest.fsx diff --git a/docs/content/FsUnitTyped.fsx b/docs/content/FsUnitTyped.fsx new file mode 100644 index 00000000..ad286227 --- /dev/null +++ b/docs/content/FsUnitTyped.fsx @@ -0,0 +1,102 @@ +(*** hide ***) +// This block of code is omitted in the generated HTML documentation. Use +// it to define helpers that you do not want to show in the documentation. +#I "../../bin/FsUnit.NUnit/" +#r "NUnit.Framework.dll" +#r "FsUnit.NUnit.dll" + +(** +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`). + +No more untyped constrains and tests like + + 1 |> should equal "1" + +FsUnitTyped from NuGet +----------------------- + +The `FsUnit.Typed` is part of `FsUnit` package for NUnit and can be [installed from NuGet](https://nuget.org/packages/FsUnit). + +FsUnitTyped with Paket +----------------------- + +`FsUnitTyped` supports lightweight usage scenario with [Paket](http://fsprojects.github.io/Paket/). + +In the case when you do not want to add dependency on [FsUnit](https://www.nuget.org/packages/FsUnit/) +package to your project, you can add reference to [FsUnitTyped.fs](https://github.com/fsprojects/FsUnit/blob/master/src/FsUnit.NUnit/FsUnit.Typed.fs) +file and [NUnit](https://www.nuget.org/packages/NUnit/) package. + +Example of `paket.dependencies` file: + + [lang=paket] + source https://nuget.org/api/v2 + + nuget FSharp.Core + github fsprojects/FsUnit src/FsUnit.NUnit/FsUnitTyped.fs + + group Test + source https://nuget.org/api/v2 + nuget NUnit.Console + nuget NUnit + +Example of `paket.reference` file for test projects: + + [lang=paket] + File:FsUnitTyped.fs + group Test + NUnit + +Syntax +------- + +With FsUnitTyped, you can write unit tests like this: +*) + +open NUnit.Framework +open FsUnitTyped + +(** +One object equals or does not equal another: +*) + +1 |> shouldEqual 1 +1 |> shouldNotEqual 2 + +(** +One comparable value greater or smaller than another: +*) + +11 |> shouldBeGreaterThan 10 +10 |> shouldBeSmallerThan 11 + + +(** +A string contains specified substring: +*) +"ships" |> shouldContainText "hip" + +(** +A List, Seq, or Array instance contains, does not contain a value or empty: +*) +[1] |> shouldContain 1 +[] |> shouldNotContain 1 +[] |> shouldBeEmpty + +(** +A List or Array instance has a certain length: +*) +[|1;2;3;4|] |> shouldHaveLength 4 + +(** +A function should throw a certain type of exception: +*) +(fun _ -> failwith "BOOM!") |> shouldFail + +(** +A function should fail +*) +shouldFail (fun _ -> 5/0 |> ignore) diff --git a/docs/tools/templates/template.cshtml b/docs/tools/templates/template.cshtml index 46db257c..c618e1cf 100644 --- a/docs/tools/templates/template.cshtml +++ b/docs/tools/templates/template.cshtml @@ -47,14 +47,13 @@
  • Release Notes
  • -
  • NUnit
  • +
  • NUnit Classic
  • +
  • Lightweight FsUnit with Paket
  • +
  • FsUnitTyped
  • +
  • xUnit
  • -
  • MbUnit
  • MsTest
  • -
  • -
  • Paket
  • -
  • FsCheck
  • - +
  • MbUnit
  • Operators
  • diff --git a/src/FsUnit.NUnit/FsUnit.NUnit.fsproj b/src/FsUnit.NUnit/FsUnit.NUnit.fsproj index 90a67592..2176f931 100644 --- a/src/FsUnit.NUnit/FsUnit.NUnit.fsproj +++ b/src/FsUnit.NUnit/FsUnit.NUnit.fsproj @@ -54,6 +54,7 @@ + CustomMatchers.fs diff --git a/src/FsUnit.NUnit/FsUnitTyped.fs b/src/FsUnit.NUnit/FsUnitTyped.fs new file mode 100644 index 00000000..8d59e9d8 --- /dev/null +++ b/src/FsUnit.NUnit/FsUnitTyped.fs @@ -0,0 +1,62 @@ +namespace FsUnitTyped + +open System.Diagnostics +open NUnit.Framework +open System.Collections.Generic + +[] +module TopLevelOperators = + [] + let shouldEqual (expected : 'a) (actual : 'a) = + Assert.IsTrue((expected = actual), sprintf "Expected: %A\nActual: %A" expected actual) + + [] + let shouldNotEqual (expected : 'a) (actual : 'a) = + Assert.IsFalse((expected = actual), sprintf "Expected: %A\nActual: %A" expected actual) + + [] + let shouldContain (x : 'a) (y : 'a seq) = + let list = List<_>() + for a in y do + list.Add a + Assert.Contains(x, list) + + [] + let shouldBeEmpty (list : 'a seq) = + Assert.IsEmpty(list) + + [] + let shouldNotContain (x : 'a) (y : 'a seq) = + if Seq.exists ((=) x) y then failwithf "Seq %A should not contain %A" y x + + [] + let shouldBeSmallerThan (x : 'a) (y : 'a) = + Assert.GreaterOrEqual(x, y, sprintf "Expected: %A\nActual: %A" x y) + + [] + let shouldBeGreaterThan (x : 'a) (y : 'a) = + Assert.Greater(y, x, sprintf "Expected: %A\nActual: %A" x y) + + [] + let shouldFail<'exn when 'exn :> exn> (f : unit -> unit) = + let succeeded = ref false + try + f() + succeeded := true + with + | exn -> + if exn :? 'exn then () else + failwithf "Exception was not of type %s" <| typeof<'exn>.ToString() + if !succeeded then + failwith "Operation did not fail." + + [] + let shouldContainText (x : string) (y : string) = + if y.Contains(x) |> not then + failwithf "\"%s\" is not a substring of \"%s\"" x y + + [] + let shouldHaveLength expected list = + let actual = Seq.length list + if actual <> expected then + failwithf "Invalid length in %A\r\nExpected: %i\r\nActual: %i" list expected actual \ No newline at end of file diff --git a/tests/FsUnit.NUnit.Test/FsUnit.NUnit.Test.fsproj b/tests/FsUnit.NUnit.Test/FsUnit.NUnit.Test.fsproj index 03eacba3..3c051193 100644 --- a/tests/FsUnit.NUnit.Test/FsUnit.NUnit.Test.fsproj +++ b/tests/FsUnit.NUnit.Test/FsUnit.NUnit.Test.fsproj @@ -79,6 +79,15 @@ + + + + + + + + + diff --git a/tests/FsUnit.NUnit.Test/typed.beEmptyTests.fs b/tests/FsUnit.NUnit.Test/typed.beEmptyTests.fs new file mode 100644 index 00000000..5fcf7f50 --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.beEmptyTests.fs @@ -0,0 +1,29 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``shouldBeEmpty tests`` ()= + [] member test. + ``empty List should be Empty`` ()= + [] |> shouldBeEmpty + + [] member test. + ``non-empty List should fail to be Empty`` ()= + shouldFail (fun () -> [1] |> shouldBeEmpty) + + [] member test. + ``empty Array should be Empty`` ()= + [||] |> shouldBeEmpty + + [] member test. + ``non-empty Array should fail to be Empty`` ()= + shouldFail (fun () -> [|1|] |> shouldBeEmpty) + + [] member test. + ``empty Seq should be Empty`` ()= + Seq.empty |> shouldBeEmpty + + [] member test. + ``non-empty Seq should fail to be Empty`` ()= + shouldFail (fun () -> seq { yield 1 } |> shouldBeEmpty) \ No newline at end of file diff --git a/tests/FsUnit.NUnit.Test/typed.haveLengthTests.fs b/tests/FsUnit.NUnit.Test/typed.haveLengthTests.fs new file mode 100644 index 00000000..b4d6a415 --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.haveLengthTests.fs @@ -0,0 +1,23 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``haveLength tests`` ()= + // F# List + [] member test. + ``List with 1 item should have Length 1`` ()= + [1] |> shouldHaveLength 1 + + [] member test. + ``empty List should fail to have Length 1`` ()= + shouldFail (fun () -> [] |> shouldHaveLength 1) + + // Array + [] member test. + ``Array with 1 item should have Length 1`` ()= + [|1|] |> shouldHaveLength 1 + + [] member test. + ``empty Array should fail to have Length 1`` ()= + shouldFail (fun () -> [||] |> shouldHaveLength 1) \ No newline at end of file diff --git a/tests/FsUnit.NUnit.Test/typed.shouldBeGreaterThanTests.fs b/tests/FsUnit.NUnit.Test/typed.shouldBeGreaterThanTests.fs new file mode 100644 index 00000000..8b8d6187 --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldBeGreaterThanTests.fs @@ -0,0 +1,13 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``shouldBeGreaterThan tests`` ()= + [] member test. + ``11 should be greater than 10`` ()= + 11 |> shouldBeGreaterThan 10 + + [] member test. + ``11.1 should be greater than 11.0`` ()= + 11.1 |> shouldBeGreaterThan 11.0 \ No newline at end of file diff --git a/tests/FsUnit.NUnit.Test/typed.shouldBeSmallerThanTests.fs b/tests/FsUnit.NUnit.Test/typed.shouldBeSmallerThanTests.fs new file mode 100644 index 00000000..77717d99 --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldBeSmallerThanTests.fs @@ -0,0 +1,13 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``shouldBeSmallerThan tests`` ()= + [] member test. + ``10 should be less than 11`` ()= + 10 |> shouldBeSmallerThan 11 + + [] member test. + ``10.0 should be less than 10.1`` ()= + 10.0 |> shouldBeSmallerThan 10.1 diff --git a/tests/FsUnit.NUnit.Test/typed.shouldContainTests.fs b/tests/FsUnit.NUnit.Test/typed.shouldContainTests.fs new file mode 100644 index 00000000..37b8baa9 --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldContainTests.fs @@ -0,0 +1,53 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``shouldContain tests`` ()= + [] member test. + ``List with item should contain item`` ()= + [1] |> shouldContain 1 + + [] member test. + ``empty List should fail to contain item`` ()= + shouldFail (fun () -> [] |> shouldContain 1) + + [] member test. + ``empty List should not contain item`` ()= + [] |> shouldNotContain 1 + + [] member test. + ``List with item should fail to not contain item`` ()= + shouldFail (fun () -> [1] |> shouldNotContain 1) + + [] member test. + ``Array with item should contain item`` ()= + [|1|] |> shouldContain 1 + + [] member test. + ``empty Array should fail to contain item`` ()= + shouldFail (fun () -> [||] |> shouldContain 1) + + [] member test. + ``empty Array should not contain item`` ()= + [||] |> shouldNotContain 1 + + [] member test. + ``Array with item should fail to not contain item`` ()= + shouldFail (fun () -> [|1|] |> shouldNotContain 1) + + [] member test. + ``Seq with item should contain item`` ()= + seq { yield 1 } |> shouldContain 1 + + [] member test. + ``empty Seq should fail to contain item`` ()= + shouldFail (fun () -> Seq.empty |> shouldContain 1) + + [] member test. + ``empty Seq should not contain item`` ()= + Seq.empty |> shouldNotContain 1 + + [] member test. + ``Seq with item should fail to not contain item`` ()= + shouldFail (fun () -> seq { yield 1 } |> shouldNotContain 1) \ No newline at end of file diff --git a/tests/FsUnit.NUnit.Test/typed.shouldContainText.fs b/tests/FsUnit.NUnit.Test/typed.shouldContainText.fs new file mode 100644 index 00000000..99b22d2c --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldContainText.fs @@ -0,0 +1,14 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``shouldContainText tests`` ()= + [] member test. + ``empty string should contain ""`` ()= + "" |> shouldContainText "" + + [] member test. + ``ships should contain hip`` ()= + "ships" |> shouldContainText "hip" + diff --git a/tests/FsUnit.NUnit.Test/typed.shouldEqualNullTests.fs b/tests/FsUnit.NUnit.Test/typed.shouldEqualNullTests.fs new file mode 100644 index 00000000..4c3a8981 --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldEqualNullTests.fs @@ -0,0 +1,13 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``Typed: shouldEqual null tests`` ()= + [] member test. + ``null should be null`` ()= + null |> shouldEqual null + + [] member test. + ``null should fail to not be null`` ()= + shouldFail (fun () -> null |> shouldNotEqual null) diff --git a/tests/FsUnit.NUnit.Test/typed.shouldEqualTests.fs b/tests/FsUnit.NUnit.Test/typed.shouldEqualTests.fs new file mode 100644 index 00000000..09d8018b --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldEqualTests.fs @@ -0,0 +1,75 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +type AlwaysEqual() = + override this.Equals(other) = true + override this.GetHashCode() = 1 + + +type NeverEqual() = + override this.Equals(other) = false + override this.GetHashCode() = 1 + + +[] +type ``shouldEqual Tests`` ()= + let anObj = new obj() + let otherObj = new obj() + + [] member test. + ``value type should equal equivalent value`` ()= + 1 |> shouldEqual 1 + + [] member test. + ``value type should fail to equal nonequivalent value`` ()= + shouldFail (fun () -> 1 |> shouldEqual 2) + + [] member test. + ``value type should not equal nonequivalent value`` ()= + 1 |> shouldNotEqual 2 + + [] member test. + ``value type should fail to not equal equivalent value`` ()= + shouldFail (fun () -> 1 |> shouldNotEqual 1) + + [] member test. + ``reference type should equal itself`` ()= + anObj |> shouldEqual anObj + + [] member test. + ``reference type should fail to equal other`` ()= + shouldFail (fun () -> anObj |> shouldEqual otherObj) + + [] member test. + ``reference type should not equal other`` ()= + anObj |> shouldNotEqual otherObj + + [] member test. + ``reference type should fail to not equal itself`` ()= + shouldFail (fun () -> anObj |> shouldNotEqual anObj) + + [] member test. + ``should pass when Equals returns true`` ()= + anObj |> shouldEqual (box(new AlwaysEqual())) + + [] member test. + ``should fail when Equals returns false`` ()= + shouldFail (fun () -> anObj |> shouldEqual (box(new NeverEqual()))) + + [] member test. + ``should pass when negated and Equals returns false`` ()= + anObj |> shouldNotEqual (box(new NeverEqual())) + + [] member test. + ``should fail when negated and Equals returns true`` ()= + shouldFail (fun () -> anObj |>shouldNotEqual (box(new AlwaysEqual()))) + + [] member test. + ``None should equal None`` ()= + None |> shouldEqual None + + [] member this. + ``structural equality`` () = + let actualList: char list = [] in + [(actualList, "")] |> shouldEqual [([], "")] diff --git a/tests/FsUnit.NUnit.Test/typed.shouldFailTests.fs b/tests/FsUnit.NUnit.Test/typed.shouldFailTests.fs new file mode 100644 index 00000000..43542a2d --- /dev/null +++ b/tests/FsUnit.NUnit.Test/typed.shouldFailTests.fs @@ -0,0 +1,21 @@ +namespace FsUnit.Typed.Test +open NUnit.Framework +open FsUnitTyped + +[] +type ``shouldFail tests`` ()= + [] member test. + ``empty List should fail to contain item`` ()= + shouldFail (fun () -> [] |> shouldContain 1) + + [] member test. + ``non-null should fail to be Null`` ()= + shouldFail (fun () -> "something" |> shouldEqual null) + + [] member test. + ``shouldFail should fail when everything is OK`` ()= + shouldFail (fun () -> shouldFail id) + + [] member test. + ``Simplify "should throw"``() = + (fun () -> failwith "BOOM!") |> shouldFail \ No newline at end of file