How to use the Factory design pattern to create browser instances: the simple approach
We face one problem trying to apply the multi-browser test approach: the complexity to create the browser instance.
In this article, I will show you the regular browser creation, how we can improve this, and a solution using the Factory design pattern.
Using Selenium WebDriver, we need to instantiate the browser class and inform its driver. The browser drivers are maintained as third-party plugins, and you can find them here. The only exception is the Safari driver.
Let’s say you want to run a test using Google Chrome. We have the following code:
Using Firefox, we have the following:
The problem using this approach
There’s one main problem using this basic example wherein can see on line 5 in both: the addition of the driver path.
It is not wrong after all, it’s the first way to use it. The problem is that you will do either one or another (I also have seen both):
- adding the driver path in a generic folder
- adding the resource path and pushing the driver within your code
The second one is the worst approach ever from my perspective, so do not do that.
The Factory design pattern
I have no intention to explain the Factory design pattern as we have tons of excellent articles and books. If you do not know this pattern, I would recommend reading this article.
The basic implementation is to have a class factory that will look into the browser you would like to create to run your tests and instantiate the browser with the configurations you want.
In the following diagram, the factory implementation is the
DriverFactory class the browser configuration is the classes with
DriverFactory class has a method createInstance that receives the browser name as String to create the correct browser instance. We can instantiate the browser-based on either an
if-else statement or
switch-case. To bring it more legibility, try to always to for the
- Line 5 upper case the browser value to map it to the
BrowserListenum t enable us to use it in the
- Lines 10, 13, 16, 19, 22, and 25 create the driver instance based on the matching browser
- Line 28 throws an exception if the browser value is not valid or recognized
- Line 33 is the internal browser enumeration
Browser Manager classes
You noticed that the browser instance is using a custom class. We could directly use the driver class in the
switch-case, like this:
Instead, we are using the
ChromeDriverManager that manages the browser driver using WebDriverManager to solve the problem mentioned at the beginning of this article and creates the browser instance.
It can be a better approach to keep your
DriverFactory class clean and with only one responsibility where the driver manager classes contain any additional code to each required browser as starting it maximized or changing any specific configuration.
Each driver manager class implements the
Factory interface to have consistent implementation of the browser creation. When you open the other classes you will see the same method being used, but the different driver and browser usage.
How to use this approach
You might have a BaseTest class to manage the test pre and postconditions. You need to inform the preconditions of the browser you need to use, passing it as a parameter to the DriverFactory class. The code would look like this:
BaseWeb class above is an example to you understand who we can use it. I would not recommend you hardcode the browser. You can find a more elegant example getting the browser from a config file looking at this class.
A complete example
You can navigate to the following GitHub repo to see a complete and functional example like the one described in this article. I would recommend you to read the README file to understand a little bit more about the architecture, libraries in use, and the implementation.
What to do next?
Now it is your turn to get your hands dirty and try to create this approach. I would say to follow these steps:
- Create a
DriverFactoryclass with an internal browser enumeration
- Add the
switch-casestatement and add all the cases
- Implement only one
caseto create a browser instance
- Create a simple test class and use the
DriverFactorymethod to create the
WebDriverinstance with a hardcoded browser
- If everything is working as expected, proceed to the next steps, otherwise review this article
- Create browser manager class and refactor the
DriverFactoryclass to use it
- If it is still working, do the same for the other browser you would like to implement
Do not forget you can see an example in the mentioned GitHub repo.