Folder-by-feature structure: Cấu trúc tổ chức mã nguồn e2e testing quy mô lớn

Folder-by-feature structure: Cấu trúc tổ chức mã nguồn e2e testing quy mô lớn

Xem nhanh

Khi bắt đầu triển khai dự án e2e testing, có lẽ chúng ta ít quan tâm về việc xây dựng structure dự án sao cho kiểm thử có khả năng mở rộng (scalable testing) và kiểm thử có thể bảo trì (maintainable testing) với suy nghĩ hiện tại ít test case hoặc chuyện này là của tương lai, v.v.

Sau quá trình thực nghiệm ở Cybozu Vietnam với nhiều lần điều chỉnh tốn không ít cost của nhóm mới có một cách tổ chức source code hiệu quả. Do đó trong bài viết này, tôi sẽ chia sẻ một mô hình tổ chức source code tên là folder-by-feature structure được áp dụng vào dự án Garoon’s e2e testing.

Qua bài viết này với hy vọng có thể giúp các bạn mới tìm hiểu về tự động hóa kiểm thử có cái nhìn khách quan hoặc đang gặp vấn đề trong tổ chức source code có thêm giải pháp tham khảo.

Khi Garoon e2e testing áp dụng folder-by-type structure

Lùi thời gian một tí, Cybozu vào thời điểm đầu triển khai dự án Garoon's e2e testing, cách tổ chức mã nguồn được thiết kế dựa trên các components (hoặc góc độ triển khai gọi là 4 tầng kỹ thuật) được định nghĩa trước gồm: Page Objects, Test Specs, Test dataTesting flow. Cách tổ chức này gọi chung là: folder-by-type. Nhìn xa hơn ra cộng đồng chúng ta có thể thấy MVC Folder Structure cũng là một điển hình cho folder-by-type structure Cấu trúc của Garoon’s e2e testing source code ban đầu được thiết kế như Hình 1.0 bên dưới

Tổng quan Garoon's e2e testing tổ chức theo folder-by-type structure

Hình 1.0: Tổng quan Garoon's e2e testing tổ chức theo folder-by-type structure

Với cách tổ chức như Hình 1.0. Chúng ta nhìn từ "layer" ngoài vào trong (bắt đầu từ acceptance folder) thì structure đang được chia thành 4 folders chính (cấp 1):

  1. pages: chứa tất cả pages của tất cả module cần test của Garoon application
  2. test-data: chứa tất cả test data của tất cả module cần test của Garoon application
  3. test-flows: chứa tất cả testing flows của tất cả module cần test của Garoon application
  4. test-scripts: chứa tất cả test script (hay test spec) của tất cả module cần test của Garoon application

Trong mỗi folder chính (pages, test-data,…) chúng ta sẽ tiếp tục được phân cấp nhỏ hơn theo từng ứng dụng cần triển khai auto test. Ví dụ:

  • Các page objects liên quan tới ứng dụng memo sẽ được đặt trong folder pages/memo
  • Các test scripts của ứng dụng memo sẽ được đặt trong folder test-scripts/memo

Memo | Cybozu Garoon là một ứng dụng của sản phẩm Garoon, cho phép người dùng có thể lưu trữ lại các ghi chú của cá nhân (giống ứng dụng Notes trên Macbook).

Với cách tổ chức source code này, mọi thứ vẫn ổn, mọi người trong đội phát triển vẫn miệt mài thêm vào test case mà chưa thấy phàn nàn nào.
Theo thời gian, khi số lượng test case đã lên tới hàng trăm (chưa tới hàng ngàn), thì lúc này cấu trúc trên bộc lộ một số nhược điểm:

  • Phân mảnh source code rộng khắp trong project
    Khi thêm mới một test case. Developer sẽ "bối rối" vì không biết phải phân bổ: test data ở đâu, test spec ở đâu và page object ở đâu, … một cách nhanh chóng. Lúc này họ phải tìm hiểu lại tài liệu hướng dẫn, hoặc phải "lùng sục" toàn bộ cấu trúc folder trong dự án để nắm bắt nguyên lý sau đó phân bổ phù hợp.
  • Rủi ro tăng quy mô mở rộng dự án
    Khi xóa bỏ một test case nào đó đã implement trước đây. Tương tự như thêm mới, chúng ta phải xác định được test script, page objecttest data,… nó nằm ở đâu (vì các thành phần này đang được phân bổ ở các nơi khác nhau trong khắp dự án). Sau đó tiến hành xóa bỏ cẩn thận từng thành phần một hoặc những nghiệp vụ riêng của test case bị xóa, thật chắc chắn và "tỉnh táo" để tránh xóa nhầm test data của test case khác; theo tôi việc xóa bỏ khá áp lực, và không kém gì thêm mới.
  • Tối nghĩa và test code không hướng đến con người
    Khi maintain test case, test module,… trong dự án test automation.
    Khi cần đọc source code hoặc tìm test spec để “confirm” một tình huống nào đó, chúng ta không thể định vị chính xác test spec nào là cái chúng ta đang cần; cho đến khi chúng ta phải mở test spec lên và xem nội dung bên trong nó. Điều này làm giảm hiệu suất và động lực làm việc của developer.

    Nếu chúng ta cần fix bug cho test code hoặc improve source code hiện tại cũng như áp dụng cải tiến công nghệ cho một module nào đó. Điều này sẽ trở nên phức tạp hơn, vì các thành phần của ứng dụng đó được đặt ở nhiều nơi khác nhau, dài trải.
    Ví dụ: khi thay đổi việc tổ chức source code cho module Memo sang folder-by-feature structure ta phải tìm và làm việc trên tất cả các tầng của dự án như: pages/memo, test-flows/memo, test-data/memo, test-scripts/memo

