Screenplay pattern là gì? Khác gì với Page Object

Screenplay và Page Object Model là 2 patterns dành cho Automation Test. Dạo gần đây, screenplay nổi lên như cồn, nên mình đú trend, viết 1 bài để khái quát những đặc điểm của mô hình này.

I. Screenplay Pattern là gì?

Screenplay, tiếng anh có nghĩa là kịch bản, nên nhiều người hay chém gió “dùng screenplay có nghĩa mình là nhà soạn kịch“.

Nó là 1 design pattern phục vụ cho automation test, có thể áp dụng cho 2 level API và UI. Nguồn gốc của nó từ bác John Ferguson Smart, một người chuyên đi dạy về agile, tập trung vào BDD.

Bác ý có 1 framework tên là serenity bdd, nó support 3 cách làm việc khác nhau:

  • Page Object
  • Cucumber
  • Screenplay

Vậy nên bạn đừng nhầm lẫn screenplay là serenity và ngược lại. Screenplay là 1 design pattern thể hiện 1 cách viết test. Còn serenity bdd là 1 framework cho Automation Test.

Giờ đây screenplay đã có mặt trên 3 framework khác nhau

II. Mô hình của Screenplay, so sánh với Page Object.

Hình mình tự vẽ lại cho có màu xanh :v

Bạn nào đọc được tiếng anh thì có thể đọc hướng dẫn và giới thiệu về screenplay ở đây.

Mô hình Page Object:

1. Tất cả xoay quanh Actor

Trong mô hình này, trung tâm của nó là Actor. Vì sao nó lại có actor??? Actor là đại diện cho 1 người dùng thật, nó xuất phát từ story trong agile. Và đó cũng là điểm khác biệt mấu chốt giữa Screenplay và Page Object. Actor sẽ là người đứng ra làm mọi việc, điều này dễ hiểu hơn là việc gọi method từ pageA rồi pageB.

Ví dụ:

17 Useful user story examples to get you started - Justinmind
copy image from https://www.justinmind.com/blog/user-story-examples/

Code mẫu copy từ trang gốc:

@RunWith(SerenityRunner.class)
public class AddNewTodos {

    private Actor james = Actor.named("James");

    @Managed
    private WebDriver hisBrowser;

    @Steps
    private PlaceholderText thePlaceholderText;

    private DisplayedItems theDisplayedItems = new DisplayedItems();

    @Before
    public void jamesCanBrowseTheWeb() {
        james.can(BrowseTheWeb.with(hisBrowser));
    }

    @Test
    public void should_be_able_to_add_a_todo_item() {

        givenThat(james).wasAbleTo(OpenTheApplication.onTheHomePage());

        when(james).attemptsTo(AddATodoItem.called("Buy some milk"));

        then(james).should(seeThat(theDisplayedItems, hasItem("Buy some milk")));
    }
}
  • Actor has an ability (có thể sử dụng browser, có thể sử dụng api)
james.can(BrowseTheWeb.with(hisBrowser));
//thực chất là khởi tạo webdriver
  • Actor do tasks (task này nhìn dưới góc độ business)
(james).wasAbleTo(OpenTheApplication.onTheHomePage())
(james).attemptsTo(AddATodoItem.called("Buy some milk"))
//thực chất là gọi các method để thực hiện action lên web application
  • Actor ask question
(james).should(seeThat(theDisplayedItems, hasItem("Buy some milk")));
//Thực chất là compare actual và expected

Về bản chất 2 thằng đều giống nhau thôi, nhưng mà Screenplay tạo ra cho nó 1 layer abstraction để nhìn test dưới góc độ business, thay vì gắn chặt vào UI, bạn nào nếu dùng cucumber cũng nhận thấy điểm tương tự.

2. Khác biệt đến từ Task

Task dưới góc độ business sẽ giúp cho chúng ta giữ nguyên được test nếu như UI thay đổi, thực ra thì mình thấy nó cũng không hơn gì method của Page Object. Điểm nó hay hơn, đó là Task này là 1 interface extends từ interface Performable, nó định nghĩa cách làm việc chung cho tất cả các task lớn bé.

