Breaking changes in Selenium and how we handled them
December 29, 2017
During the regression phase of a particular product update release, our QA team at Qualita reported an issue: all the mouse actions were not working with Selenium 3.6.
During the regression phase of a particular product update release, our QA team at Qualita reported an issue: all the mouse actions (MouseHover, MouseUp, MouseDown) were not working with Selenium (SE) version 3.6+. We investigated and found that inside mouse actions in the Qualitia engine code, we used Locatable APIs. These Locatable APIs had recently been refactored and deprecated by Selenium community in SE 3.6+ and the community recommended the use of Actions API, which Selenium has supported since SE 3.0+.
The primary challenge moving forward would be maintaining backward compatibility with Selenium versions in Qualitia (at least post SE 3.0). We have users using various SE 3.x versions, so we had to fix this issue in Qualitia 5.0 in a way that would work across all the SE 3.x versions. We also figured that Locatable is a primitive way of accessing mouse actions, so the community was forced to move to Actions API and didn't care refactoring them, which caused breaking changes. After brainstorming, we came up with a few approaches as solutions for this issue:
Potential Solution 1: The obvious solution was to replace Locatable package statements with new package structure statements introduced in SE 3.6 and compile the code with SE 3.6. The code would have successfully compiled, but would have thrown runtime exception for those mouse actions since Java wouldn't find the package structure in earlier versions, so we dropped this solution.
Potential Solution 2: Use Locatable APIs and write code to handle Mouse actions in Selenium version in an agnostic way. The idea was, if mouse actions fail at runtime due to unexpected package import, catch that exception (i.e. a user running a pre-SE 3.6 version) and explicitly call the pre-SE 3.6 package structure.
The pseudo would look something as follows:
try
{
//SE 3.6 handling
Locatable driver = (Locatable) webDriver;
Mouse mouse = driver.getMouse();
mouse.click(getCoordinates());
}
catch(RunTimeException e)
{
//SE 3.6- handling
com.newstructure.Locatable = (com.newstructure.Locatable) webDriver
Mouse mouse = driver.getMouse();
mouse.click(getCoordinates());
}
But this version-specific exception based code and using deprecated Locatable didn’t look clean and promising. We moved on to the next approach.
Solution 3: Use Actions API. Since Actions API is supported post 3.0+, it was very safe to use them. Moreover, the SE community recommends their use over the primitive way of using Locatable mouse action. In this way we achieved backward comparability. There was almost no impact on the user since for him, Qualitia mouse action name and parameters remained the same (although technically parameter got ignored in the latest API but that doesn't break anything for user hence, we ignored that to go ahead with the current release).
The takeaway from this process is that, since the SE community will keep on adding breaking changes and introducing new APIs, we should strive to keep our code future proof and backward compatible as much as possible. Writing quality software is a tough job, especially when the environment surrounding you is constantly evolving.