canopy - f#rictionless web testing

The canopy library can be installed from NuGet:

PM> Install-Package canopy

canopy is a web testing framework with one goal in mind, make UI testing simple:
  • Solid stabilization layer built on top of Selenium. Death to "brittle, quirky, UI tests".
  • Quick to learn. Even if you've never done UI Automation, and don't know F#.
  • Clean, concise API.
  • .net Standard 2.0.
  • MIT License.

Getting Started

1. Create a new F# console application (4.6.1+ or .net core)

F# New Project

2. Install canopy via Nuget

Install canopy

3. Install chromedriver via Nuget

Install chromedriver

4. Paste the following code into Program.fs

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
//these are similar to C# using statements
open canopy.runner.classic
open canopy.configuration
open canopy.classic

canopy.configuration.chromeDir <- System.AppContext.BaseDirectory

//start an instance of chrome
start chrome

//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 "http://lefthandedgoat.github.io/canopy/testpages/"

    //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
run()

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

quit()

6. Explore the rest of canopy's API

  • Actions: documentation of everything you can do on a page
  • Assertions: all the ways you can verify what's on the page is correct
  • Configuration: configure and fine tune canopy
  • Testing: different ways to orchestrate tests and troubleshoot issues with a page
  • Reporting: different ways to output the results of your test suite

7. Watch some intro videos

4 minute canopy starter kit
5 minutes with Amir Rajan
30 minutes with Chris Holt at fsharpConf
namespace canopy
namespace canopy.runner
module classic

from canopy.runner
module configuration

from canopy
module classic

from canopy
val mutable chromeDir : string
namespace System
type AppContext =
  static member BaseDirectory : string
  static member GetData : name:string -> obj
  static member SetData : name:string * data:obj -> unit
  static member SetSwitch : switchName:string * isEnabled:bool -> unit
  static member TargetFrameworkName : string
  static member TryGetSwitch : switchName:string * isEnabled:bool -> bool
  static event UnhandledException : UnhandledExceptionEventHandler
  static event FirstChanceException : EventHandler<FirstChanceExceptionEventArgs>
  static event ProcessExit : EventHandler
property System.AppContext.BaseDirectory: string
val start : b:canopy.types.BrowserStartMode -> unit
val chrome : canopy.types.BrowserStartMode
val url : u:string -> unit
val click : item:'a -> unit
val run : unit -> unit
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...
System.Console.ReadLine() : string
val ignore : value:'T -> unit
val quit : browser:'a6 -> unit