Selenium considerations | C#

Jordan Mace
4 min readFeb 28, 2021

It’s been roughly four years since I began my career in UI test automation using Selenium in C#. Over this time, I’ve played a role in the construction of a number of frameworks for various different web applications.

Selenium has a well documented set of best practices, and they offer very detailed explanations for why engineers should or should not write tests in a particular way. In this article, I’m going to take a deeper look at some of these best practices, as well as mention a few other features in the C# bindings. This is to assist those starting out in this area and even those who are building a framework now.

Avoid Sleeping

Let’s say that we’re testing a React page. It’s a login page, and has an external login provider (for example, sign in via Google). We have been tasked with testing to ensure this external provider button works. We begin writing the test case, but notice that this button can take anywhere from two to five seconds to appear on the page. No worries, we simply add a five second Thread.Sleep and go on with our day.. right?

There should never be a need for Thread.Sleep in Selenium code

One problem with this scenario is that if our UI developers add a performance fix the very next day to make this button load in 500ms then suddenly we’ve blown out the test execution time for seemingly no reason. The other problem is that Selenium has actually already resolved this problem for us..

If you’re using the C# bindings of Selenium, check out the ImplicitWait found on the WebDriver.

The WebDriver already supports implied waits

Effectively, the ImplicitWait is just Selenium polling every 100ms or so to wait for the element to be visible when FindElement is used. This is ideal as it won’t always need to wait the maximum specified time, like in Thread.Sleep

Idempotency is key

This means that I should be able to run a single test multiple times and get the exact same results. I should never, ever have to run the previous test so that the test data is created. Alternatively, I should never build tests in such a way that they must be run in a particular order.

Idempotent tests do not rely on anything.

When diagnosing test failures, the last thing I want is to be led down a completely separate path because five of my tests are failing instead of one. If tests rely on each other, all it takes is one failure to start a domino effect.

Add your own functionality

Selenium is a one-size-fits-all library. In every test framework I have seen, extensions have been made to Selenium to ensure it fits our requirements. I encourage everyone to go through the documentation, read through the GitHub repo and familiarize yourself with the inner workings of the C# bindings of Selenium.

With React and other JS frameworks becoming more prevalent, it poses a challenge to those writing the web tests. Selenium cannot just find a React component by the text it contains out of the box.

If only..

I have found that by writing these extension methods my own understanding of Selenium has grown exponentially. Digging through the GitHub files to find out what an ISearchContext is to actively monitoring the Slack channel has been an excellent learning experience.

Finally, a word on flakiness

A major pain to diagnose, ‘flakey tests’ give the test engineer zero confidence that a legitimate bug can be found. A flakey test is simply a test that randomly fails once every x executions without making any changes to the code. If the tests fail at the drop of a hat, how can we trust them?

Flakey tests can be caused by a number of things. Added a new asynchronous call in the background? Accidentally deleted one of your testing users from the DB? Trying to locate an element and they’ve gone and changed the id?

Using ImplicitWait can help manage asynchronous waits, but only to an extent, and only if you’re using FindElement. For page loads, I would recommend using the PageLoad property (shown in the screenshot above).

--

--

Jordan Mace
0 Followers

Quality Coach | Shift-Left, Automation