Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
affaan-m avatar

Fsharp Testing

  • 1.9k installs
  • 234k repo stars
  • Updated July 27, 2026
  • affaan-m/everything-claude-code

fsharp-testing provides F# unit and property-based testing patterns with xUnit, FsUnit, Unquote, and FsCheck.

About

The fsharp-testing skill from everything-claude-code documents comprehensive F# testing patterns using xUnit, FsUnit.xUnit, Unquote quotations, and FsCheck.xUnit property-based tests. It activates when writing new F# tests, reviewing coverage, setting up test infrastructure, or debugging flaky suites. The stack table maps each library to purpose: xUnit as framework, FsUnit for idiomatic assertions, Unquote for quotation-based failure messages, and FsCheck for generative properties. Guidance covers test organization, async testing, mocking boundaries, and modern .NET practices for functional code. Use when users test F# modules, add property tests, or improve assertion clarity in .NET solutions. xUnit, FsUnit, Unquote, and FsCheck.xUnit as the core F# test stack Property-based testing patterns integrated with xUnit runners Activates for new tests, coverage review, infrastructure setup, and flaky test fixes F#-friendly assertion syntax and quotation-based failure messages Modern .NET async and integration testing practices for functional code fsharp-testing provides F# unit and property-based testing patterns with xUnit, FsUnit, Unquote, and FsCheck Organized F# test suites with idi.

  • xUnit, FsUnit, Unquote, and FsCheck.xUnit as the core F# test stack.
  • Property-based testing patterns integrated with xUnit runners.
  • Activates for new tests, coverage review, infrastructure setup, and flaky test fixes.
  • F#-friendly assertion syntax and quotation-based failure messages.
  • Modern .NET async and integration testing practices for functional code.

Fsharp Testing by the numbers

  • 1,942 all-time installs (skills.sh)
  • +274 installs in the week ending Jul 28, 2026 (Skillselion tracking)
  • Ranked #6 of 154 .NET & C# skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Jul 28, 2026 (Skillselion catalog sync)
At a glance

fsharp-testing capabilities & compatibility

Capabilities
unit test patterns · property based tests · assertion libraries · test infrastructure setup · flaky test debugging
Use cases
testing · debugging
npx skills add https://github.com/affaan-m/everything-claude-code --skill fsharp-testing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1.9k
repo stars234k
Security audit3 / 3 scanners passed
Last updatedJuly 27, 2026
Repositoryaffaan-m/everything-claude-code

How do I structure effective F# tests with property-based and quotation-friendly assertions?

Apply F# testing patterns with xUnit, FsUnit, Unquote, and FsCheck for unit, property-based, and integration tests.

Who is it for?

Developers writing or reviewing F# tests in .NET projects.

Skip if: C#-only test suites without F# code under test.

When should I use this skill?

User writes F# tests, mentions FsCheck, Unquote, or F# xUnit setup.

What you get

Organized F# test suites with idiomatic assertions and generative property coverage.

  • Unit test suites
  • Property-based tests
  • Integration test scaffolding

Files

SKILL.mdMarkdownGitHub ↗

F# Testing Patterns

Comprehensive testing patterns for F# applications using xUnit, FsUnit, Unquote, FsCheck, and modern .NET testing practices.

When to Activate

  • Writing new tests for F# code
  • Reviewing test quality and coverage
  • Setting up test infrastructure for F# projects
  • Debugging flaky or slow tests

Test Framework Stack

ToolPurpose
xUnitTest framework (standard .NET ecosystem choice)
FsUnit.xUnitF#-friendly assertion syntax for xUnit
UnquoteAssertion library using F# quotations for clear failure messages
FsCheck.xUnitProperty-based testing integrated with xUnit
NSubstituteMocking .NET dependencies
TestcontainersReal infrastructure in integration tests
WebApplicationFactoryASP.NET Core integration tests

Unit Tests with xUnit + FsUnit

Basic Test Structure

module OrderServiceTests

open Xunit
open FsUnit.Xunit

[<Fact>]
let ``create sets status to Pending`` () =
    let order = Order.create "cust-1" [ validItem ]
    order.Status |> should equal Pending

[<Fact>]
let ``confirm changes status to Confirmed`` () =
    let order = Order.create "cust-1" [ validItem ]
    let confirmed = Order.confirm order
    confirmed.Status |> should be (ofCase <@ Confirmed @>)

Assertions with Unquote

Unquote uses F# quotations so failure messages show the full expression that failed, not just "expected X got Y".

module OrderValidationTests

open Xunit
open Swensen.Unquote

[<Fact>]
let ``PlaceOrder returns success when request is valid`` () =
    let request = { CustomerId = "cust-123"; Items = [ validItem ] }
    let result = OrderService.placeOrder request
    test <@ Result.isOk result @>

[<Fact>]
let ``order total sums item prices`` () =
    let items = [ { Sku = "A"; Quantity = 2; Price = 10m }
                  { Sku = "B"; Quantity = 1; Price = 5m } ]
    let total = Order.calculateTotal items
    test <@ total = 25m @>

[<Fact>]
let ``validated email rejects empty input`` () =
    let result = ValidatedEmail.create ""
    test <@ Result.isError result @>

Async Tests

[<Fact>]
let ``PlaceOrder returns success when request is valid`` () = task {
    let deps = createTestDeps ()
    let request = { CustomerId = "cust-123"; Items = [ validItem ] }

    let! result = OrderService.placeOrder deps request

    test <@ Result.isOk result @>
}

[<Fact>]
let ``PlaceOrder returns error when items are empty`` () = task {
    let deps = createTestDeps ()
    let request = { CustomerId = "cust-123"; Items = [] }

    let! result = OrderService.placeOrder deps request

    test <@ Result.isError result @>
}

