In today’s newsletter we are going to discuss
SOLID Introduction
Single Responsibility Principle(SRP)
Open Closed Principle(OCP)
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
SOLID Introduction
SOLID is a popular set of design principles that are used in object-oriented software development. SOLID is an acronym that stands for five key design principles
S - Single Responsibility Principle (SRP)
O - Open-Closed Principle (OCP)
L - Liskov Substitution Principle(LSP)
I - Interface Segregation Principle
D - Dependency Inversion Principle
Single Responsibility Principle(SRP)
SRP states that a class should have only one reason to change.
The SRP principle promotes better organization, readability, and maintainability of your Selenium test automation code. It allows you to manage responsibilities independently and facilitates code reuse.
First we will see the example where SRP is not ben followed.
Without SRP
In the above example, all aspects of the login process (interactions, assertions, and verifications) are handled within a single test case. This approach violates the SRP because the test case has multiple responsibilities.
With SRP
LoginPage.java
LoginTest.java
In this above improved example, we've separated the login page interactions into a loginPage.java class, adhering to the SRP. The test case LoginTestSRP.java focuses solely on the high-level test steps, making the code more modular, maintainable, and adhering to the SRP.
Open Close Principle (OCP)
OCP states that classes, modules or functions should be open for extension but closed for modification.
We can achieve the OCP by designing test scripts to be extensible without changing their core logic.
Lets say we have below LoginPage and LoginTest class to Test Login functionality of a website.
LoginPage.java
LoginTest.java
Lets say we want to add Tests for multi factor authentication(MFA).
In non OCP way, we might be tempted to modify existing LoginPage or LoginTest class.
This violates Open Closed Principle because we are modifying existing code.
To adhere to OCP, we should create new class extending LoginPage and LoginTest without modifying existing code as shown below.
MFALoginPage.java
MFALoginTest.java
Liskov Substitution Principle
LSP states that objects of a superclass should be able to be replaced with objects of a subclass without affecting the correctness of the program
First we will see the example where LSP is not ben followed.
Without LSP
Lets say we have base class WebElelement Handler for handling web elements.
And we have two sub classes Button Handler and Textfield Handler which handles buttons and text field differently, violating LSP.
WebElementHandler.java
TextHandler.java
ButtonHandler.java
With LSP
In the above example button Handler or text handler do not override or change the behavior of methods defined in the base class, WebElementHandler adhering to LSP.
By this way we can use the instance of subclasses interchangeably without affecting the correctness of the program.
Interface Segregation Principle
ISP states that classes should not be forced to implement interfaces they don't use.
We can achieve this by creating small, more focused interfaces to implement.
Lets say we have an interface having methods to do all operations of Webdriver.
Opening URL
Type Text
Click Element
Close Browser
Find element
Find elements
In Non ISP way, lets say if we implement this interface on LoginPage, we only need first 5 operations violating ISP.
Without ISP
IWebDriverActions
LoginPage.java
With ISP
INavigationActions - small more focused interfaces
LoginPage - implementing only required interfaces
In the above example, we have divided the big interfaces into small, more focused interfaces. By this way LoginPage will only implement those interfaces which are required.
Dependency inversion principle (DIP)
DIP states that High-level modules should not depend on low-level modules. Both should depend on abstractions.
First we will see example without adhering to DIP
Without DIP, you might directly instantiate and use the specific WebDriver implementation, like ChromeDriver, in your test class.
In this approach, the test class (LoginPage
) directly depends on the concrete implementation (ChromeDriver
). If you want to switch to a different browser, you would need to modify this class, violating the DIP.
With DIP
To adhere to DIP, you would introduce an interface (e.g., IWebDriver
) that abstracts the behavior of the WebDriver. Then, implement this interface for specific browsers.
IWebDriver
Implement the interface for ChromeDriver.
Now, your LoginPage can depend on the IWebDriver
interface, not on any specific implementation:
By adhering to DIP, your LoginPage is decoupled from the specific WebDriver implementation. You can easily switch between different browser implementations (e.g., Chrome, Firefox) without modifying the LoginPage
, making your code more flexible, maintainable, and adherent to SOLID principles.
"Success seems to be connected with action. Successful people keep moving. They make mistakes, but they don't quit." —Conrad Hilton
Let’s Connect on Social Media
Connect with me on LinkedIn (6.2K+ Followers) and Twitter.