thomhurst / TUnit

A modern, fast and flexible .NET testing framework
MIT License
1.02k stars 8 forks source link

F# support #573

Open KeterSCP opened 6 hours ago

KeterSCP commented 6 hours ago

Project description states that this is a

.NET testing framework

But .NET != C# Are there any plans to support F# projects?

thomhurst commented 6 hours ago

Hey @KeterSCP . In all honesty I've never used F# but if it all compiles down to the same IL code, is there any reason this doesnt work with F#?

Thats a genuine question. If changes or tweaks need to be made please let me know.

A reproduction of any issues would be helpful, and if you want to help solve any challenges I'm open to that as like I said I'm not too versed in F#

KeterSCP commented 6 hours ago

Hi @thomhurst! Thanks for the quick reply (and also nice job with this project!)

So here are the problems I encountered while trying minimal example in F# (it doesn't even assert anything, just returns 0):

module Tests

open TUnit.Core

[<Test>]
let ``My test`` () = 0
  1. The test is not visible in the Tests tab in Rider (Testing platform support is enabled)
  2. After running dotnet test from the CLI, build fails:
dotnet test
Restore complete (0.2s)
You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
  TestProject2 succeeded (1.3s) → bin\Debug\net8.0\TestProject2.dll
  TestProject2 test failed with 1 error(s) (0.2s)
    ...\TestProject2\bin\Debug\net8.0\TestProject2.dll : error run failed: Tests failed: '...\TestProject2\bin\Debug\net8.0\TestResults\TestProject2_net8.0_x64.log' [net8.0|x64]

Test summary: total: 0, failed: 0, succeeded: 0, skipped: 0, duration: 0.2s
Build failed with 1 error(s) in 2.0s

Log file contains following output:

████████╗██╗   ██╗███╗   ██╗██╗████████╗
╚══██╔══╝██║   ██║████╗  ██║██║╚══██╔══╝
   ██║   ██║   ██║██╔██╗ ██║██║   ██║   
   ██║   ██║   ██║██║╚██╗██║██║   ██║   
   ██║   ╚██████╔╝██║ ╚████║██║   ██║   
   ╚═╝    ╚═════╝ ╚═╝  ╚═══╝╚═╝   ╚═╝   

   v0.1.783.0 | 64-bit | Microsoft Windows 10.0.22631 | win-x64 | .NET 8.0.8 | Microsoft Testing Platform v1.4.0

Test run summary: Zero tests ran - ...\TestProject2\bin\Debug\net8.0\TestProject2.dll (net8.0|x64)
  total: 0
  failed: 0
  succeeded: 0
  skipped: 0
  duration: 59ms

=== COMMAND LINE ===
C:\Program Files\dotnet\dotnet.exe exec ...\TestProject2\bin\Debug\net8.0\TestProject2.dll --internal-msbuild-node testingplatform.pipe.467200f8a0ac44d1a3488e611ee746e0 
thomhurst commented 4 hours ago

Hmmm... Could you create a new repo with minimal repo please? Should help debug issues. I'll take a look but also might need your help if that's okay!

KeterSCP commented 4 hours ago

Sure thing! Here is a separate repo, which demonstrates working example with XUnit and non-working example with TUnit:

https://github.com/KeterSCP/tunit-fsharp-repo

bevanweiss commented 1 hour ago

My understanding is that TUnit relies on C# code generation. That won't work for a F# project, because the F# project will not compile the C# generated code... it will just be random files in the F# project.

What 'should' work however, is having a dedicated C# project just for the tests that references the F# project with the logic to be tested.

I don't think that F# has support for source generation in the same way that C# has, so I don't think it's an option at this stage. It does look like the F# source generator issue has been raised https://github.com/fsharp/fslang-suggestions/issues/864, but nothing advanced on it.

thomhurst commented 1 hour ago

My understanding is that TUnit relies on C# code generation. That won't work for a F# project, because the F# project will not compile the C# generated code... it will just be random files in the F# project.

What 'should' work however, is having a dedicated C# project just for the tests that references the F# project with the logic to be tested.

I don't think that F# has support for source generation in the same way that C# has, so I don't think it's an option at this stage. It does look like the F# source generator issue has been raised fsharp/fslang-suggestions#864, but nothing advanced on it.

Ah interesting. Does this essentially mean it's not a TUnit bug? I just (maybe naively) assumed that the nugrt packages I published would work for any .net language because it all compiles down to the same thing. If not I just need to see if I can tweak the source generator depending on theangjage

bevanweiss commented 1 hour ago

Ah interesting. Does this essentially mean it's not a TUnit bug? I just (maybe naively) assumed that the nugrt packages I published would work for any .net language because it all compiles down to the same thing. If not I just need to see if I can tweak the source generator depending on theangjage

You potentially know more in this space than me ;) My understanding was, the 'Core' stuff that you (@thomhurst) write in fixed C# is indeed compiled down on your side to .NET IL (unless you opt for AoT etc etc) during the nuget publishing, and is purely runnable under the .NET CLR, so is agnostic to C#/F#/VB.NET usage. However... for the source generated aspects, the parts which are spat out C# language code files, these need to be compiled at the 'end-users' side. If they have an F# / VB.NET project environment, they might not even have the Roslyn C# compiler AT ALL... I also think that the C# source generators are only enabled in C# projects, since they kind of inject themselves into the compilation process. Although they don't have to restrict themselves to .cs files (they can access other files also... but their output is stuffed into the C# compilation chain).

So I'd say it's not a TUnit 'bug' at all. It's just one of the limitations of using the (C#) Source Generator concept. There's potentially some ways to get around it, maybe having an MSBuild Task which separately launches the csc compiler against some boilerplate core code that then allows for the source generator to kick in and parse the F# files, to generate the final C# source which the csc invocation then builds... but it would also need to somehow link this csc result back into the F# project... so I reckon the 'bang for buck' on maintaining such a monstrosity wouldn't be there...

In an F# project, there is no C# compiler invocation, so I don't believe your source generator is even called.

https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview