There are many methods of testing your application. Great tools like Selenium are widely used, and developers (should) write unit tests for their code. In a DevOps team, we want to run tests automated, ideally using continuous integration tools like TeamCity or Release Manager.
This post will show an example of testing your AngularJS fully automated from within Visual Studio or your continuous integration tooling.
Setting up your environment
Instead of defining the unit tests manually, we will be using SpecFlow. It’s Gherkin syntax will allow you to specify human-readable tests that automagically generate the unit test skeleton files. SpecFlow has integration installers for almost all versions. See this link to install your version. In this post we will be using Visual Studio 2015 professional.
Writing your first SpecFlow feature file
After setting up your environment correctly, adding a new item will show the following dialog:
We will create a file called ‘TodoTester.feature’. In this example we will make a test that uses a sample app located at http://todomvc.com/examples/angularjs/.
In this simple test, we will add some items to the todo list, and remove some items from the todo list.
First of all, we write our scenario in the feature file. As you can see, the Gherkin syntax is human-readable and can be setup together with our client/product owner/business consultant. SpecFlow will enable you to generate the unit-test file.
In the feature file above, we have defined some steps in the Gherkin syntax. Right-clicking the file will enable us to create the steps and copy them to a .cs file. In this project, the file is called StepDefinition1.cs. The skeleton methods can been seen below:
The great plus of this is that we can keep our changes ‘in sync’ by updating the method from the feature file. And, shown in the example above, the tool is smart enough to extract variables from within the feature file.
Writing the unit test for AngularJS
One of the problems of end-to-end testing is that most webdrivers like Selenium cannot detect if AngularJS’ async calls are done loading. A workaround for this problem is to wait for some kind of element is present, or wait until a spinner of some kind has been removed. A better way is to use a driver that natively works with AngularJS projects.
Protractor is a library, built on top of the Selenium WebDriver and understands the behaviour of AngularJS. It wraps drivers like ChromeDriver and enables them to understand AngularJS. Installing this package is very easy using the Install-Package syntax, and the setup is easy in code, see the example below:
After initialization, the next step is to write the code for the skeleton method, as shown in the screenshot below:
Running the test
Running the test will spin up Chrome, execute all steps programmed in the test, and quit the runner and webdriver. A succesful test will give the following feedback within Visual Studio:
Running the test from our build server
While the Chrome webdriver (wrapped in the NgDriver) works perfectly on our development machine, we also want to run these test on other platforms, using a headless driver. PhantomJS is a headless driver, suited for these situations. The setup in code is as follows:
Because the PhantomJS WebDriver is also wrapped in the NgWebDriver, there is no need for further code adjustments, our unit tests will work exactly the same.
Bonus features
This post explains just the basics of SpecFlow / Protractor / NgWebDriver, but there are many features that can be of great use in testing scenario’s. One of these is taking screenshots after tests, explained in code below:
This will take a screenshot and save it to disk. This can come in handy when tests fail and, in addition to the stacktrace from our buildserver, can help speed up finding issues.
Recap
In this post I’ve tried to tie the SpecFlow / Protractor / WebDriver tools together to show a simple example of end-to-end testing. In the DevOps fashion, we are able to run these tests on any platform, from your favourite IDE or from your buildserver, any time, all the time.
Using the Protractor library there is no need to add extra logic to wait for AngularJS calls to end, and using SpecFlows Gherkin syntax it is possible to write human-readable tests together with your stakeholders.
Please feel free to contact me in case you have any questions!