User interface testing

Even though unit testing can and should cover the major part of the application, there is still a need to work on functional and acceptance tests. Unlike unit tests, they provide higher-level verifications, and are usually performed at entry points, and rely heavily on user interface. At the end, we are creating applications that are, in most cases, used by humans, so being confident of our application's behavior is very important. This comfort status can be achieved by testing what the application is expected to do, from the point of view of real users.

Here, we'll try to provide an overview of functional and acceptance testing through a user interface. We'll use the Web as an example, even though there are many other types of user interfaces such as desktop applications, smart phone interfaces, and so on.

Web testing frameworks

The application classes and data sources have been tested throughout this chapter, but there is still something missing; the most common user entry point—the Web. Most enterprise applications such as intranets or corporate sites are accessed using the browser. For this reason, testing Web provides a significant value, helping us to make sure that it is doing what it is expected to do.

Furthermore, companies are investing a lot of time performing long and heavy manual tests every time the application changes. This is a big waste of time since a lot of those tests can be automatized and executed without supervision, using tools such as Selenium or Selenide.

Selenium

Selenium is a great tool for Web testing. It uses a browser to run verifications and it can handle all the popular browsers such as Firefox, Safari, and Chrome. It also supports headless browsers to test web pages with much greater speed and less resources consumption.

There is a SeleniumIDE plugin that can be used to create tests by recording actions performed by the user. Currently, it is only supported by Firefox. Sadly, even though tests generated this way provide very fast results, they tend to be very brittle and cause problems in the long run, especially when some part of a page changes. For this reason, we'll stick with the code written without the help from that plugin.

The simplest way to execute Selenium is to run it through JUnitRunner. All Selenium tests start by initializing WebDriver, the class used for communication with browsers:

  1. Let's start by adding the Gradle dependency:
    dependencies {
      testCompile 'org.seleniumhq.selenium:selenium- java:2.45.0'
    }
  2. As an example, we'll create a test that searches Wikipedia. We'll use a Firefox driver as our browser of choice:
            WebDriver driver = new FirefoxDriver();

WebDriver is an interface that can be instantiated with one of the many drivers provided by Selenium:

  1. To open an URL, the instruction would be following:
            driver.get("http://en.wikipedia.org/wiki/Main_Page");
  2. Once the page is opened, we can search for an input element by its name and then type some text:
            WebElement query = driver.findElement(By.name("search"));
            query.sendKeys("Test-driven development");
  3. Once we type our search query, we should find and click the Go button:
            WebElement goButton = driver.findElement(By.name("go"));
            goButton.click();
  4. Once we reach our destination, it is time to validate that, in this case, the page title is correct:
            assertThat(driver.getTitle(), startsWith("Test-driven development"));
  5. Finally, the driver should be closed once we're finished using it:
            driver.quit();

That's it. We have a small but valuable test that verifies a single use case. While there is much more to be said about Selenium, hopefully, this has provided you with enough information to realize the potential behind it.

Note

Visit http://www.seleniumhq.org/ for further information and more complex use of WebDriver.

The complete source code can be found in the SeleniumTest class in the https://bitbucket.org/vfarcic/tdd-java-ch02-example-web.git repository.

While Selenium is the most commonly used framework to work with browsers, it is still very low level and requires a lot of tweaking. Selenide was born out of the idea that Selenium would be much more useful if there wasa higher level library that could implement some of the common patterns and solve the often repeated needs.

Selenide

What we have seen about Selenium is very cool. It brings the opportunity to probe that our application is doing things well, but sometimes it is a bit tricky to configure and use. Selenide is a project based on Selenium that offers a good syntax for writing tests and makes them more readable. It hides the usage of WebDriver and configurations from you, while still maintaining a high level of customization:

  1. Like all the other libraries we have used until now, the first step is to add the Gradle dependency:
    dependencies {
        testCompile 'com.codeborne:selenide:2.17'
    }
  2. Let's see how we can write the previous Selenium test using Selenide instead. The syntax might be familiar to for those who know JQuery (https://jquery.com/):
    public class SelenideTest {
        @Test
        public void wikipediaSearchFeature() throws InterruptedException {
            // Opening Wikipedia page
            open("http://en.wikipedia.org/wiki/Main_Page");
    
            // Searching TDD
            $(By.name("search")).setValue("Test-driven" + " development");
    
            // Clicking search button
            $(By.name("go")).click();
    
            // Checks
            assertThat(title(), startsWith("Test-driven" + " development"));
        }
    }

This was a more expressive way to write a test. On top of a more fluent syntax, there are some things that happen behind this code and would require additional lines of Selenium. For example, a click action will wait until an element in question is available, and will fail only if the predefined period of time expired. Selenium, on the other hand, would fail immediately. In today's world, with many elements being loaded dynamically through JavaScript, we cannot expect everything to appear at once. Hence, this Selenide feature proves to be useful and saves us from repetitive boilerplate code. There are many other benefits Selenide brings to the table. Due to the benefits that Selenide provides when compared with Selenium, it will be our framework of choice throughout this book. Furthermore, there is a whole chapter dedicated to Web testing using this framework. Visit http://selenide.org/ for more information on ways to use Web drivers in your tests.

No matter whether tests were written with one framework or the another, the effect is the same. When tests are run, a Firefox browser window will emerge and execute all steps defined in the test sequentially. Unless a headless browser was chosen as your driver of choice, you will be able to see what is going on throughout the test. If something goes wrong, a failure trace is available. On top of that, we can take browser screenshots at any point. For example, it is a common practice to record the situation at the time of a failure.

The complete source code can be found in the SelenideTest class in the https://bitbucket.org/vfarcic/tdd-java-ch02-example-web.git repository.

Armed with a basic knowledge of Web testing frameworks, it is time to take a short look at BDD.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset