Nội dung bài viết
I. Vì sao lại cần Loadable Component?
Như trong bài về Page Object mình đã có nói là ta mô hình hóa mỗi page hoặc mỗi phần của 1 page thành 1 object riêng biệt để quản lý, tránh duplicate code. Page Object rất tốt nhưng vẫn còn thiếu 1 chút, đó là cách đồng bộ ready state trước khi làm việc với 1 page hoặc component. Hơi khó hiểu nhỉ?
Hãy nghĩ đến trường hợp này:
- Bạn thường xuyên phải sử dụng WebdriverWait để làm việc với 1 số WebElements, liên tục từ method này qua mehod khác.
- Bạn open 1 page mới nhưng không biết khi nào page mới render xong để bạn có thể sẵn sàng thực hiện action lên nó.
–> Cả 2 trường hợp đều thiếu 1 thứ đó là “1 cơ chế cho ta biết là khi nào page / component đã ở trạng thái sẵn sàng (ready state) để có thể thực hiện actions“
Và đó chính là cái Loadable Component hướng đến, nó cung cấp cho ta 1 cách làm việc chung, phần việc của chúng ta là điền cái điều kiện (condition) để cho biết thế nào là ready state.
II. Cách sử dụng Loadable Component như thế nào
Sơ qua về LoadableComponent:
- LoadableComponent nằm trong package org.openqa.selenium.support.ui. Đây là package có chứa nhiều Classes rất là hữu dụng cho quá trình làm selenium. (Mình sẽ viết thêm các bài về package này sau)
- LoadableComponent là 1 abstract class, trong nó có chứa 3 methods:
- load();
- isLoaded() throws Error
- public get()
Dưới đây là 1 page object có sử dụng LoadableComponent:
Dưới đây là 1 số lưu ý khi implement:
- Class Page Object phải extend từ class LoadableComponent<T extends LoadableComponent<T>>. Trong đó T chính là tên class Page Object.
- Phải Override lại 2 methods: load() và isLoaded().
- Load(): dùng để navigate to page. Nếu áp dụng cho component thì có thể không cần implement gì cả
- isLoaded(): dùng để xác định xem đã ở đúng page hoặc component cần tương tác đã đạt trạng thái ready state hay chưa.
ở trong ví dụ này, mình để điều kiện xác định trang web có được load hay chưa là “URL có chứa keyword practice“
Test file sẽ trông như thế này:
Điều lưu ý duy nhất là sử dụng:
- Nhớ call method get() trong phần Test vì nó sẽ gọi đến 2 method load() và isLoaded()
Bạn cũng hoàn toàn có thể viết thế này:
III. Cơ chế của Loadable Component
Khi get() method được gọi thì nó sẽ:
- Gọi vào method isLoaded(). Mặc dù method isLoaded() giống như trả về Boolean nhưng nó sẽ thực hiện 1 series các Assertions. Bạn có thể add 1 hoặc nhiều Assertions ở trong isLoaded(). Việc thêm assert sẽ giúp có thông tin chuẩn xác hơn khi debug tests.
- Nếu isLoaded() pass –> step (4) —> step (5) –> return về Test method.
- Nếu isLoaded() failed –> sẽ văng ra Error –> nhảy vào Catch block. Ở Catch block sẽ gọi đến method load() step 3. Ở Step 3, sẽ load lại page 1 lần nữa.
- Hết Step 3 –> chuyển sang step 4 –> step 4 mà fail thì Test fail với dòng Assertion mình đã viết ở trong isLoaded().
- Nếu step 4 pass –> step 5 –> return về Test method –> Kết thúc công việc của LoadableComponent.
IV. Tổng kết
Mình nghĩ là LoadableComponent đã cung cấp 1 phương thức làm việc khá hiệu quả mà lâu nay mình không để ý đến. Hi vọng có ích cho bạn khi áp dụng Page Object vào làm Selenium.
[…] ← Previous […]
Anh Giang ơi, cho em hỏi chút về cái .get()
– như bài a viết thì:
PageA comp_1 = new PageA().get();
comp_1.doSomething();
– Nhưng framework em thì tất cả method là static nên ko khởi tạo object như vậy mà gọi luôn:
PageA.doSomething();
vậy có cách nào xài cái get(); này trong framework của em ko a?
Em nên học thêm về OOP để tránh việc viết static cả project như vậy. Các biến của em sẽ dưới dạng static hết và sẽ bị side effect, edit value của 1 biến là tất cả những chỗ sử dụng biến đó sẽ bị ảnh hưởng. Như thế quá nguy hiểm, khi viết code ngta luôn cố gắng độc lập giữa các thành phần (loose coupling), đôi khi còn hướng đến immutable class vì lo sợ giá trị của các biến bị thay đổi.
Class như của em ko thể thừa kế class hay interface nào, do đó không thể phát triển tiếp được. OOP tập trung vào phần object chứ ko phải class.
Dạ thanks anh, em mới vào cty được gần 2 tuần thì phải tiếp nhận project auto đã viết sẵn này. em quan sát thì thấy:
– phần method thì gần như 100% là static
– phần biến của class thì ko có nhiều, nếu có thì nó ở dạng non-static (có thể em chưa xem kĩ hết)
Vậy liệu method static, còn biến của class giả sử ko dùng luôn thì liệu có ổn không a? em đang bị force viết khá nhiều test cases để kịp build, nhưng em cũng suy nghĩ theo hướng OOP như anh nói, vì giờ viết cho kịp build, mốt refactor lại cũng mệt mỏi
Chả làm sao cả, nó chỉ khiến người đọc code cảm thấy confused thôi. Thường thì ngta sẽ remove hoặc ko viết phần ko dùng đến.
Em có thể tiếp tục viết theo hướng đó cho kịp công việc, nhưng về lâu dài thì sẽ rất khó mở rộng (tất nhiên là nếu có nhu cầu mở rộng về mặt tính năng: run parallel, data-driven test hoặc gì đó).