Scott Hanselman

NuGet Package of the Week: Canopy Web Testing Framework with F#

March 25, 2014 Comment on this post [18] Posted in NuGet | NuGetPOW | Open Source
Sponsored By

I've been exploring Automated Browser Testing recently, and also checking out F# for unrelated reasons. However, when you combine the two you end up with "canopy." Canopy is a "f#rictionless web testing" framework that combines the flexibility of Selenium with the clean look of the F# language. F# is much terser (more elegant, even) than C#, and is garnering the interest of a lot of the .NET Open Source community. Folks are creating cool domain specific languages of their own using F# as the base.

You already have F# and perhaps didn't realize you did! If you don't, there's lots of ways to get F# for free. You can use F# for free with VS2013 Desktop Express plus Visual F# Tools 3.1.1.

F# is open source and cross platform, running on Linux, Mac OS X, Android, iOS, Windows as well as HTML5 and GPUs. F# is free to use and has an OSI-approved open source license.

Even if you don't feel like installing anything, you can learn and play with F# in your browser now! Check out 

Also check out FunScript, which is F# to JavaScript! Don't believe them? Try Pacman using F# and JavaScript with source!


Anyway, back to Canopy. Make a new Console app and NuGet in the canopy package:


The NuGet package will bring in Selenium as a dependency.

Then, try out their "Hello World" web testing sample, that I've also pasted here.

//these are similar to C# using statements
open canopy
open runner
open System

//start an instance of the firefox browser
start firefox

//this is how you define a test
"taking canopy for a spin" &&& fun _ ->
//this is an F# function body, it's whitespace enforced

//go to url
url ""

//assert that the element with an id of 'welcome' has
//the text 'Welcome'
"#welcome" == "Welcome"

//assert that the element with an id of 'firstName' has the value 'John'
"#firstName" == "John"

//change the value of element with
//an id of 'firstName' to 'Something Else'
"#firstName" << "Something Else"

//verify another element's value, click a button,
//verify the element is updated
"#button_clicked" == "button not clicked"
click "#button"
"#button_clicked" == "button clicked"

//run all tests

System.Console.WriteLine("press [enter] to exit")
System.Console.ReadLine() |> ignore


And boom, it just works. You can run this .NET application just like any other. .NET apps are .NET apps, as they say. It doesn't matter what language it's written in. When (if) you distribute this application you'd just include the contents of your Debug folder. No need to "install" F# or anything on the target machine.


You can do all sorts of Selenium testing with canopy, like:

//start a bunch of browsers and switch around
start firefox
let mainBrowser = browser
start chrome
let secondBrowser = browser
//switch back to mainBrowser after opening secondBrowser
switchTo mainBrowser

//take screenshots
let path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\canopy\"
let filename = DateTime.Now.ToString("MMM-d_HH-mm-ss-fff")
screenshot path filename

//get an element
element "#firstName" |> someParent

//press buttons
press tab
press enter
press down
press up
press left
press right

//check and click things
check "#yes"
click "#login"

//or even drag things!
drag ".todo" ".inprogress"

Oh, and by the way, the canopy library builds itself using FAKE, the F# Build System we talked about last week! Go check these projects out and offer to help or support them. There's a lot of interesting open source happening in the .NET space lately that may have been flying under your radar.

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
March 25, 2014 4:43
Wow. I've used Cucumber (Ruby's equivalent of canopy) and canopy looks like it holds its own quite well. I'm kind of diving into F# myself nowadays and writing program logic in a functional way is _tons_ of fun.
March 25, 2014 4:47
Neat. RE: the emphasis on F#, though, this is a Nuget package and thus an assembly or a bunch of assemblies like any other, right? Doesn't that mean I could use any CLR language I wanted?
March 25, 2014 5:10
@Aashish, technically yes you could. But if you try to implement the same code in C# it will most definitely be a lot more code and harder to read. The beauty of F# is how clear and concise it is (IMO).
March 25, 2014 6:34
Great work on the library, its a nice example of utilizing F# well.

@Aashish, Attempting to use a lib that makes great use of F# language features from another CLR language can be difficult at best. I'd recommend giving it a shot and see how it feels. If you want to do some automation in C# with a concise, simple syntax check out the previous blog post on automation: NuGet Package of the Week: FluentAutomation for automated testing of Web Applications. I'd challenge anyone who says its harder to read but I really do enjoy both libs. (disclaimer: developer of FluentAutomation ;))
March 25, 2014 9:30

<input type="hidden" hidden="hidden"/>

Sir,I am little confused about this attribute hidden="hidden".What's the significance of this attribute(hidden="hidden").
Thank You.
March 25, 2014 11:10
@Nitish, the hidden attribute is new in HTML 5. You're more likely to see it used on it's own without setting a value although both are correct.

W3Schools hidden attribute
March 25, 2014 12:36

In your blog "audo" text is rendered at top of the HTML. I can see it in this blogpost and also in your blog root URL.

March 25, 2014 22:38
Great postings. Cheers!
March 26, 2014 6:05
I like this. I hope the folks at Microsoft are paying attention. This seems much more approachable than the coded UI tests that I have seen. F# is cool and it's great to see a practical implementation of a functional language.
March 26, 2014 12:29
@Kevin.Thanks for your support
March 26, 2014 19:35
Wonderful information, Thank you!
March 26, 2014 21:44
I've been using Coypu recently which is the C# equivalent of Canopy.

It's been around for a long time and is very stable. I believe Canopy was modelled on Coypu which itself was modelled on the Capybara API for Ruby.
March 27, 2014 1:46
Can F# and Canopy be integrated into the TFS Build process?
March 27, 2014 2:37
@Jose Diaz You should be able to. You can just create your canopy project as an F# console app. Then have TFS build the console app and run the resulting exe. I personally use TeamCity but the process should be similar.
March 27, 2014 23:58
lefthandedgoat has done a great job with canopy. It was useful on day one for me. @amirajan's Oak project was where I was introduced to canopy.

I am stuck in VS2010 at the moment, so the current maximum version I use is 0.8.9. It still has a lot of features, plus extensions are easy to create.

Having tried other UI testing libraries, canopy was the easiest out-of-the-box. The DSL is easy to master, even for those of us F# noobs. Moreover, it's a F# primer. I now have a better understanding of F# having used canopy.
March 28, 2014 18:27
@Kurt I will fix the problem with VS 2010 in an upcoming build. I will open a ticket now. Thanks!
March 30, 2014 2:57
It would be awesome to use NuGet instead of or in conjunction with MSI. Has anyone considered this?

I have a project I'm working on where I need to unify multiple packages (MSI, exe, etc.) into a single installer. I must resolve dependencies and conflicts as well as per-package options.

I had considered writing my own SAT solver, but if I can use, embed, or leverage NuGet somehow that would be amazing!
March 30, 2014 11:02
Hello Scott,
As always you use to write a blog with a full of information and knowledge. Thanks

Citrix Web Interface

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.