So, first and foremost, welcome to F#! At a practical level, any of the four tools you listed will “get the job done”. There are some differences… but they mostly boil down to: workflow and politics.
In terms of workflow, xUnit/NUnit/MSTest are all libraries which try to hook into the testing infrastructure provided by various IDEs (Visual Studio, Rider, et cetera) and by the
dotnet command-line interface. Meanwhile, Expecto prefers a simple, stand-alone console for hosting/running tests. The net difference between the two approaches is: with Expecto you will interact with test execution by directly modifying the test suite. Conversely, with the others, test execution is largely driven by interacting with a particular IDE (or the
In terms of politics, xUnit has largely emerged as the de facto standard for the larger .NET community. However, many organizations rely on their existing investment in MSTest or NUnit (which is the oldest of the four libraries). Additionally, as you might’ve guessed from the previous paragraph, xUnit/NUnit/MSTest all try to be “good citizens” within the context of the larger (admittedly very Microsoft-centric) .NET ecosystem. Expecto, however, has always been about “doing its own thing”. Further, the creator of Expecto is very… zealous in his views, and this sometimes leads to questionable decisions around community interactions and OSS project maintenance.
So, in the end, I’d say choose whichever one best matches: the way you like to work, and your priorities around “F# as part of .NET” versus “F# as outside of .NET” (both are valid points-of-view, by the way).