A three-course menu for writing your Selenium tests before the feature is complete

How many times does this happen: you start a new iteration/sprint; you give estimates; you realize that the testing work will not be complete in the sprint for certain features?

While analyzing the work that needs to be done in a sprint you tend to think in a sequential manner: developers write the code –> only once the code is complete will the testing begin –> the developers are done with their work within the sprint, the testers are not. Strategies, workarounds and intense thought processing are used to determine how to somehow fit the testing work in the sprint, to not allow it to flow over into the next sprint. Is there an alternative? Yes.

When it comes to Selenium tests, here is a “3 course-menu” that provides a solution to this problem, by suggesting how to write these tests before the feature to be tested is even implemented:

Let’s take a deeper look at this menu.

Starters (also known as pre-requisites)

There is no need to wait for the feature to be fully coded before writing tests, especially if you are doing Selenium tests. However you do need a few things, the pre-requisites.

First of all, you must have the requirements clarified. You must understand what it is your developers are implementing. You need to know what the feature is all about. You need to have the definition of the feature.

Based on the requirements, and with the help of this post i wrote on identifying test scenarios, you can identify what scenarios need to be automated, and what the steps of each scenario are. You can have a clear idea of what each scenario represents: what are the steps and the order in which they are done, how the interaction with the feature (in this case the webpages) will be done. You already have an idea of the sequence of interactions that will be done with the page. For example, if let’s say your test means filling in a form, you know that you have some fields in which you need to type something, you know in what order you need to fill in the form, you know that you have a submit button and that submitting the form will trigger another action. You can actually sketch out what the tests do, without bothering about what the selectors behind these steps are. At this point you don’t even have to think about the selectors.

Also, ideally, but this is not always the case, you would have some sort of visual diagram, sketch or wireframe of what the page you will interact with should look like. In case that does not exist, you can make a sketch yourself, just so you can use it as a visual guideline in sorting out your test steps.

Entree (also known as the part where all the hard work is done)

Once you know the test requirements and the scenarios you want to automate, you can start doing just that. Since you know what scenarios need to be automated, this should be an easy process. But a bit different one than how you would normally write tests.

First of all, when it comes to the WebElements needed for interacting with the webpages, you will not have any idea of what selectors (CSS or XPATH) will be used to identify them, since there is no code yet. Therefore, you will still need to write the page object classes, but instead of writing the correct selectors, you will just define WebElements having dummy selectors.

If, let’s say, you would need to fill in a field that requires a nickname, you would do something like:

@FindBy(how = How.CSS, using = "DUMMY") private WebElement nickname;

This way, you are not blocked by not having the actual HTML implemented, since you defined a WebElement (even though dummy), that represents the element you would be interested in. So there is nothing stopping you from writing the code that would interact with this element. The test won’t pass of course, but you can write it in advance.

As a good practice, in fact, the tests you will write will not directly use the WebElement you defined, but instead a getter method for it. Getter methods are nothing more than methods that return the WebElement. You should make the actual element private, and the getter method public, so that you will not be able to call the WebElement directly. In a getter method you can also perform some processing of the WebElement before returning it to the test that uses it. This makes the WebElement definition completely separate from the test code itself, and makes it easier to update the WebElements when needed, without having to make changes in the test code. A simple getter, that does no processing, would look like this:

public WebElement getNickname() {
    return nickname;
}

The test will now use the getter for interacting with the element. In the above example where “nickname” is a field, instead of writing nickname.sendKeys(“someValue”) you would write getNickname().sendKeys(“someValue”).

Having all the required WebElements defined will allow writing the tests. But, there might be some steps in the scenarios where you are not exactly sure of how the page will behave. For example, if you fill in a field with some incorrect data, you could get a different type of warning: either a popup, or an inline error message, or some other behavior. If you are not sure which one of these will be triggered in case of error, you could instead just create another dummy bit of code, a helper method, whose actual code you will write only when this functionality is implemented by the developers. This helper method would be the one that checks that the error has been triggered properly. From the test perspective, you would just replace the bit where you check for the error from inside the test method with a call to a method inside which the whole error checking is done. This way you isolate the error checking.

In order not to have false positives in your tests (and to not forget that the helper method is dummy), you could just write one line of code inside it, that just fails the test. This way, when you are at the step where you are finishing everything up, or when you are running the test, you will realize that the method needs to be looked at. Such a helper method would look something like:

public void checkTheDisplayedError() {
    //TODO - add method code here
    fail("Failing test until the actual method code is written");
}
Dessert (also known as the finishing touches)

Once the feature is fully coded, and the official testing part begins, you are only left with polishing your tests. In the previous step you already did 80% of the automation work. Now you only need to fill in the gaps. You need to add the actual selectors to identify the webElements and write the code for any helping method that you abstracted in the previous step.

After doing this, you will need to run you tests, in order to check that everything is in the right order and that you did not miss any bits of code. Any updates that are required to the code you wrote initially will be done at this step, and once all updates are made, the test is complete and ready to test your fully functional feature.

Advertisements

One thought on “A three-course menu for writing your Selenium tests before the feature is complete”

  1. This is great advice and very similar to approaches that I take. My boss says that I am an anomaly, because I get all my testing done in the sprint. I just write what I can ahead of time and finish when the devs finish coding. I think it is also important to keep in constant communication with my devs and do turnovers and code reviews, so I can understand what they are implementing. We also write in test hooks to the element tags i.e. and then call those using xpath. I am allowed to add these myself to the code and then I can update my page objects at the same time.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s