Using canopy and F# for functional testing

Using canopy and F# for functional testing

There are a lot of ways to test the software. The most popular are for sure unit tests, but they check only separate part of the solution. Functional tests on the other hand, allows us to check whole application in testing environment – interaction to db, backend code, frontend code, browser compatibility. This is the thing that we do every time manually after adding new feature – we open browser and we do manual steps to check if everything is ok. By automating this we can save ourselves a lot of time.

In Java world the most popular tool for functional testing is Selenium, which was also adopted for .Net world and you can use it in your program. But in my opinion the easiest for functional testing in .Net is canopy which connects power of F# with power of Selenium.

The best example of what canopy is can be found on their homepage:

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

This example is I believe self explenatory. By writing start firefox we start browser, then using url command we go page we want to test. We find html controls on page using standard “#by_id”, “.by_class” syntax and either by “==” we assert that value is correct or we use “<<“ to pass new value to control. To interact with page we have also very simple commands click “#button_id”  or press enter. As you can see writing test in canopy looks pretty much as writing test in natural language, which I think is a great advantage of this framework.

To show you a little bit more complex example, I wanted to present you simple authentication tests. The first module – User:

module User

open canopy
open lib12.Data.Random
open Consts

let login user password =
    url LandingPageAddress

    click "#loginLink"
    on LoginPageAddress

    "#tEmail" << user
    "#tPassword" << password
    press enter
    on LoggedInLandingPage

let logout =
    click "#logoutLink"
    on LandingPageAddress

let registerRandomUser =
    url LandingPageAddress

    click "#registerLink"
    on RegisterPageAddress

    "#tEmail" << Rand.NextEmail()
    "#tPassword" << TestPassword
    "#tConfirmPassword" << TestPassword
    check "#chTermsAccepted"
    press enter
    on LoggedInLandingPage

LandingPageAddress, LoggedInLandingPage and others are part of Consts module. I create three reusable functions – login, logout and registerRandomUser. Login gets user and password as arguments and tries to pass them to login form after that checks if user is on correct landing page. Logout only job is to click logout link and check if user is on main page. Finally registerRandomUser uses my lib12 library to create random email address, pass it to registration form and check if user is logged in.

Actual test scenarios are created in Program module, when I create two simple scenarios to check login and user registration:

open canopy
open runner
open User
open Consts

start firefox

"login and logout as test user" &&& fun _ ->
    login TestUser TestPassword
    logout

"register new user and logout" &&& fun _ ->
    registerRandomUser
    logout

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

quit()

As you can see canopy is really easy, even for someone who doesn’t have a deep knowledge of F# and can be really useful for automation of web page testing.

Leave a Reply

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