Với một số nhược điểm vừa kể trên. Với kiểu thiết kế folder-by-type structure, nó sẽ phù hợp với dự án có lượng test case ít (dưới 100 test case). Tuy nhiên, một khi sản phẩm phần mềm đã quyết định là cần triển khai automation testing, điều đó có nghĩa là sẽ có nhu cầu mở rộng liên tục về test case, do đó test code cũng sẽ tăng theo.

Nên, khi đã quyết định triển khai automation testing dù hiện tại số lượng test case ít (dưới 100 test case, chỉ một loại test), thì chúng ta cũng nên luôn nghĩ rằng dự án tăng lên hàng ngàn test case, hoặc mở rộng nhiều loại test thì chuyện gì sẽ xảy ra? Từ đó chúng ta chọn một cấu trúc phù hợp để có thể nhẹ nhàng khi mở rộng quy mô.

Khi Garoon's e2e testing áp dụng folder-by-feature structure

Sau khi implement nhiều test case và nhiều người (ngoài team xây dựng nền tảng) tham gia vào dự án Garoon e2e testing. Mọi người trong team nhận thấy được một số nhược điểm của kiểu thiết kế folder-by-type. Nhược điểm này lớn tới mức team quyết định “Muốn đi tiếp buộc phải dừng lại”.

Đúng vậy team xây dựng nền tảng của Garoon's e2e testing quyết định “tái cấu trúc dự án”. Sau khi tìm hiểu và tham khảo các đồng đội. Chúng tôi quyết định tổ chức toàn bộ mã nguồn từ source code hiện tại đến tương lai theo folder-by-feature structure (hiện tại tiếp tục triển khai automation testing cho mobile web application). Và ngoài ra, cũng kết hợp những ưu điểm từ kiểu thiết kế folder-by-type.

Vậy hình dáng của kiểu thiết kế folder-by-feature như thế nào, nó có lợi ích ra sao, chúng ta cùng tham khảo chi tiết bên dưới

 folder-by-feature structure

Hình 2.0: folder-by-feature structure

Với thay đổi ở trên, ta sẽ thấy rõ 2 điểm khác biệt giữa folder-by-feature structurefolder-by-type structure như sau:

  1. Với folder-by-feature structure: Chúng ta sẽ tổ chức source code dựa theo ứng dụng và ưu tiên theo tuần tự: module test → hành vi cần test (behavior) → sự cô lập (isolation) giữa các module, test component và test case nhất có thể

  2. Tất cả những file của riêng test case sẽ tổ chức về cùng với nhau: Như vậy test scripttest data của mỗi test case sẽ nằm cùng folder với tên folder đại diện là tên hành vi nó sẽ test.
    với 3 đặc tính:

    • Toàn bộ data để của test case, bao gồm các thông tin như: file test spec, test data, credentials, các file tĩnh để upload,… được kết thúc với .data.js trong đó .data phản ánh vai trò của nó
    • Tên folder của test case cần phản ánh về mục đích (hoặc hành vi) của test case sẽ thực hiện, ví dụ:
      Test case thêm mới một memo cho module Memo → Tên folder nên là: adding-memo
      Test case xóa một memo cho module Memo → Tên folder nên là: deleting-memo
    • File test spec có thêm extension là .spec.js để dễ dàng định danh vai trò của file đó so với các *.js file còn lại trong folder. Ví dụ:
      Test case thêm mới một memo cho module Memo:
      File test spec: adding-memo.spec.js
      File test data: adding-memo.data.js

Ưu điểm của folder-by-feature structure

Ưu điểm của folder-by-feature structure đó chính là:

  • Các ứng dụng hoặc module sẽ độc lập với nhau, việc maintain một ứng dụng nào đó sẽ trở nên dễ dàng hơn vì giữa các module hoặc ứng dụng không có hoặc rất ít kết dính với nhau.
    Ví dụ: khi muốn loại bỏ ứng dụng memo ra khỏi dự án Garoon’s e2e testing, ta chỉ cần xóa nguyên folder memo, mà không sợ bị ảnh hưởng tới các ứng dụng khác. Hay việc refactor 1 ứng dụng nào đó, thì chỉ ảnh hưởng trong phạm vi của ứng dụng đó mà thôi.
  • Maintain dễ dàng vì test spectest data cũng như những file liên quan mật thiết đều nằm trong cùng 1 folder, với tên file phản ánh tên nghiệp vụ và vai trò tham gia của nó. Do đó các member mới khi tham viết test case sẽ không bị bối rối về việc test data nên đặt ở đâu

Tuy nhiên, với việc phân bổ source code theo folder-by-feature structure, nó cũng rất dễ gây rối structure, do đó trước khi dự án bùng nổ về test case chúng ta nên đưa ra những quy ước cho việc đặt tên folder của test case như: độ dài, camel case hoặc snake case, …

Hiện tại dự án Garoon’s e2e testing của Cybozu đã triển khai theo kiến trúc folder-by-feature structure và đang nhận được các phản hồi tích cực từ các Cybozu's developers.

Kết bài

Với tư duy “Test code is real code“, structure cũng chính là một phần khá quan trọng trong việc xây dựng dự án e2e testing. Với một structure phù hợp, được đầu tư bài bản, nó sẽ là 1 nền móng vững chãi để dự án của bạn có thể phát triển lâu dài và ngày càng mở rộng.

Các bài viết cùng chủ đề