Hello mọi người, tiến độ viết xong chuỗi 5 bài về design pattern trong Automation test nhanh hơn mình nghĩ, hôm nay mình sẽ hướng dẫn mọi người apply Facade Pattern vào trong code Automation test giúp code của mọi người mướt mườn mượt hơn nhé.
Đặt vấn đề một chút nhé. Đây là class testcase bài trước chúng ta vừa code:
package browserStackSetup;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackSetup {
WebDriver driver;
BrowserStackHomePage objBrowserStackHomePage;
BrowserStackSignUpPage objBrowserStackSignUpPage;
@BeforeTest
public void setup() {
driver = DriverFactoryManager.getBrowserDrive("FIREFOX");
driver.get("https://www.browserstack.com/");
}
@Test(priority = 1)
public void navigate_to_homepage_click_on_getstarted() {
objBrowserStackHomePage = PageFactoryManager.getHomePage(driver);
objBrowserStackHomePage.veryHeader();
objBrowserStackHomePage.clickOnGetStarted();
}
@Test(priority = 2)
public void enter_userDetails() {
objBrowserStackSignUpPage = PageFactoryManager.getSignUpPage(driver);
objBrowserStackSignUpPage.veryHeader();
objBrowserStackSignUpPage.enterFullName("TestUser");
objBrowserStackSignUpPage.enterBusinessEmail("TestUser@gmail.com");
objBrowserStackSignUpPage.enterPasswrod("TestUserPassword");
}
@AfterTest
public void afterTest() {
driver.quit();
}
}
Đây là class testcase mà chúng ta đã apply 2 design pattern là Page Object Model và Factory Design Pattern vào rồi, trông cũng đã khá gọn và clear hơn rồi đúng không ạ? Nhưng bây giờ giả sử ở một testcase khác chúng ta lại muốn implement testcase đăng ký tài khoản tiếp thì sao ? Lại đi bê đoạn code trong hàm enter_userDetail() đi sang testcase khác sao ? Cái này rõ ràng lại vi phạm nguyên tắc không duplicate code rồi. Vậy phải làm sao đây ? Thì thế mới có bài blog hôm nay chứ hihi. Thôi vào việc nào.
Định nghĩa và ví dụ
Trong ngữ cảnh của Automation test, Facade Pattern có thể được hiểu là chúng ta sẽ xây dựng các lớp trung gian để tập hợp các step kết hợp tạo thành một testcase để tái sử dụng sau này.
Ví dụ bạn có thể testcase đăng ký
Ở HomePage bạn có step click vào btn Đăng ký tài khoản
Ở SignUpPage bạn có các step input username, password,.. và nhấn SignUpBtn
Nếu không có Facade class trung gian thì trong class testcase bạn sẽ gọi hêt các step ở trên để tạo thành class testcase ( như đoạn code ở trên ).
vào ví dụ luôn nhé, mình vẫn sẽ dùng 2 class quen thuộc ở các bài trước: BrowserStackHomePage và BrowserStackSignUpPage.
Giả sử bạn đang viết test case cho một trang web với các hành động sau:
- Vào homepage
- Click vào btn đăng ký tài khoản
- Điền các thông tin cần thiết và nhấn đăng kí
Thay vì thực hiện từng bước trong mỗi test case, bạn có thể sử dụng Facade Pattern để gói gọn các hành động này trong một lớp, giúp mã dễ đọc và tái sử dụng.
2 class PageObject vẫn giữ nguyên không có gì thay đổi
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class BrowserStackHomePage {
WebDriver driver;
By Header=By.xpath("//h1");
By getStarted=By.xpath("//*[@id='signupModalProductButton']");
public BrowserStackHomePage(WebDriver driver) {
this.driver=driver;
}
public void veryHeader() {
String getheadertext=driver.findElement(Header).getText();
assertEquals("App & Browser Testing Made Easy", getheadertext);
}
public void clickOnGetStarted() {
driver.findElement(getStarted).click();
}
}
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class BrowserStackSignUpPage {
WebDriver driver;
By Header = By.xpath("//h1[contains(text(), 'Create')]");
By userName = By.xpath("//*[@id='user_full_name']");
By businessEmail = By.xpath("//*[@id='user_email_login']");
By password = By.xpath("//*[@id='user_password']");
public BrowserStackSignUpPage(WebDriver driver) {
this.driver = driver;
}
public void veryHeader() {
String getheadertext = driver.findElement(Header).getText().trim();
assertEquals("Create a FREE Account", getheadertext);
}
public void enterFullName(String arg1) {
driver.findElement(userName).sendKeys(arg1);
}
public void enterBusinessEmail(String arg1) {
driver.findElement(businessEmail).sendKeys(arg1);
}
public void enterPasswrod(String arg1) {
driver.findElement(password).sendKeys(arg1);
}
}
Giờ ta tạo class Facade gói gọn các hành động cho việc Signup tài khoản vào trong class này nhé
package facade;
import org.openqa.selenium.WebDriver;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackFacade {
private WebDriver driver;
private BrowserStackHomePage objBrowserStackHomePage;
private BrowserStackSignUpPage objBrowserStackSignUpPage;
// Khởi tạo Facade với các trang cần dùng
public BrowserStackFacade(WebDriver driver) {
this.driver = driver;
this.objBrowserStackHomePage = new BrowserStackHomePage(driver);
this.objBrowserStackSignUpPage = new BrowserStackSignUpPage(driver);
}
// thực hiện sign up account
public void performSignUpAccount(String username, String password, String businessEmail) {
objBrowserStackHomePage.veryHeader();
objBrowserStackHomePage.clickOnGetStarted();
objBrowserStackSignUpPage.veryHeader();
objBrowserStackSignUpPage.enterFullName(username);
objBrowserStackSignUpPage.enterBusinessEmail(businessEmail);
objBrowserStackSignUpPage.enterPasswrod(password);
}
}
Mọi người có thể thấy mình đã gom tất cả step để tạo account vào một hàm
Ok giờ sửa sang class testcase nhé
package browserStackSetup;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackSetup {
WebDriver driver;
BrowserStackFacade browserStackFacade;
@BeforeTest
public void setup() {
driver = DriverFactoryManager.getBrowserDrive("FIREFOX");
driver.get("https://www.browserstack.com/");
browserStackFacade = new BrowserStackFacade(driver);
}
// @Test(priority = 1)
// public void navigate_to_homepage_click_on_getstarted() {
// objBrowserStackHomePage = PageFactoryManager.getHomePage(driver);
// objBrowserStackHomePage.veryHeader();
// objBrowserStackHomePage.clickOnGetStarted();
// }
@Test(priority = 2)
public void enter_userDetails() {
browserStackFacade.performSignUpAccount("testabc","234567","a@test.com");
}
@AfterTest
public void afterTest() {
driver.quit();
}
}
Gọn hơn hẳn đúng không ạ hihi
Lợi ích khi áp dụng Facade Pattern
Code đơn giản dễ hiểu: Thay vì viết từng bước như vào home, click signup, điền thông tin…,trong class testcase ta chỉ cần gọi hàm performSignUpAccount().
Dễ maintain: Khi có thay đổi về logic (ví dụ: cần thêm bước xác thực OTP), bạn chỉ cần thay đổi trong class Facade mà không phải sửa toàn bộ test case.
Reuse code: Sau khi người số lượng testcript tăng sẽ có nhiều testcase được tái sử dụng lại rất nhiều trong các quy trình nghiệp vụ
Ẩn đi sự phức tạp: Test case sẽ tập trung vào kiểm thử chức năng thay vì phải quản lý các bước chi tiết của quy trình.
Kết luận
Trong các dự án automation lớn, Facade Pattern giúp tạo ra các quy trình kiểm thử chung một cách dễ dàng và hiệu quả, giúp các test case tập trung vào logic kiểm thử thay vì phải quan tâm đến từng bước thực hiện chi tiết.