public interface Performable extends SkipNested {
    <T extends Actor> void performAs(T actor);
}
  • Task này có thể chứa 1 hoặc nhiều task khác.
  • Khi nhìn vào task, bạn chỉ nhìn thấy business và chỉ khi nào đi đến cái task level cuối cùng, bạn sẽ nhìn thấy interaction, chính là code selenium tương tác với browser (tất nhiên là nó cũng được bọc bên ngoài bằng code khác).

3. Viết test rất giống câu văn

Viết code như là viết văn, với người khác thì là điểm mạnh, với mình thì nó là điểm yếu vcđ, nó luôn làm cho mình phải nghĩ đến ngữ pháp tiếng anh mỗi khi viết code và phải hi sinh java coding convention =)))) Còn bạn thì sao, hãy comment phía dưới nhé.

@Test
public void should_be_able_to_add_a_todo_item() {
     givenThat(james).wasAbleTo(OpenTheApplication.onTheHomePage());
     
     when(james).attemptsTo(AddATodoItem.called("Buy some milk")); 
    
     then(james).should(seeThat(theDisplayedItems, hasItem("Buy some milk"))); 
}

III Để dùng screenplay hiệu quả

1. Về mind-set

  • Bạn phải thấm nhuần tư tưởng của BDD, sử dụng example, story …Tốt nhất là đọc kỹ cuốn BDD in action của ông John.
  • Team bạn phải làm theo phương pháp BDD, nếu không thì người tím lịm chính là người viết test. :v

2. Về kỹ thuật

  • Java core (cực chắc chắn)
  • Bạn phải hiểu và biết cách sử dụng Interface: marker interface và functional interface (lambda expression) và cả interface thông thường.
  • Ngoài ra là Generics, Annotation
  • Bạn nên làm quen với kiểu đẻ class mới như lợn con, vì screenplay tách nhỏ từng thứ, nên viết rất nhiều class. Nếu đơn giản viết một đoạn code 3 dòng selenium mở 1 trang web nào đó thì bên này bạn phải có đến khoảng 3 class. Không nói bạn cũng có thể mường tượng số lượng dòng code gấp khoảng vài lần.

IV. Tổng kết

Nếu bạn thấy hay hoặc không hiểu gì, đừng ngại ngần cho bài viết 1 like. :))) Vì để viết được bài này, tác giả phải làm đôi cái dự án dùng screenplay và đọc code framework ngày đêm. Nếu bạn muốn tác giả phân tích code của framework serenity, hãy để lại 1 comment, tác giả sẽ viết dần (nếu rảnh).

13 thoughts on “Screenplay pattern là gì? Khác gì với Page Object

      • Anh có thể phân biệt Interaction và Task giúp em ko ạ, em thấy 2 thằng này nó khá giống nhau. Em cảm ơn ạ.

        • Interaction –> tương tác với browser
          Task –> tập hợp các interaction hoặc tập hợp các tasks.

  1. Đã đọc qua bài viết. Và nhận xét từ 1 người có làm qua cucumber và chưa làm qua screenplay thì vẫn chưa thấy sự pro hơn hẳn ở đây nhưng cách viết code lại phức tạp hơn nhiều lần.
    Cảm ơn tác giả nhé!

  2. Mong anh làm thêm nhiều bài về Senerity Framework + Cucumber + Screenplay Pattern ạ, đúng thật là dạo gần đây nó rất hot, như là xu thế tương lai vậy ạ, mặc dù từ bài viết này cá nhân em thích POM hơn vì nó ko phải nhớ nhiều đến các keyword của Screenplay, và code của POM cũng đơn giản dễ đọc vs người đã code có tí kinh nghiệm rồi 😀

    Em hóng phần này lắm, em sẽ thường xuyên lên page để hóng các bài viết mới của anh về chủ đề này 😀
    Chúc anh nhiều sức khỏe ạ ^^

    • Khi dùng Serenity thì chọn 1 cách làm việc thôi, cucumber không kết hợp đc với screenplay đâu em. Nếu có viết bài, chắc cũng chỉ viết thêm về screenplay, phân tích FW.
      Dùng POM đơn giản, dễ làm và rất nhiên là dễ làm sai vì mỗi người lại hiểu POM khác nhau.
      Screenplay nó thống nhất cách làm việc nhưng ko dễ cho người mới. Nếu chắc kiến thức java thì cũng chỉ mất vài hôm, nhưng đúng là nó rất rườm rà, code rất nhiều.

Leave a Reply

Your email address will not be published. Required fields are marked *