Web UI testing with Canopy

- [Instructor] Let's now go to the opposite endof the stack and look at web user interface testing.For this video, we'll use a package called Canopyand a dummy florist website which I've got here.The transaction we want to testis that we click on Build a Bouquet,select Calla Lilies, pick the second color,pick a quantity, and add to basket,and we want to test that the estimated total is $60.That's not the real cost of two calla lilies,because it's a completely dummy website,but it shows the principal.

To do that, firstly, we're going to needto download a thing called ChromeDriver.You can just search for ChromeDriver online,download the latest release,and I'm using Windows so I'll pick that one.Just copy the single .exe.I'm going to put it in my C:\Program Files (x86).No reason to call it anything other than ChromeDriver.And there's no installation.As long as you know the path where it is, that's enough.

Now I'm going to go to Visual Studio,and I'm going to make a new project.It's going to bewhatever the latest version of .NET framework is,and it's going to be a Console Application.I'll leave it in my Visual Studio projects,and I'm going to call it CanopyTesting.Now, I'm going to install paketbut in a slightly cheaty way.I'm going to open the folder location.I'm just going to go to another projectand that one's got the bootstrapper in.

Copy .paket, put it in CanopyTesting.And then we'll just get rid of paket.exeand paket.targets and we'll just keep bootstrapper.Go back to Visual Studio, make sure we saved everything,open up the Package Manager Console,run the bootstrapper, and paket init.Then add nuget Canopy to the single project we've got.

We load, and there we go.We can get rid of everything in Program.fs,make a module called Main,open some namespaces.Probably want System.We'll definitely want canopy with a lowercase c.Likewise, a thing called runner,and we're also going to want the thingwhich Canopy is based on,which is Selenium,which is a very well-established automation framework.Canopy is essentiallya nice F# friendly wrapper 'round Selenium.

Now I'm going to make myself a little AutoOpen module,which we're going to call Selectors,and this is the place where we'll keepthe selection paths for all the things in the website.So, the first thing we clicked on,if you remember back to the transaction we performed,was to click on Build a Bouquet,so I'm going to make a let binding called,with back tick quotes, build a bouquet.You don't have to use back tick naming here,but I find it's just a little more friendlywhen we come to consume the selectors.

And what's the value for that going to be?Well, go back to the website,make sure it's in its initial state.Its initial state had Arrangements clicked.And then right-click on Build a Bouquet,say Inspect.This is in Chrome.And without changing the selection up here,say Copy selector,and if you go back to Visual Studio,you can put a couple of quotes in there and paste.

And that copies my selector,which, given the website's in its initial state,will be guaranteed to pick the right button.But I'm just going to repeat thatfor all the things we clicked.So the next one was Calla Lilies.Inspect.Copy selector.And I'll just repeat that for everything we did.And then finally, go back to the website.

The last thing we did was to do an Add to Basket.That popup came up,and we wanted to verify this value here,so I'm going to inspect that,copy its path selector,and that's all the selectors we're going to need.We're going to need to set up Chrome,so I'm going to have a module called Initialize.I'm just going to set a value called chromeDir,which comes from Canopy.

We're using a silent operator.And this will need to bewhatever path you installed ChromeDrive into,so in my case, that was C:\Program Files_(x86)\ChromeDriver.And we need to start Chrome.So that would cause Chrometo be run when our testing program runs.Now we need an actual test.And we call it "I can order a bouquet."And this strange triple ampersand operatoris Canopy's way of expressing a test.

Before it goes the name of a test.After it needs to go the lambda,which is the body of the test.I'm going to use that same way of linking up to a lambdathat we did in expector, just like that.Now in the body of a test,I can use a Canopy keyword called url.It will just take Chrome to a URL.The URL I want is the homepage,which is this, including the improved bit.

And I'm going to leave the bodyof the test at that just for nowso we can demonstrate that the automation works,and the next thing I'll need to do is say run() here,and just so we get a chancefor the user to read the test results,I will say printfn "Press [Enter] To exit,"and we'll just read a key from the consoleso it doesn't disappear straightaway.

Finally, I will quit(), which will close down Chrome.Oh, yes, I just need to ignore the results of ReadKey.All right, let's run that.And sure enough, it loads up Chromein its own independent window that it's controlling,and it navigates to Hansel Petal improved.So now let's go back and fill out the body of the test.

