2026-05-11 21:43:17 -04:00

1.7 KiB

paths
paths
**/*.fs
**/*.fsx
**/*.fsproj

F# Testing

This file extends common/testing.md with F#-specific content.

Test Framework

  • Prefer xUnit with FsUnit.xUnit for F#-friendly assertions
  • Use Unquote for quotation-based assertions with clear failure messages
  • Use FsCheck.xUnit for property-based testing
  • Use NSubstitute or function stubs for mocking dependencies
  • Use Testcontainers when integration tests need real infrastructure

Test Organization

  • Mirror src/ structure under tests/
  • Separate unit, integration, and end-to-end coverage clearly
  • Name tests by behavior, not implementation details
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 ``PlaceOrder returns error when items are empty`` () =
    let request = { CustomerId = "cust-123"; Items = [] }
    let result = OrderService.placeOrder request
    test <@ Result.isError result @>

Property-Based Testing with FsCheck

open FsCheck.Xunit

[<Property>]
let ``order total is never negative`` (items: OrderItem list) =
    let total = Order.calculateTotal items
    total >= 0m

ASP.NET Core Integration Tests

  • Use WebApplicationFactory<TEntryPoint> for API integration coverage
  • Test auth, validation, and serialization through HTTP, not by bypassing middleware

Coverage

  • Target 80%+ line coverage
  • Focus coverage on domain logic, validation, auth, and failure paths
  • Run dotnet test in CI with coverage collection enabled where available