I recently completed a web application project, using UI tests for client side testing. I found it to be one of the best forms of testing you could do, although it did come with a few down sides. Essentially, UI tests, or Automated User Interface tests, automate actions through the UI like a normal user would. I have been focusing primarily on UI tests for web applications using a browser automation tool called Selenium.
Selenium
Selenium is open source and available on GitHib. It supports C# and Java as well as a few other languages, and can run in many browsers like Google Chrome, Firefox, Internet Explorer and Safari among others. Selenium works by finding the specified element on the html page using the DOM, and performs the required actions such as click, enter text, visibility check, basically anything a real user would test for.
Setup
Getting started is very simply. First, you need to create a project for the unit tests. Then, you will need to install the WebDriver for each specific browser you want to run your tests through, so for example, Selenium.WebDriver.ChromeDriver for Google Chrome. This is what Selenium will use to automate tests through the browser.
And that is pretty much it! Next, you will need to write the actual tests.
Sample Test
For this example, I will be using MSTests, but you can go ahead and chose whichever testing framework you prefer.
Firstly, in the test setup, we will need to initialize our browser, so the driver can execute the steps. We will be using Google Chrome to execute our UI tests, so we will initialize a Google Chrome window:
[TestInitialize()] public void Initialize() { driver = new ChromeDriver(); driver.Manage().Window.Maximize(); driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30)); }
This will open a new Chrome instance, then maximize the window. I am also setting the timeout for when trying to perform an action to 30 seconds in the browser. What value you decide to set this to will be dependent on your web application speed, connection speed and how tolerant you'd like your tests to be.
Next, we will need to write our actual test to perform some action on the website. The website we will be testing will be: http://partsunlimited.azurewebsites.net/; a sample retail website for car parts set up by Microsoft. I have created a simple test for the add to cart functionality:
[TestMethod] public void AddToCart() { driver.Navigate().GoToUrl("http://partsunlimited.azurewebsites.net/"); driver.FindElementById("search-box").SendKeys("tire"); driver.FindElementById("search-link").Click(); driver.FindElementsByTagName("a").First(link = > link.GetAttribute("title") == "Chrome Rim Tire Combo").Click(); driver.FindElementsByTagName("a").First(link = > link.Text == "ADD TO CART").Click(); Assert.AreEqual(driver.FindElementById("cart-count").Text, "1"); Assert.IsTrue(driver.Url.EndsWith("ShoppingCart")); }
This test will search for the tires, find a specific one, view the details, then add the item to the shopping cart. The test asserts that once you have added an item to your shopping cart, the shopping cart icon (see image below) updates to the number of items in the shopping cart, and that you are navigated to your shopping cart page, by asserting the URL.
We could then have another test that adds an item to the shopping cart, then removes the item and asserts that the shopping cart, as well as the cart icon, are both updated. Then another test for checking out, logging in etc.
For all of this, you would want to use OOP principles to make the entire process of writing test easier. So, for this website, you’d have a base page which could be header for example, as the header is present on every page:
public class Header {
public Link HomeLogo {
get;
set;
}
public SearchBar SearchBar {
get;
set;
}
public Link HomeIcon {
get;
set;
}
public Link CartIcon {
get;
set;
}
public Link LoginIcon {
get;
set;
}
}
The search bar would look something like:
public class SearchBar {
private SearchTextBox TextBox {
get;
set;
}
private SearchButton SearchButton {
get;
set;
}
public void Search(string searchTerm) {
TextBox.EnterText(searchTerm);
SearchButton.Click();
}
}
public class SearchTextBox {
public void EnterText(string searchTerm) {
driver.FindElementById("search-box").SendKeys(searchTerm);
}
}
public class SearchButton {
public void Click() {
driver.FindElementsByTagName("a").First(link => link.Text == "Add To Cart").Click();
}
}
And of course, this can be broken down further but this is just to give you an idea. This would reduce repetition of code and make writing the UI tests more efficient.
Although UI tests can provide you with an unparalleled level of automated testing, it comes with both advantages and disadvantages:
Advantages:
Save time and money by using automated UI tests instead of requiring human to test repeatedly. And this is a very big one as it saves time and money from QA, reduce the amount of testing software devs have to do, therefore more time for new features.
Normally finds a high number of bugs that server side tests wouldn’t. Normally when you change something, you test the code around the area and run all the server side tests, but if a different area of the UI breaks, you wouldn’t be aware of it, and your server side tests wouldn’t catch it. Personally, I have found that UI tests catch many bugs, that would otherwise not be found until tested by QA.
Huge range of browser automation. There’s not really much a human can do that a UI test can’t.
Test compatibility using multiple browsers. A user going through each browser to test their change and perform some regression testing can be very tedious, whereas a UI test can automatically go through all browsers and perform the same tests.
Disadvantages
Could take an entire day to run all tests. As you add more and more tests, any single test can take several minutes and this can add up. Normally, UI tests are only run overnight on the build server.
Maintenance is a high cost. Maintaining the tests on a daily basis can be a big issue when the UI is okay, but the test is either timing out, or a class has been changed on the UI and this can lead to false indication of issues in the UI.
How long should your timeout be? In our example, we set it to 30 seconds, which is the amount of time you wait for a button to appear, a page to fully load etc. before failing the test. If the test site you are running the server from is slow, some tests may fail as they hit the timeout, other times you need to wait longer than usual for all the data to load before performing an action so it’s a difficult variable to set and it normally varies between pages and actions.
Writing tests can be cumbersome, although using OOP principles helps principles helps to minimize this.
Only tests physical functionality, cannot tests visual elements of the UI. For example, if a button is out of place, due to some CSS, the UI test will still be able to find the button and perform the action, not knowing it is not positioned incorrectly.
Conclusion
From my experience, I have found UI tests very useful due to the number of bugs they pick up. Whether it’s a button not working, or an image not being displayed or the inability to navigate to a certain webpage. The downside for my team was the fact that maintenance of the tests was too high, but I believe this can be minimized effectively by have a good structure to your UI tests, e.g. only testing the main features of the website, instead of every intricate detail.
Comments