Parameterized Tests with Theory

[<Theory>]
[<InlineData("")>]
[<InlineData("   ")>]
let ``PlaceOrder rejects empty customer ID`` (customerId: string) =
    let request = { CustomerId = customerId; Items = [ validItem ] }
    let result = OrderService.placeOrder request
    result |> should be (ofCase <@ Error @>)

[<Theory>]
[<InlineData("", false)>]
[<InlineData("a", false)>]
[<InlineData("user@example.com", true)>]
[<InlineData("user+tag@example.co.uk", true)>]
let ``IsValidEmail returns expected result`` (email: string, expected: bool) =
    test <@ EmailValidator.isValid email = expected @>

Property-Based Testing with FsCheck

Using FsCheck.xUnit

open FsCheck
open FsCheck.Xunit

[<Property>]
let ``order total is always non-negative`` (items: NonEmptyList<PositiveInt * decimal>) =
    let orderItems =
        items.Get
        |> List.map (fun (qty, price) ->
            { Sku = "SKU"; Quantity = qty.Get; Price = abs price })
    let total = Order.calculateTotal orderItems
    total >= 0m

[<Property>]
let ``serialization roundtrips`` (order: Order) =
    let json = JsonSerializer.Serialize order
    let deserialized = JsonSerializer.Deserialize<Order> json
    deserialized = order

Custom Generators

type OrderGenerators =
    static member ValidEmail () =
        gen {
            let! user = Gen.elements [ "alice"; "bob"; "carol" ]
            let! domain = Gen.elements [ "example.com"; "test.org" ]
            return $"{user}@{domain}"
        }
        |> Arb.fromGen

[<Property(Arbitrary = [| typeof<OrderGenerators> |])>]
let ``valid emails pass validation`` (email: string) =
    EmailValidator.isValid email

Mocking Dependencies

Function Stubs (Preferred)

let createTestDeps () =
    let mutable savedOrders = []
    { FindOrder = fun id -> task { return Map.tryFind id testData }
      SaveOrder = fun order -> task { savedOrders <- order :: savedOrders }
      SendNotification = fun _ -> Task.CompletedTask }

[<Fact>]
let ``PlaceOrder saves the confirmed order`` () = task {
    let mutable saved = []
    let deps =
        { createTestDeps () with
            SaveOrder = fun order -> task { saved <- order :: saved } }

    let! _ = OrderService.placeOrder deps validRequest

    test <@ saved.Length = 1 @>
}

NSubstitute for .NET Interfaces

open NSubstitute

[<Fact>]
let ``calls repository with correct ID`` () = task {
    let repo = Substitute.For<IOrderRepository>()
    repo.FindByIdAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>())
        .Returns(Task.FromResult(Some testOrder))

    let service = OrderService(repo)
    let! _ = service.GetOrder(testOrder.Id, CancellationToken.None)

    do! repo.Received(1).FindByIdAsync(testOrder.Id, Arg.Any<CancellationToken>())
}

ASP.NET Core Integration Tests

type OrderApiTests (factory: WebApplicationFactory<Program>) =
    interface IClassFixture<WebApplicationFactory<Program>>

    let client =
        factory.WithWebHostBuilder(fun builder ->
            builder.ConfigureServices(fun services ->
                services.RemoveAll<DbContextOptions<AppDbContext>>() |> ignore
                services.AddDbContext<AppDbContext>(fun options ->
                    options.UseInMemoryDatabase("TestDb") |> ignore) |> ignore))
            .CreateClient()

    [<Fact>]
    member _.``GET order returns 404 when not found`` () = task {
        let! response = client.GetAsync($"/api/orders/{Guid.NewGuid()}")
        test <@ response.StatusCode = HttpStatusCode.NotFound @>
    }

Test Organization

tests/
  MyApp.Tests/
    Unit/
      OrderServiceTests.fs
      PaymentServiceTests.fs
    Integration/
      OrderApiTests.fs
      OrderRepositoryTests.fs
    Properties/
      OrderPropertyTests.fs
    Helpers/
      TestData.fs
      TestDeps.fs

Common Anti-Patterns

Anti-PatternFix
Testing implementation detailsTest behavior and outcomes
Mutable shared test stateFresh state per test
Thread.Sleep in async testsUse Task.Delay with timeout, or polling helpers
Asserting on sprintf outputAssert on typed values and pattern matches
Ignoring CancellationTokenAlways pass and verify cancellation
Skipping property-based testsUse FsCheck for any function with clear invariants

Related Skills

  • dotnet-patterns - Idiomatic .NET patterns, dependency injection, and architecture
  • csharp-testing - C# testing patterns (shared infrastructure like WebApplicationFactory and Testcontainers applies to F# too)

Running Tests

# Run all tests
dotnet test

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"

# Run specific project
dotnet test tests/MyApp.Tests/

# Filter by test name
dotnet test --filter "FullyQualifiedName~OrderService"

# Watch mode during development
dotnet watch test --project tests/MyApp.Tests/

Related skills

Forks & variants (1)

Fsharp Testing has 1 known copy in the catalog totaling 1.3k installs. They canonicalize to this original listing.

How it compares

Pick fsharp-testing for F#-specific xUnit and FsCheck guidance rather than generic JavaScript or Python testing skills.

FAQ

Which frameworks does this skill cover?

xUnit with FsUnit, Unquote, and FsCheck.xUnit for property-based tests.

When should FsCheck be used?

For property-based testing of invariants and generative edge cases in F# modules.

Does this help with flaky tests?

Yes. It activates when debugging flaky or slow F# test suites.

Is Fsharp Testing safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

.NET & C#testing

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.