Goal is to be able to have a suite of tests for a library target both dotnet and js runtimes via Expecto.
Motivation for me: For new libraries, using the setup similar to this repo with the Fable.Plugins.NUnit.dll has worked well. However, I now want to make some other libraries available via Fable which already have a full suite of Expecto tests and would rather avoid porting everything to xunit just so they can be used with the Fable.Plugins.NUnit (tho maybe that's the easiest?)
I know this has been discussed before, but I was wondering if there were any new thoughts in this area, esp wrt suggested implementation approach.
The two main approaches I've seen discussed:
1) Create something like Fable.Plugins.NUnit for Expecto that translates the AST into a JS lib
2) Create an Expecto-like api that invokes a JS test library like Mocha or Jest (https://github.com/fable-compiler/Fable/issues/1039#issuecomment-312658165)
Is this something that interests other folks as well? If so, is there a preference or suggestion for a particular approach?
I think creating an Expecto-like API layer for another test library would be easier than creating a plugin that does AST transformations.
We already have some simple example of tests usage:
I don't know well expecto API but perhaps this two samples have a similar syntax to it already ?
I didn't look into QUnit, but it looks like Mocha already has a kind of similar API to Expecto, and some features that can be mapped to Expecto as well, like exclusive tests (focused in Expecto) or asynchronous tests.
@MangelMaxime That and the other JS bindings won't help here as the main goal is to have tests that will run on both dotnet and js for "isomorphic" libs, not just having the same style. Most projects I've seen do Server unit tests in Expecto or xunit and client unit tests via one of the bindings (Jest,Ava,QUnit,Mocha,etc), but the only project I've seen with dual targeting tests is the Fable Core suite using Fable.Plugins.NUnit.
Honestly, the xunit+plugin approach does work just fine today and does meet my needs, I was hoping to avoid porting existing Expecto based test projects over to xunit for code I'd like to start consuming from client code. (That and a personal preference towards Expecto over alternatives on the dotnet side).
@inosik Thanks for looking into Mocha deeper, sounds like a promising approach. I had not looked deeply at any of them yet and wasn't even sure if they had feature parity with Expecto.
Hi @johlrich, just FYI, I have created Fable bindings to Jest here: https://github.com/jgrund/fable-jest
I have also started to port some expecto functionality; Here is an example using testList: https://github.com/jgrund/fable-jest/blob/master/test/Matchers.test.fs#L127.
We are using this lib in production to run our unit (and soon) integration tests. I'll be adding more expecto functionality as needed, but PRs always welcome 馃槃
I need to add unit testing to ts2fable and was working on that today https://github.com/fable-compiler/ts2fable/pull/58. I'm not super happy with this:
module ts2fable.Tests
open Fable.Core.JsInterop
open Fable.Import
let mocha: Mocha.IExports = importDefault "Mocha"
let assertt: Chai.Chai.Assert = import "assert" "Chai"
mocha.describe.Invoke("my suite", fun _ ->
mocha.it.Invoke("my test", fun donee ->
assertt.equal(1, 1)
donee.Invoke()
)|> ignore
) |> ignore
mocha.describe.Invoke("keywords", fun _ ->
mocha.it.Invoke("done", fun donee ->
assertt.equal(Keywords.escapeWord "done", "``done``")
donee.Invoke()
)|> ignore
) |> ignore
It works and there is an AppVeyor test reporter which is cool. Happy to use something else. It would be nice if there was a AppVeyor test reporter.
@ctaggart Here is how we use Mocha in general.
https://github.com/fable-compiler/fable-powerpack/blob/master/tests/DateFormatTests.fs#L8-L16
Can't we general a function for mocha.describe ? Instead of the mocha.describe.
Also, I believe for some bindings perhaps it suitable to make them manually to make them more F# friendly. Or add some helpers, on top of the bindings to "glue" the code.
Thanks @MangelMaxime. Yes, that looks good. I'll use those.
The purpose of the NUnit plugin was indeed to be able to run tests both in .NET and JS. Now that Expecto is more common in F# projects, I agree it's better to move on. Furthermore, Expecto's API is closer to that of standard JS test runners like Mocha or Jest. I also agree it's better to use an existing JS test runner so we don't have to write reporters (which are very important as @ctaggart confirms) and such ourselves. I can think of three possibilities right now:
Use a plugin to convert Expecto tests into Mocha/Jest: This is the approach I took for Fable tests, but now I regret it a bit, as it's more work, involves compiler hacking and also plugins haven't become very popular in the community.
Use conditional compilation to add Emit attributes to Expecto functions: this could work but at the end it involves magic strings, which is not ideal. Another common problem of this approach (and the one above) is it's difficult for users to know how much of the .NET library API is ported to Fable.
Create a common wrapper that could use Expecto for .NET and Jest/Mocha in JS: I did something similar when moved Fable tests from NUnit to XUnit. This could make it easier to get advantage of @jgrund's work for example, and it's also explicit to users which API is cross-platform supported. The main disadvantage is users may need to adapt their Expecto tests, but most of the work could be avoid using aliases.
BTW @MangelMaxime, the equal function in fable-powerpack tests is wrong, it should use Fable.Core.Testing.Assert. I realized I had forgotten to update it, so I just did it.
This was an interesting thread, sadly the continuation link (last post) is broken. Where did fable-scripts go?
Most helpful comment
The purpose of the NUnit plugin was indeed to be able to run tests both in .NET and JS. Now that Expecto is more common in F# projects, I agree it's better to move on. Furthermore, Expecto's API is closer to that of standard JS test runners like Mocha or Jest. I also agree it's better to use an existing JS test runner so we don't have to write reporters (which are very important as @ctaggart confirms) and such ourselves. I can think of three possibilities right now:
Use a plugin to convert Expecto tests into Mocha/Jest: This is the approach I took for Fable tests, but now I regret it a bit, as it's more work, involves compiler hacking and also plugins haven't become very popular in the community.
Use conditional compilation to add
Emitattributes to Expecto functions: this could work but at the end it involves magic strings, which is not ideal. Another common problem of this approach (and the one above) is it's difficult for users to know how much of the .NET library API is ported to Fable.Create a common wrapper that could use Expecto for .NET and Jest/Mocha in JS: I did something similar when moved Fable tests from NUnit to XUnit. This could make it easier to get advantage of @jgrund's work for example, and it's also explicit to users which API is cross-platform supported. The main disadvantage is users may need to adapt their Expecto tests, but most of the work could be avoid using aliases.
BTW @MangelMaxime, the
equalfunction in fable-powerpack tests is wrong, it should useFable.Core.Testing.Assert. I realized I had forgotten to update it, so I just did it.