I noticed quite an interesting trend while I was using my Google-fu to up my Selenium skills, everyone who is serious in the test automation space has a “Selenium tips and tricks” blog post floating around on the internet. So b.ignited couldn’t stay behind, and this post was born.
The first tip is perhaps the most important one. Make sure that Selenium is the tool that you need to get the job done. If you are sure that Selenium is your only hope, then keep reading.
Reinventing the wheel is never a good thing. This is also a thing for Selenium, so the first thing I suggest is checking out frameworks that are based on Selenium. If they fit your needs, then they will make your work easier and faster to accomplish. An example of such framework is Selenide.
Now onto the real tips and tricks
Page objects are a popular design pattern within the Selenium community. I’m a fan of this because it promotes code deduplication and thus leads to less test maintenance, providing that your page objects are robust. In my opinion, writing your own custom framework does not excuse you from using this pattern, as it can be used in 99% of cases. The idea behind page objects is hinted at by the name itself, it has to do with mentally dividing your user interface in separate pages. Usually a clear division in pages can be seen when navigating the UI. Then you take these pages and extract the elements that you are likely to use for your tests such as buttons for example, and add these to your page object. Once all paths to important objects are added to the page you can start with adding functions to work with these objects. A clear advantage becomes visible here, if a developer decides to change one button, then the tester has to obviously make the same change in the tests. With a page object, these changes are condensed to one file and hopefully one line. The same applies for functions or methods that you have added to your page object.
Imagine that you open a webpage and there’s a loading bar just sitting there for a while before the actual data you want to test is loaded. How will you handle this, a hard-coded wait? That’s not a good idea. Selenium has different ways to wait on certain things to happen, There’s of course hard-coded waits, also called explicit waits, but we have already established that this is a bad idea. Then there’s another way of waiting, which is an implicit wait. Pick an object of that you want to test and wait until it is visible on the page. Or even better, if the loading bar is used all over the UI, wait until the loading bar has disappeared. Important here is to not start mixing implicit and explicit waits in your code. One might creep in like a cancer and must be stopped at all costs. Do you see a wait that doesn’t belong in a pull request of your colleague? Decline, or set the status to ‘needs more work’.
Just as with waits, there are different types of locators you can use to find an element on your page. The ones you can use may differ from project to project, depending on how the pages under test are built. My advice is to pick one of 8 available types, stick with it, and include it in a style guide, if your project has one.
XPath is my personal favorite of the bunch though not technically the best locator. Your personal favorite may differ from mine, and that’s okay if you apply it correctly and consistently. Perhaps one day a dedicated piece on locators might even find its way to a blog near you, since going into the nitty gritty details is out of scope for this post.
The runner that is used in conjunction with Selenium usually supports parallelism. This is extremely handy when the project you are working on is expected to be a big one. Selenium tests are usually slow, so every test you write will add a bunch of time to the pipelines. This could start to hamper development or deployments when people have to wait for a CI pipeline that takes hours to complete. My advice is to use the runner (JUnit, nUnit, xUnit, …) and tag tests properly so that you have a bunch of sets you may run. A set for regression tests, a set that is marked for parallel execution and a set for serial execution, as there will always be some tests that cannot be run in parallel for various reasons. You can then, for example, run all tests each night, and smaller sets thorough the day when pull requests have to be approved and work needs to be done quickly.
I’m of the idea that when you glance over a codebase, it should be almost immediately clear where things are and how they work, in broad strokes. The first thing to take into account is to follow the standards set forth of the programming language you’re using to write your tests. Then you can start splitting your tests into different folders using the UI as a template and discerning how files will be separated in folders. For example, a page with multiple tabs on top may all be in the same folder. Naming convention is also quite important, this especially plays a big role when the UI is in a language different to English. Do you translate those terms to English to use them as variable or function names? Discuss this within the team and especially the developers since they might have faced the same issue, it makes sense to then implement the same idea and stick with it. This is certainly another rule that should be enforced quite strictly by means of pull requests.
Just because your test will be automated doesn’t mean that a test plan is not useful. I would opt to still have some sort of test plan, perhaps not as in depth and with a pure manual test, as your code for your automated test should be so readable that it could be used to base a manual test on. These test plans are not only handy for you, but could help future people that need to maintain and expand these tests.
Never forget that Selenium is also a protocol that is just implemented by the WebDriver, and thus has its protocol documentation freely available to peruse on the internet. Feel free to take a look here. It could give you some ideas of methods you never thought existed, It’s quite technical, though. https://www.w3.org/TR/webdriver/
Finally, I would like to stress that not everything needs to be automated. Always do a cost-benefit analysis to check. Does a certain test take 2 minutes to do manually, but takes 2 weeks to automate? Leave that test alone and don’t automate it.