Test code phần lớn được tạo ra bởi con người và cho con người sử dụng, trước khi nó được biên dịch và thực thi nhiều lần bởi máy tính, giúp giải phóng sức người và tăng tính hiệu quả công việc. Con người (developer, reviewer) đối diện với test code với tần số rất lớn. Đôi khi con số lên đến hàng trăm lần trong suốt vòng đời của test code, lắm test code dễ đọc, dễ hiểu nhưng cũng có những test code phải nỗ lực cật lực mới có thể đọc hiểu được nó là gì. Sau tất cả thì chúng ta thấy rằng "Test code được viết trước tiên là cho con người"
Test code được tạo ra cho chính mình
Trước tiên test code được tạo ra cho chính mình!
Để có những dòng test code trước khi chúng ta “bấm nút” chạy, thì liệu test code ta viết ra đầu tiên cho ai? Chắc chắn rằng đầu tiên nó được viết ra là cho bản thân người viết trước (chính mình). Vì họ chính là người viết nó sau đó kiểm tra lại tính đúng đắn, debug để đảm bảo yêu cầu đặt ra đã được hiện thực đầy đủ và chính xác.
Chúng ta dùng một ngôn ngữ lập trình cụ thể chẳng hạn: PHP, Java, Python hay JavaScript để hiện thực kịch bản của test case. Nếu không có lỗi nào về cú pháp thì cơ bản máy tính sẽ biên dịch thành mã máy và thực thi nó một cách dễ dàng.
Để dễ hiểu. Chúng ta xem qua ví dụ sau:
Viết test case với yêu cầu như sau: Mở Chrome browser và truy cập trang google.com.vn
. Nhập vào ô tìm kiếm từ khoá automation testing
. Bấm search/enter sau khi nhập xong để xem kết quả trả về của google.com.vn
. Click vào liên kết đầu tiên của kết quả trả về. Xác nhận xem ở trang chi tiết có chữ automation testing.
Developer sau bước làm rõ yêu cầu, chọn testing framework,… là bước tiến hành viết test code.
Mở Notepad++ lên và gõ ra hàng loạt dòng code:) đó là kết quả của thao tác trí tuệ của tư duy máy tính
describe('Test code được tạo ra cho chính mình', () => {
before(() => {
require('expect-webdriverio').setOptions({ wait: 5000 });
});
it('Truy cập google.com.vn và nhập từ khóa tìm kiếm', () => {
browser.url('https://www.google.com.vn');
$('input[type="text"]').addValue('automation testing');
browser.keys('\uE00C');
$('input[type="submit"]').click();
$('*=Automation Testing').click();
expect(browser).toHaveTitleContaining('Automation Testing');
});
});
Như vậy đến đây chắc bạn cũng đồng ý rằng test code ta viết ra đầu tiên là đáp ứng nhu cầu con người (chính developer) chứ không phải là cho máy tính. Do đó chúng ta nên viết test code một cách tinh gọn và hiệu quả
Con người cũng là những người debug line-by-line test code
Test code là kết quả từ thao tác trí tuệ của developer, phần lớn khi mới viết ra không thể bao quát (cover) hoặc đáp ứng hết tất cả khía cạnh của yêu cầu.
Đôi khi những tình huống phát sinh lỗi ở giai đoạn implement hoặc giai đoạn maintain mà không thể tìm ra nguyên nhân lỗi trong nháy mắt. Lúc này, chúng ta sẽ debug line-by-line để hiểu chuyện gì xảy ra với test code. Một lần nữa test code được con người sử dụng mở mức độ line-by-line. Developer sẽ rất chán nản hoặc làm việc kém hiệu quả nếu đối diện với test code “tồi” (code không có tiêu chuẩn) và công cụ hỗ trợ nghèo nàn :(
Để gia tăng tính hiệu quả của quá trình debug, chúng ta nên lựa chọn IDE, framework và software architecture phù hợp ngay khi bắt đầu triển khai; vì chúng sẽ giúp việc debug dễ dàng, thân thiện và tốn ít thời gian nhất.
Dự án Garoon's automated e2e sử dụng thư viện log4js để tạo ra "log message" thân thiện. Sử dụng là PhpStorm IDE: Viết và debug test code. Đồng thời tổ chức source code theo folder-by-feature structure giúp dễ dàng mở rộng, dễ dàng mở rộng test case, cũng như dễ dàng trong việc tìm kiếm test spec khi maintain
Con người cũng là những người maintain test code
Test code do con người maintain
Maintain là một sự tất yếu trong phát triển phần mềm
Dự án automation testing cũng là dự án phần mềm. Phần lớn thời gian của developer là maintain source code. Công việc maintain code chiếm khoảng 80% trong khi viết mới chỉ chiếm 20% trong tổng số thời gian trong suốt chu kỳ sống của phần mềm.
Maintain là công công việc cũ nhưng vai trò mới
Developer chẳng thể nhớ nổi những đoạn code mà họ mới viết dù vài ngày trước đó một cách chính xác. Theo thời gian, 1 tháng, 2 tháng hoặc xa hơn, khi họ quay lại và những dòng code mà chính họ viết ra cũng không còn quen thuộc như ngày đầu. Nên rất may mắn nếu chúng ta maintain project mà nó viết ra ưu tiên cho con người
Đặt mình vào người maintain sau này khi viết test code
Theo tôi, test code được gọi là “chất” là bất kỳ developer nào cũng có thể hiểu được: nó làm gì? Mà không cần một tài liệu hay người viết giải thích lại.
Test code không có đặc trưng cá nhân trong đó, tức là sau một thời gian đối diện với test code ta không nhận ra source code đó là mình viết hay đồng đội viết cho đến khi xem git log. Khi chúng ta viết test code với góc nhìn người maintainer chúng ta sẽ viết những dòng code dễ hiểu như: từ khai báo biến; phân chia function; hoặc module hóa bài toán, cho đến chọn giải thuật dễ hiểu nhất với mọi người
Những điểm nhỏ nhất nên tuân thủ khi viết test code
Để hiểu được dòng code làm gì thì chắc chắn khi viết ra phải tuân thủ các quy chuẩn về code. Rất nhiều quy tắc nhưng quy tắc Single responsibility là kinh điển và cần tuân thủ trong mọi test code.
- Test code viết tối nghĩa sẽ là ác mộng với chính mình và người tiếp nhận sau này
- Sử dụng công cụ, phương thức giúp việc con người maintain hiệu quả (GIT, SVN, Bitbucket)
Con người cũng là những người review test code
Ở bước review, test code cũng được con người sử dụng
Tại Cybozu tất cả cái gì có yếu tố “code” để merge vào codebase cần được review bởi thành viên khác trong team. Đây là công việc theo tôi khá thú vị và tốn kém thời gian vì reviewer đọc hiểu từng dòng code làm gì và cả phải nội suy lẫn debug khi cần thiết. Thường công đoạn review test code chiếm khoảng 30% của thời gian implement hoặc hơn.
Nếu những dòng code tối nghĩa, về cơ bản reviewer cố gắng cật lực cũng có thể hiểu nó làm gì. Nhưng tôi tin rằng người review sẽ thấy mệt mỏi và cáu gắt với những dòng code như thế này. Đôi khi nó trở nên ác mộng đối với họ và có những tranh luận không hồi kết giữa developer và reviewer.
Để nhất quán trong quá trình implement và review source. Cybozu developer tuân thủ theo "Cybozu coding standard", nó được đúc kết và tài liệu lại từ "phi ngôn ngữ lập trình" tới từng ngôn ngữ cụ thể như JavaScript; PHP...
Nhưng cũng có một thống nhất khá thú vị ở bộ phận đó là nếu implement và review tranh luận không đi đến thống nhất quan điểm thì quan điểm của người review sẽ được chọn (review là người sáng suốt hơn :))
Reviewer sử dụng test code nên chúng ta cố gắng viết ra test code trọng tâm:
- Mỗi test code viết ra chỉ giải quyết một việc duy nhất
- Đơn giản nhất để hiểu về test code, đồng nghĩa là chúng ta ưu tiên dùng những thuật toán phổ biến và sử dụng rộng rãi ở cộng đồng IT. Hoặc những library đã được unit test được cung cấp miễn phí
- Test code không mang phong cách cá nhân, văn hoá và quốc gia. Ví dụ: Dù là thành viên Việt Nam hay Nhật Bản viết ra test code. Nó đều mang một phong cách toàn cầu, bất kỳ thành viên nào trong đội lập trình cũng hiểu cũng có thể review nó một cách thuận lợi.
Thông thường mỗi công ty sẽ có một tiêu chuẩn để đánh giá chất lượng test code, tại Cybozu cũng vậy test code sẽ tuân theo bộ tiêu chuẩn của dự án cần triển khai test code (tức là production code)
Để test code thuyết phục reviewer
- Khi review source code, thông thường tôi đọc qua tổng thể source code để nắm bắt tổng quan chương trình, sau đó tới đi vào mức module, function và cuối cùng là dòng code. Nếu những dòng code không tự nó nói lên là nó làm gì thì rất khó để người review đọc hiểu và “đóng dấu thông hành”. Thời buổi này rất hiếm những người review tận tâm như: Mở tài liệu đặc tả test case để xem kịch bản là gì? sau đó mới xem qua test code.
- Test code “chất lượng” là test code tự giải thích nó làm gì. Nó có một nhiệm vụ để tồn tại và cũng một lý do để mất đi
Một dòng code rõ ràng tự giải thích sẽ giá trị hơn một dòng code tối nghĩa và kèm theo dòng giải thích quanh nó.
Con người quyết định số phận test code
Theo thời gian để bắt kịp thời đại, có những "tính năng" phần mềm không còn phù hợp sẽ bị loại bỏ khỏi chương trình. Lúc này test code cho tính năng đó cũng chịu chung số phận, không có gì quá xa lạ với những developer làm công việc maintain những sản phẩm lâu năm của công ty.
Điều gì sẽ xảy ra nếu test code
rối rắm, dàn trải rộng khắp trong project với cả nghìn file source code
được thiết kế theo monolithic
. Và cật lực mới hiểu nỗi test code nào cho tính năng bị bỏ đi, nếu chúng ta không cẩn thận có thể dẫn đến sai lầm (degrade source code). Đến đây bạn cũng thấy rằng test code
cũng được con người sử dụng và quyết định số phận, không phải máy tính quyết định số phận test code
.
Để dễ dàng trong việc đọc hiểu và ra quyết định, chúng ta nên chọn một cách triển khai hợp lý. Cybozu VN đang triển khai theo hai điểm chính:
- Mỗi
test spec
độc lập, test đúng một kịch bản duy nhất hay nói cách khác “có một lý do để tồn tại cũng chỉ có một lý do để xoá đi” - Dùng
folder-by-feature structure
để triển khai test spec.
Ví dụ:changing-message-by-sender.spec.js
Tên spec tự nói nó test điều gì. Phần mở rộng cho biết nó có vai trò gì (.spec) và sử dụng ngôn ngữ (.js) nào để triển khai. Về folder-by-feature structure chúng ta có thể xem ví dụ bên dưới để có thể hình dung tổng quát. (trích lại từ trang: stackexchange.com)
com.example
├── pet
│ ├── Pet.java
│ ├── PetController.java
│ ├── PetRepository.java
│ └── PetService.java
├── user
│ ├── User.java
│ ├── UserController.java
│ ├── UserRepository.java
│ └── UserService.java
│ // and everything else in the project
└── MyApplication.java
Thay vì cấu trúc theo dạng Folder-by-type như truyền thống
com.example
├── domain
│ ├── User.java
│ └── Pet.java
├── controllers
│ ├── UserController.java
│ └── PetController.java
├── repositories
│ ├── UserRepository.java
│ └── PetRepository.java
├── services
│ ├── UserService.java
│ └── PetService.java
│ // and everything else in the project
└── MyApplication.java
Máy tính chỉ là một công cụ hỗ trợ
Mỗi ngày, CI (Tích hợp liên tục) chạy test code lên đến hàng trăm lần. Tại Cybozu cũng vậy, mỗi khi production code thay đổi, ngay tức thì MÁY TÍNH sử dụng test code thực thi cho ra kết quả trong ít phút, để đảm bảo chất lượng phần mềm không bị suy yếu (degrade). Điều này đã và đang mang lại giá trị thời gian, công sức rất lớn với cho nhân viên.
Vậy test code có là lợi thế mà không đội manual test nào làm nổi. Test code giúp giải phóng sức người rất lớn để chúng ta có thời gian tập trung vào giá trị cao hơn.
Thông qua máy tính, test code giúp đảm bảo các tính năng cũ vẫn hoạt động đúng giúp release nhanh hơn và mang lại giá trị trực tiếp đến khách hàng giúp công ty tăng sức cạnh tranh.
Đến đây chúng ta hiểu rằng test code là viết cho con người trước tiên nhưng sau đó phải nhờ đến máy tính thực thi nó nhiều lần khi có nhu cầu. Máy tính là công cụ là trợ thủ đắc lực mà chúng ta không thể thiếu. Do đó một cỗ máy mạnh mẽ giúp ích rất nhiều, rút ngắn thời gian chạy test thông qua parallel testing.
Con người + công cụ = mã nguồn hiệu quả
Sức khỏe tinh thần và thể chất tốt là yếu tố rất thuận lợi để thao tác trí tuệ hoạt động tạo ra mã nguồn hiệu quả (là mã nguồn đạt clean code, hoạt động đúng yêu cầu, chi phí phù hợp)
Ngoài yếu tố con người, các công cụ IDE, lib, frameworks đóng góp rất nhiều vào việc tạo ra mã nguồn hiệu quả
Ví dụ: Nếu chúng ta dùng notepad++ độ hiệu quả sẽ không bằng khi dùng Webstorm, PhpStorm để triển khai test code.
Lời kết
Test code trong lĩnh vực test automation nói riêng và rộng hơn là source code trong lĩnh vực software nói chung là VIẾT CHO CON NGƯỜI TRƯỚC TIÊN do đó chúng ta nên
lấy người maintain làm trọng tâm trong mọi dòng code được tạo ra
Từ nhận định trên chúng ta sẽ đầu tư vào dự án test automation một cách có chiến lược từ kỹ năng code đến những công cụ hỗ trợ. Bên trên là một số trường hợp test code được con người sử dụng và cũng là đối tượng đầu tiên sử dụng nó.
Tư duy "Test code được viết trước tiên là cho con người" giúp mỗi developer trưởng thành hơn cũng như hướng đến lập trình viên toàn cầu. Theo thời gian, tư duy này cũng tạo được một team đầy tính teamwork từ đó dẫn dắt project lớn mạnh và giàu tính maintainable