Cookbook Examples
This page is a concentrated set of “show me the shape” examples.
If you want the most persuasive examples first, jump to Power Showcase.
Basics
Direct Equality Assertion
<@ List.length [1; 2; 3] @> =? 3
Assertion With A Reusable Expectation
let positiveSmall =
AssertExpectation.greaterThan 0
<&> AssertExpectation.lessThan 10
<@ 5 @> |>? positiveSmall
Domain Modeling
type Person = { Name: string; Age: int }
## Compare Domain Objects By One Field
<@ { Name = "Tony"; Age = 48 } @>
|>? AssertExpectation.equalBy (fun person -> person.Age) { Name = "Anthony"; Age = 48 }
Compare To One Projected Key
<@ "Testify" @>
|>? AssertExpectation.equalByKey String.length 7
Compare With A Custom Relation
<@ { Name = "Tony"; Age = 48 } @>
|>? AssertExpectation.equalWith (fun a b -> a.Age = b.Age) { Name = "Anthony"; Age = 48 }
Property Power
Simple Property Check Against A Reference
<@ List.rev >> List.rev @> |=> id
Property Check With A Custom Arbitrary
let pairArb =
Arbitraries.tuple2
(Arbitraries.from<int>)
(Arbitraries.from<int>)
Check.should(
CheckExpectation.equalToReference,
(fun (a, b) -> a + b),
<@ fun (a, b) -> a + b @>,
arbitrary = pairArb)
Custom Generator Then Arbitrary
let fixedLengthLists =
Generators.listOfLength 5 (Generators.from<int>)
|> Arbitraries.fromGen
Check.should(
CheckExpectation.equalToReference,
List.length,
<@ List.length @>,
arbitrary = fixedLengthLists)
Advanced Dependent Property
Check.shouldBy(
(fun verify ->
FsCheck.Prop.forAll Arbitraries.from<int> (fun n ->
let length = abs n
let arb = Arbitraries.fromGen (FsCheck.Gen.listOfLength length FsCheck.Arb.generate<int>)
FsCheck.Prop.forAll arb (fun xs ->
verify (length, xs)))),
CheckExpectation.isTrue,
(fun _ -> true),
<@ fun (expectedLength, xs) -> List.length xs = expectedLength @>)
Inspect A Property Failure Without Throwing
let result =
Check.result(
CheckExpectation.equalToReference,
(fun x -> x + 1),
<@ fun x -> x + 2 @>)
match result with
| Passed -> printfn "ok"
| _ -> printfn "%s" (Check.toDisplayString result)
Replay A Failing Property Run
match result with
| Failed failure ->
match failure.TryGetReplayConfig() with
| Some replayConfig ->
let replayed =
Check.result(
CheckExpectation.equalToReference,
(fun x -> x + 1),
<@ fun x -> x + 2 @>,
config = replayConfig)
printfn "%s" (Check.toDisplayString replayed)
| None ->
()
| _ ->
()
Hints And Global Configuration
Turn On Built-In Hint Packs
Testify.configure (
TestifyConfig.defaults
|> TestifyConfig.withHintPacks BuiltInHintPacks.beginner
)
Add A Custom Hint Rule
let trailingSpaceHint =
TestifyHintRule.onFieldRegexPattern
"Course.TrailingSpace"
HintTextField.ActualValue
@"\s+$"
(fun _ -> "The actual value appears to end with trailing whitespace.")
let customHints =
TestifyHintPack.create "course" [ trailingSpaceHint ]
Testify.configure (
TestifyConfig.defaults
|> TestifyConfig.withHintPacks (BuiltInHintPacks.beginner @ [ customHints ])
)
Integrations
Expecto
open Expecto
open Testify.Expecto
[<Tests>]
let tests =
TestifyExpecto.testList "demo" [
TestifyExpecto.testCase "projection equality" (fun () ->
<@ { Name = "Tony"; Age = 48 } @>
|>? AssertExpectation.equalBy (fun person -> person.Age) { Name = "Anthony"; Age = 48 })
]
Multiple items
module List from Microsoft.FSharp.Collections
--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T with get member IsEmpty: bool with get member Item: index: int -> 'T with get ...
module List from Microsoft.FSharp.Collections
--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T with get member IsEmpty: bool with get member Item: index: int -> 'T with get ...
val length: list: 'T list -> int
val positiveSmall: obj
type Person =
{
Name: string
Age: int
}
Multiple items
val string: value: 'T -> string
--------------------
type string = System.String
val string: value: 'T -> string
--------------------
type string = System.String
Multiple items
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
module String
from Microsoft.FSharp.Core
val length: str: string -> int
val rev: list: 'T list -> 'T list
val id: x: 'T -> 'T
val pairArb: 'a
val fixedLengthLists: 'a
val abs: value: 'T -> 'T (requires member Abs)
val result: 'a
val Passed: 'a
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
val failure: 'a
union case Option.Some: Value: 'T -> Option<'T>
val replayConfig: 'a
val replayed: 'a
union case Option.None: Option<'T>
val trailingSpaceHint: 'a
val customHints: 'a
val tests: 'a
testify