We need to click on Build a Bouquet,and that could not be simpler.We simply type click, and build a bouquetshould be in my IntelliSense somewhere.There we are.Click is a keyword provided by Canopy,and that will cause the relevant controlwith whatever path you provide to be clicked,and remember, we defined the build a bouquet selector here.Click calla lilies and color.

Then having selected the color control,and one way to pick a particular colorwould have been to press the down arrow key,but we can just say press,and that's provided by Canopy as well,Keys.ArrowDown, and the key's enumerationis provided by the OpenQA.Selenium.So that's why I opened that namespace before.Then we need to to click the quantity.By the way, it's not putting in the double back quotesfor things up here that don't need thembecause they have those spaces in, but just for consistency,I'm going to force those in there.

Then we'll do Backspaceto delete the existing quantity value, one way of doing it.NumberPad2, one way of pressing two.Enter.And then we need to add to basket,so that's click add to basket.Let's see if that works.Let me just maximize Chrome for you,and yes, we're in exactly the place we wanted to be,which was with the basket preview open.

So that's absolutely perfect.And it saying that the test have passed in thisconsole window simply because the test had no assertion.Incidentally, in early versions of Visual Studio 2017,you may not see the console windowwhen you run a console project.If that starts happening to you,then just save everything, go out of Visual Studio,and back in again, and you'll be fine.So now we need an assertion in our test.Again, that's almost comically easy.

We want path, selector I should say,which is our basket total.That was the number at the bottom of the basket preview.We want a double equals,because that's the equality assertion in Canopy.We want the expected value, which was $60, as a string.In fact, let's firstly make sure the test can failby putting an incorrect value in there.So let's make it $60 and a cent.So that is the assertion of our test.

And you can see that if I hover over it,the double equals is being provided by Canopy.Now, you'll get a bit of a pause when a test failslike this, simply because it's giving the websitea chance to produce the expected number.It doesn't fail immediately because obviouslythere's inherently delays in web rendering.Yeah, and there are exceptions.Expected 60.01, got 60.I can turn off break on exception.And we see the failure in the console.Right, let's prove the test can passby putting in the right value.

And there we are, passing test.So let's just take stock.We installed a thing called Canopy,which is a wrap around Selenium.We navigated through the transaction we wanted to do,and we used Chrome, right-click, inspect,copy selector to get the selectors.We put a little module of those in just for convenience.I could just as well have put this literal value down here,but I just think it's more readableif you keep all the names simplewhen you're actually consuming those selectors.

Makes it more maintainable as well.If these get renamed in the website,we have to just change those in the selectors project.We'll just name that, let me call that Selectors.Then we initialize starting Chromeusing the ChromeDriver that we downloaded.Then I wrote a test with a name and a lambda.Then I used Canopy keywords like click and url and pressand the assertion to write a really nice test,and I just had a little bit of boilerplate herejust to run the testand give the user a chance to read them.

So there's a lot more to Canopy.We're not going to go through it all now,but if we have a little look, for instance,at the assertions page,just look at all the assertions you can have.You have have one of many equals, so you can lookthrough a list that you're not sure the order ofand make sure it contains a certain itemor it doesn't contain a certain item.Or you can use case insensitive matching,or you can use regular expression matching.So it's really an enormously powerful framework,based, of course, on the power of Selenium underneath.

If you do need to automate a website,this is a great way to do it.Having said that, we have to acceptthat these UI-style automation teststake a lot of maintenance, because they're very sensitiveto changes in the layout, element naming, and so forth.However, if you can cover the key workflowsof your site with automation tests,it is a great confidence booster.

Resume Transcript Auto-Scroll

Author

Released

6/15/2017

Automated testing is a popular topic in software development, but it's still often seen by developers as overhead rather than as an opportunity. By leveraging F# and some external tools and libraries, you can make automated testing easy, enjoyable, and productive. In this course, learn about a variety of techniques for writing automated testing code in F#.

Kit Eason explains how to use xUnit—a .NET unit-testing package—to do some test-driven development, and demonstrates how to improve your test run experience using NCrunch, a test runner. He shows how to use FsCheck to generate test cases, and how to use Expecto to move into the world of tests as first-class values. He also covers the use of Canopy to automate the testing of web user interfaces, and of mocking to tame dependencies.