F# Unit Testing Simplified – Expecto with Visual Studio Code

This post is a slightly shorter follow on post to my last one, F# Has Won Me Over: Coming to .Net World from Outside .Net

In that post, I showed how to set up a basic F# development workflow using Visual Studio Code. It probably seemed a little overkill just to get simple tests up and running.I’m glad I took this longer approach though as, coming into .NET world, it made me aware of how the tools and F# projects fit together under the hood – something that wouldn’t be as clear if I went the all out IDE approach.

Since publishing that blog, I have gotten a lot of really helpful feedback from others in the F# community and I have taken a look at an F# testing tool called Expecto

The Ionide plugin for Visual Studio Code has a really nice integration for running tests using Expecto – it’s a whole lot simpler then the workflow I showed in my last post!

Following from my last post, lets add a different test project to test the MusicLibrary project and we’ll use Expecto this time to run our test.
Again, I’m running Visual Studio Code on Mac OSX in this example but the steps should be more or less the same for other operating systems.

So, back in Visual Studio Code, type cmd-shift-p to open the command palette
Type F# and select F#:New Project

Choose a console as this will give us a main entry point for Expecto to run tests.

You will be prompted for the name of the project directory.

Lets just call it MusicLibraryExpectoTests

You will then be prompted for the name of the project.

Again, MusicLibraryExpectoTests will be grand.

Now we need to add our Expecto dependencies with Paket.

So open up the newly creted MusicLibraryExpectoTests directory and open MusicLibraryExpectoTests.fsproj

Open the command palette again, cmd-shift-p
Type Paket and select Paket:Add NuGet Package (to current project)

Then type Expecto and Enter.

You will see, info in the Paket output terminal.

Afterwards, you should be able to search Expecto in the MusicLibraryExpectoTests.fsproj file and find something like

   
 ..\..\packages\Expecto\lib\net40\Expecto.dll
               

Repeat for
Expecto.BenchmarkDotNet
Expecto.FsCheck

After all this, our paket.references file within the MusicLibraryExpectoTests project should contain

FSharp.Core
Expecto
Expecto.BenchmarkDotNet
Expecto.FsCheck

Lets try out a hello world expecto test. So, open up MusicLibraryExpectoTests.fs which will have automatically been created for us when we created our MusicLibraryExpectoTests project.

Replace the contents of that file with the following:

module MusicLibraryExpectoTests

open Expecto

[<Tests>]
let tests =
  testCase "yes" <| fun () ->
    let subject = "Hello World"
    Expect.equal subject "Hello world"
                 "The strings should equal"


[<EntryPoint>]
let main args =
  runTestsInAssembly defaultConfig args

and save.
Here we have added one test case and a main function as an entry point for expecto to run our tests.
We can easily run our test simply as follows:
Open command palette, cmd-shift-p
Type Ex and choose Expecto:Run

In the expecto output terminal, we can see our failing test!

We can fix our failing test by changing that ‘w’ to upper case so our MusicLibraryExpectoTests.fs becomes:

module MusicLibraryExpectoTests

open Expecto

[<Tests>]
let tests =
  testCase "yes" <| fun () ->
    let subject = "Hello World"
    Expect.equal subject "Hello World"
                 "The strings should equal"

[<EntryPoint>]
let main args =
  runTestsInAssembly defaultConfig args

This time to run the tests, lets just use a shortcut, ctrl-f6
Now, our test passes and you should see this along with other output in the Expecto terminal output in Visual Studio Code:

[21:28:12 INF] EXPECTO?! Summary...
Passed:  1
	yes 
Ignored: 0
	Failed:  0
	Errored: 0

Now, we can use Expecto to test our addSongToLibrary function from the MusicLibrary project that I went through in my last post.
We need to link our MusicLibraryExpectoTests project to this library first. So, open the MusicLibraryExpectoTests.fsproj file again.

Then we can use the command palette, cmd-shift-p to add a project reference.

Choose MusicLibraryExpectoTests for the project to edit

and MusicLibrary as the project to reference

Your MusicLibraryExpectoTests.fsproj should now contain something like

    
ProjectReference Include="../../MusicLibrary/MusicLibrary/MusicLibrary.fsproj"

We can add our test for addSongToLibrary to MusicLibraryExpectoTests.fs as follows:

module MusicLibraryExpectoTests

open Expecto
open MusicLibrary

[<Tests>]
let tests =
  testList "test group" [
    testCase "yes" <| fun _ ->
        let subject = "Hello World"
        Expect.equal subject "Hello World"
                    "The strings should equal"

    testCase "addSongToLibrary adds song to library" <| fun _ ->
        let expected = ["Sir Duke";"Superstition"]   
        Expect.equal expected (addSongToLibrary ["Superstition"] "Sir Duke")
                    "The library list should contain the new song"
    ]

[<EntryPoint>]
let main args =
  runTestsInAssembly defaultConfig args

Now, we can run the tests with ctrl-F6

And in the Expecto terminal output in Visual Studio code,
you should see something like this along with other output

Passed:  2
	test group/yes ....
       ....
	test group/addSongToLibrary adds song to library [/Users/tom/Dropbox/software-
Ignored: 0
	Failed:  0
	Errored: 0

Conclusion

There is a lot more you can do with Expecto. I have just scratched the surface here but, even with the basics here, you can very quickly create and run test cases from within Visual Studio Code. It’s definitely a tool that I will be using a lot!

Leave a Reply

Your email address will not be published. Required fields are marked *