Using Assertions in your Selenium Tests

In today’s blog post we are going to learn a bit more about some of the most common assertions used in Selenium testing and get some practice with them. Writing good assertions are a critical part of writing good automation tests as they are used to determine whether an expected behaviour has occurred (or not) and will control whether or not the test will ultimately pass or fail.

For this demonstration we are going to use the excellent dummy site setup by the folks over at TOOLSQA – here. This is an excellent site to practice your automation skills on in a ‘live’ environment.

Let’s start by setting up our basic testing framework. In your automation project, right click on ‘test > java’ folder and create a new class called ‘MyFirstAssertionTests’.

Inside the new class, add the following setup code:

public class MyFirstAssertionTests {

    public static FirefoxDriver driver;

    @BeforeClass
    public static void setupDriver()
    {
        driver = new FirefoxDriver();
    }
    
    @Before
    public void goToAccountPage()
    {
        driver.get("http://store.demoqa.com/products-page/your-account/");
    }
    
    

    @AfterClass
    public static void quitDriver()
    {
        driver.quit();
    }
}

That’s the basic setup done, but the class won’t to anything yet as we don’t have any tests. Let’s change that below.

assertTrue
The first assertion that we are going to look at is ‘assertTrue’. Let’s start off nice and easy, and just check that the title of the page is what we expected. Add the following test:

    @Test
    public void assertTrue_PageTitle()
    {
        assertTrue(driver.getTitle().equals("Your Account | ONLINE STORE"));
    }

If we run this test everything should pass as expected. Great. What about if the test fails? Change the code in the test to the following and re-run the test:

    @Test
    public void assertTrue_PageTitle()
    {
        assertTrue(driver.getTitle().equals("Some dummy text"));
    }

Now the test fails, again as expected because we put some rubbish title to search for. Take a look at the error message thrown by Junit in Intellij:
blogpost1
This error message, whilst OK, doesn’t really provide much information. Imagine we had 100 different tests checking various titles throughout our website and lots of them were failing. It would be really nice to have some more information. When you are calling ‘assertTrue’ (and any of the asserts, for that matter), you can put an optional string at the start of the message that will be output to the console in the event of an error. Try it out, change the test to the following and run the test again:

    @Test
    public void assertTrue_PageTitle()
    {
        assertTrue("Error with page title on 'Your Account' page", driver.getTitle().equals("Some dummy text"));
    }

This time when the test fails, we get some relevant information in the test error message:
blogpost2
assertEquals
Let’s do something a tiny bit more advanced. We are going to check that some text on the page is what we expect it to be, namely we will check that the title of the form we are submitting is ‘Your Account’. To do this, we first need to lookup the HTML code for that WebElement using FireBug and FirePath (see this post if you need a recap on how to use FireBug). Open up FireBug and look up the ‘Your Account’ text:
blogpost3
We can see that the text ‘Your Account’ has a CSS selector ‘.entry-title‘. The ‘.’ in a CSS selector stands for the classname, so we can say that this element has a classname of ‘entry-title‘. We now have enough information to write the automated test. Add the following code to your test class:

    @Test
    public void assertEquals_FormTitleIsYourAccount()
    {
        WebElement yourAccountLabel = driver.findElement(By.className("entry-title"));

        String yourAccountLabelText = yourAccountLabel.getText();

        assertEquals(yourAccountLabelText, "Your Account");
    }

We have a bit of new code here that you might not have seen before. First of all we grab the WebElement ‘yourAccountLabel’ using the className. From that element, we then extract the text from it into a string using the ‘.getText()’ method:

String yourAccountLabelText = yourAccountLabel.getText();

Now that we have the String, we can check that it is equal to ‘Your Account’:

assertEquals(yourAccountLabelText, "Your Account");

When the assertEquals fails, it has more useful output than a simple assertTrue. We can make it even more useful by adding a description string at the start of the call. Go ahead and make the assert fail by changing it to the following, then re-run the test:

    @Test
    public void assertEquals_FormTitleIsYourAccount()
    {
        WebElement yourAccountLabel = driver.findElement(By.className("entry-title"));

        String yourAccountLabelText = yourAccountLabel.getText();

        assertEquals("Text in the 'Your Account' field was not as expected", yourAccountLabelText, "Some dummy text");
    }

Now when the test fails, we get the following message output with some useful feedback:
blogpost4
assertThat
Finally let’s look at another assert called ‘assertThat‘ (my personal favourite!). This one is a little bit more complicated to use than the others that we have seen so far, but it typically reads better and usually provides the most useful feedback in case of failure, so it is well worth learning to use.
Now ‘assertThat’ is not actually included with the standard Junit package. In order to use it, we need to download a new package called the Hamcrest Matchers. Fortunately this is really easy to do through maven, and we simply need to add a new dependency to the pom.xml file. Go ahead and open that file, and add the following:

<dependencies>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.43.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-all</artifactId>
            <version>1.3</version>
        </dependency>

</dependencies>

Now we are going to check that the footer at the bottom of the page contains the string ‘Splashing Pixels’. Look up the CSS Selector for the footer with FirePath:
blogpost5
The CSS selector will be ‘#footer_nav>p‘. Go ahead and write the following test:

    @Test
    public void assertThat_FooterContainsCertainText()
    {
        WebElement footerLaber = driver.findElement(By.cssSelector("#footer_nav>p"));

        String footerLabelText = footerLaber.getText();

        assertThat(footerLabelText, containsString("Splashing Pixels"));
    }

The only new bit of code here is ‘assertThat’ and ‘containsString’:

assertThat(footerLabelText, containsString("Splashing Pixels"));

You will need to statically import both of the above methods. For some reason in my IDE, I find that I need to manually statically import assertThat and containsString. To do so, I simply add the following lines to the top of my test class:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;

Go ahead and run the test. It should pass. Now let’s make the test fail and see what happens. Change the code to the following and run the test again:

    @Test
    public void assertThat_FooterContainsCertainText()
    {
        WebElement footerLaber = driver.findElement(By.cssSelector("#footer_nav>p"));

        String footerLabelText = footerLaber.getText();

        assertThat("Error in the footer text", footerLabelText, containsString("Some dummy text"));
    }

Now you will get a nice informative error message telling you exactly what the problem is:
blogpost6We covered some very useful ground in this post. Assertions are a critical part to writing good automation tests, and you should be asserting for multiple elements at every stage of your automated testing to ensure robustness in your tests. You never know where a test is going to fail, and if some unexpected behaviour occurs at any point then you want to be made aware of it.