Skip to content

The F# compiler takes a long time to compile each instance of xUnit's Assert.Equal #18807

@mkb137

Description

@mkb137

The F# compiler takes a long time to compile xUnit assertions, e.g. Assert.Equal<int>(1,2), especially if untyped e.g. Assert.Equal(1,2)

To reproduce the problem:

  1. Create an empty project.

  2. Build the project.

  3. Note the compile time, e.g.

  FSharpInferredTypeCompileTimes succeeded (0.9s)
  1. Add a unit test file contaning 100 lines of random Assert.Equals, e.g.
    [<Fact>]
    member this.``Test Assert.Equal with no type parameter``() =
        Assert.Equal(42, generateRandomInt 1 100)
        Assert.Equal("hello", generateRandomString 10)
        Assert.Equal(3.14, generateRandomFloat 0.0 10.0)
        // 97 more lines
  1. Build the project.
  2. Note the compile time. On this machine, the compiler is adding 100ms for each Assert.Equal.
  FSharpInferredTypeCompileTimes succeeded (12.5s)
  1. Add another 100 lines of Assert.Equals, so there are 200 total.
  2. Build the project.
  3. Note the compile time. The compiler continues to add about 100ms for each additional Assert.Equal.
  FSharpInferredTypeCompileTimes succeeded (22.9s)
  1. Return to 100 lines of Assert.Equal and add strong typing to all the Assert.Equal calls, e.g.
    [<Fact>]
    member this.``Test Assert.Equal with strong typing``() =
        Assert.Equal<int>(42, generateRandomInt 1 100)
        Assert.Equal<string>("hello", generateRandomString 10)
        Assert.Equal<float>(3.14, generateRandomFloat 0.0 10.0)
        // 97 more lines
  1. Build the project.
  2. Note the compile time, and that it is much faster.
  FSharpInferredTypeCompileTimes succeeded (3.6s)
  1. Add a wrapper function for Assert.Equal like so:
    let assertEqual (x: 'T, y: 'T) =
        Assert.Equal<'T>(x, y)
  1. Modify all uses of Assert.Equal to call the wrapper function, e.g.
    [<Fact>]
    member this.``Test Assert.Equal with functional override``() =
        assertEqual(42, generateRandomInt 1 100)
        assertEqual("hello", generateRandomString 10)
        assertEqual(3.14, generateRandomFloat 0.0 10.0)
  1. Build the project.
  2. Note the compile time and that our single Assert.Equal has added 100ms and that each call to the wrapper has added no significant compile time.
  FSharpInferredTypeCompileTimes succeeded (1.0s)

I have only observed this problem with xUnit's Assertions. The problem exists with xUnit and xUnit.v3.

Expected behavior

Bulding an F# project containing xUnit Assert.Equals should be fast and should not take any longer than if called with a wrapper function.

Actual behavior

Compiling an F# project containing xUnit tests using Assert.Equals takes significantly longer than one with typed Assert.Equals or with a wrapper function, adding significant build time for each call to Assert.Equal.

Known workarounds

Add wrapper functions for xUnit assertions.

Related information

  • Operating system
    Windows 11, Mac OS 15.5
  • .NET Runtime kind (.NET Core, .NET Framework, Mono)
    .NET 9.0.200
  • Editing Tools (e.g. Visual Studio Version, Visual Studio)

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions