Index:
Page Object Model
Wrapper Methods and classes
Extent Reports
Topic 1: Page Object Model
Design Patterns
Design Patterns
What is it?
Design patterns are standard, optimal solutions to common problems that occur in software design.
Where is it used?
They are used in all kinds of software development where common problems need to be solved efficiently and maintainably.
Advantages of Design Patterns
They provide proven solutions for recurring problems.
They are reusable and can be applied to many different scenarios.
They improve code readability and maintainability.
They facilitate communication between developers by providing a common vocabulary.
Page Object Model (POM)
What is it?
The Page Object Model is a design pattern in Selenium that creates an object repository for web UI elements.
Where is it used?
It's used in Selenium for improving test maintenance and reducing code duplication.
How is it used? (bulleted steps)
For each web page in the application, create a corresponding Page Class.
This Page Class will identify the WebElements of that web page and also contains Page methods which perform operations on those WebElements.
public class LoginPage { private WebDriver driver; @FindBy(id = "username") private WebElement usernameField; @FindBy(id = "password") private WebElement passwordField; @FindBy(id = "loginButton") private WebElement loginButton; public LoginPage(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); } public void login(String username, String password) { usernameField.sendKeys(username); passwordField.sendKeys(password); loginButton.click(); } }
Takeaways / best practices
Design patterns help in structuring code in an efficient and reusable manner.
The Page Object Model improves test maintainability and reduces code duplication. Each page class should correspond to a page in the web application.
In the POM pattern, it's important to remember that the page class doesn't contain assertions. It only contains the interaction methods with the page.
Always name the methods in the Page Class meaningfully, so they represent business operations.
Page Factory
Need for Page Factory
What is it?
Page Factory is a class provided by Selenium WebDriver to support the Page Object design pattern, and it's used for lazy initialization of WebElements.
Where is it used?
Page Factory is used in Selenium test automation scripts when following the Page Object Model.
How to use Page Factory
Create a constructor of the page class and inside the constructor use the initElements method to initialize all WebElement instances defined.
public class LoginPage { private WebDriver driver; @FindBy(id = "username") private WebElement usernameField; public LoginPage(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); } }
Page Factory Annotations
What is it?
Page Factory Annotations are used to describe the locators of the WebElements in a convenient way.
Where is it used?
Page Factory Annotations are used with Page Factory in Selenium WebDriver scripts.
How is it used? (bulleted steps)
The @FindBy annotation is used to identify elements.
@FindBy(id = "username") private WebElement usernameField; @FindBy(name = "password") private WebElement passwordField;
Takeaways / best practices
Using Page Factory can make your Page Objects cleaner and easier to read and maintain.
Page Factory uses the @FindBy annotations for cleaner and more readable code.
Be mindful that using Page Factory may lead to null pointer exceptions if an element is not found on the page, as it's only when you interact with the element that it's actually searched for in the DOM.
Make sure all WebElements in a Page Class are declared as 'private' for encapsulation. The Page Class should provide the methods to interact with the WebElements, which should be hidden from test classes.
Always initialize the Page Factory elements in the constructor of your Page Class.
Topic 2: Wrapper Methods and classes
Wrapper Methods
Wrapper Methods
What is it?
Wrapper methods are functions that are created to perform common tasks that can be used repeatedly in the code, providing an additional layer of abstraction to existing methods.
Where is it used?
Wrapper methods are often used in the context of Selenium for operations such as clicking a button, setting text in a field, getting text from a field, etc. These actions can be wrapped into simple methods like clickButton(), setText(), getText(), etc.
Process Flow of Wrapper Methods
Define the wrapper method that contains the common code functionality.
Call the wrapper method in your test code.
Wrapper Class for Primitive Data Types
What is it?
Wrapper classes in Java provide a mechanism to convert primitive into object and object into primitive.
Where is it used?
Used whenever data needs to be converted from its primitive type to an object and vice versa.
How is it used? (bulleted steps)
Integer myInt = 5; // auto-boxing int myPrimitiveInt = myInt; // auto-unboxing
Need for Wrapper Class
They convert primitive data types into objects. Objects are needed if we wish to modify the arguments passed into a method (because primitive types are passed by value).
The classes in java.util package handles only objects and hence wrapper classes help in this case also.
Data structures in the Collection framework, such as ArrayList and Vector, store only objects (reference types) and not primitive types.
An object is needed to support synchronization in multithreading.
Function Overriding in Java
What is it?
Function overriding is a feature in Java that allows a subclass or child class to provide a specific implementation of a method that is already provided by its parent class or superclass.
Function Overriding VS Wrapper Methods
Function overriding is about providing a new implementation for an existing method in a subclass. A wrapper method, on the other hand, is about creating a new method that makes the use of an existing method easier, more convenient, or safer.
Takeaways / Best Practices
Wrapper methods provide a level of abstraction that can make your code easier to use and read.
Function overriding should be used when a method in a subclass should do everything the superclass method does and more, or when the subclass method needs to provide a completely different implementation.
Always remember to add @Override annotation above the method in the subclass when overriding a method from the superclass, to make the code easier to understand and prevent errors.
Topic 3: Extent Reports
Test Reports
Need of Test Reports
What is it?
Test reports are comprehensive documents that provide an overview of testing activities, including the number of tests run, the number of passed and failed tests, and detailed information about each test.
Where is it used?
Test reports are used across all levels of software testing processes to provide stakeholders with information about the quality and readiness of the product.
Ways of Reporting Test Results
Manual reports: Manually created in a document or spreadsheet.
Automated reports: Generated by testing tools/frameworks such as JUnit, TestNG, Extent Reports, etc.
What is Extent Report?
What is it?
Extent Report is an HTML reporting library for .NET and Java which is extremely easy to use and creates detailed test result reports in HTML.
Where is it used?
It's used to create beautiful, interactive, and detailed reports for test execution results.
Integrating Extent Report with TestNG
Add Extent Reports dependencies to your project.
Initialize the Extent Reports in the @BeforeSuite or @BeforeTest method.
Create a test report entry using createTest method.
Use log method to provide detailed step information.
In @AfterMethod, use getStatus method to check for test status and log it.
Flush the reports in @AfterSuite.
//1, 2 - Add ExtentReports dependency and initialize ExtentReports ExtentReports reports = new ExtentReports(); //3 - Create a test report entry ExtentTest test = reports.createTest("MyFirstTest", "Sample description"); //4 - Log steps test.log(Status.INFO, "This step shows usage of log(status, details)"); //5 - In AfterMethod if (result.getStatus() == ITestResult.FAILURE) { test.log(Status.FAIL, "TEST CASE FAILED IS " + result.getName()); // to add name in extent report test.log(Status.FAIL, "TEST CASE FAILED IS " + result.getThrowable()); // to add error/exception in extent report } else if (result.getStatus() == ITestResult.SKIP) { test.log(Status.SKIP, "Test Case SKIPPED IS " + result.getName()); } else if (result.getStatus() == ITestResult.SUCCESS) { test.log(Status.PASS, "Test Case PASSED IS " + result.getName()); } //6 - Flush the report reports.flush();
Screenshots in Reports
In case of a failed step, capture the screenshot.
Save it to a location and document the path.
Use addScreenCaptureFromPath method to attach a screenshot to the report.
String screenshotPath = System.getProperty("user.dir") + "\\Screenshots\\" + tr.getName() + ".png"; File f = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(f, new File(screenshotPath)); test.fail("details", MediaEntityBuilder.createScreenCaptureFromPath(screenshotPath).build());
Takeaways / Best Practices
Always generate test reports for all your test executions, they're critical for understanding the health and readiness of your product.
Make sure your reports are clear, readable and include all necessary details. Extent Reports is a great tool for this.
Include screenshots in your reports for failed tests. It provides visual evidence of what went wrong and can help in debugging.
All the best and Happy Learning!
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article