Table of Contents

Hedgehog .NET

Hedgehog will eat all your bugs.

Hedgehog is a modern property-based testing system for .NET, designed to help you release with confidence by automatically finding edge cases you didn't think of.

What is Property-Based Testing?

Instead of writing individual test cases with specific inputs and expected outputs, property-based testing lets you describe properties that should hold true for all inputs:

reverse (reverse xs) = xs, ∀xs :: [α]

This reads as: "the reverse of the reverse of a list equals the original list — for all lists of any type."

In Hedgehog, you express this property and the framework generates hundreds of random test cases automatically:

property {
    let! xs = Gen.list (Range.linear 0 100) Gen.alpha
    return List.rev (List.rev xs) = xs
}
|> Property.render
+++ OK, passed 100 tests.

Why Hedgehog?

Integrated Shrinking

When a property fails, Hedgehog automatically simplifies the failing input to find the smallest counterexample. Unlike older property-based testing libraries that shrink values separately from generation, Hedgehog uses integrated shrinking — shrinking is built into generators, guaranteeing that shrunk values obey the same invariants as the generated values.

This means you get minimal, actionable error reports:

property {
    let! xs = Gen.list (Range.linear 0 100) version
    return xs |> List.rev = xs
}
|> Property.render
*** Failed! Falsifiable (after 3 tests and 6 shrinks):
[0.0.0; 0.0.1]

Even complex types like System.Version shrink automatically to their simplest failing case.

Expressive Syntax

Hedgehog provides gen and property computation expressions that feel natural in F#:

let ipAddressGen = gen {
    let! addr = Gen.array (Range.singleton 4) Gen.byte
    return System.Net.IPAddress addr
}

Precise Control

Range combinators let you control the scope of generated values:

Gen.int32 (Range.constant 0 100)      // Always between 0-100
Gen.int32 (Range.linear 0 100)        // Scales with test size
Gen.list (Range.exponential 1 1000) g // Exponential growth

Core Concepts

Properties are invariants that should hold for all inputs. They're expressed as functions that return bool or Property<bool>.

Generators produce random values of a given type. Hedgehog includes generators for primitives and combinators to build generators for complex types. Generators are composable using map, bind, and other familiar operations.

Shrinking happens automatically when a property fails. Hedgehog finds progressively smaller inputs that still cause the failure, giving you the minimal reproduction case.