Trong bài viết trước, tôi đã trình bày các kỹ thuật áp dụng Unit testing vào các thành phần AngularJS: Controller, Filter, Service và Directive thông qua các ví dụ minh họa đơn giản. Bài viết này sẽ đi sâu vào thực hành áp dụng Unit testing vào quá trình phát triển một ứng dụng AngularJS cụ thể, theo phương pháp TDD (Test Driven Development).
Nội dung trình bày
Áp dụng Unit testing vào phát triển ứng dụng
Mô tả ứng dụng minh họa
Giả sử chúng ta cần xây dựng chức năng quản lý sách (bookmgr) cho một ứng dụng chia sẻ sách trực tuyến (bookspot). Để tiện cho việc trình bày, chúng ta chỉ xây dựng chức năng quản lý sách rất đơn giản, bao gồm một danh sách liệt kê các đầu sách đang quản lý, mỗi đầu sách có 3 thông tin: tiêu đề, phân loại và giá tiền. Giao diện danh mục sách có dạng như sau:
Khi người dùng bấm vào nút Add, ứng dụng sẽ hiển thị Form nhập liệu rỗng để thêm mới một đầu sách:
Nếu người dùng bấm vào nút Edit tương ứng một đầu sách, ứng dụng sẽ nạp thông tin đầu sách vào Form chỉnh sửa:
Cuối cùng, khi người dùng bấm vào nút Delete, ứng dụng sẽ xóa đầu sách tương ứng khỏi danh sách.
Ví dụ minh họa điều gì?
Với ví dụ này, tôi muốn nhấn mạnh đến vấn đề: “chúng ta hãy sử dụng Unit testing song hành trong suốt quá trình xây dựng ứng dụng bằng AngularJS”. Kiểm thử trước, không phải là viết hết mã lệnh kiểm thử rồi mới lập trình chức năng, mà cần hiểu theo nghĩa dùng mã lệnh kiểm thử xen kẽ với mã lệnh chức năng (nhưng tách biệt nhau) để làm rõ và điểu hướng (drive) từng chức năng cần lập trình.
Thực hành phát triển ứng dụng minh họa
Ví dụ minh họa được tạo sẵn theo trình tự: tạo Unit testing đồng thời với quá trình phát triển chức năng của ứng dụng. Mỗi bước thực hiện được đánh dấu dưới dạng một branch trong cấu trúc mã nguồn Git. Các bạn không chỉ tải toàn bộ mã nguồn cuối cùng để chạy, mà còn có thể checkout từng bước của quá trình thực hiện để đối chiếu, so sánh và rút kinh nghiệm.
Tải mã nguồn ví dụ
Tải ví dụ minh họa “AngularJS BookSpot SPA Example” theo địa chỉ dành cho git clone (Lưu ý các bạn đừng tải bản nén vì bản nén chỉ chứa mã nguồn cuối cùng, trong khi chúng ta cần xem xét và so sánh mã nguồn tại các bước khác nhau trong quá trình phát triển ứng dụng).
Sau khi tải xong ví dụ bằng lệnh git clone, chuyển vào thư mục example-angularjs-bookspot-form, thực hiện lệnh git fetch để đồng bộ các branch từ remote:
Xong lệnh này, mã nguồn ví dụ minh họa đã sẵn sàng. Chạy lệnh sau để cài đặt các gói thư viện cần dùng cho Unit testing:
$ npm install karma karma-jasmine karma-chrome-launcher --save-dev
Sau khi npm cài đặt xong các gói thư viện trên, chạy thử Unit testing bằng lệnh:
$ karma start karma-unit.conf.js
Mở một cửa sổ dòng lệnh khác, cũng chuyển vào thư mục example-angularjs-bookspot-form, sau đó cài đặt các gói thư viện cần dùng cho HTTP Server:
$ npm install connect serve-static --save-dev
Sau khi npm cài đặt xong các gói thư viện trên, chạy thử HTTP Server bằng lệnh:
$ node server
Mở cửa sổ trình duyệt mới, mở trang web có địa chỉ http://localhost:3000, ta được giao diện sau:
Chuyển đổi các giai đoạn mã nguồn
Kho mã nguồn Git cho phép đánh dấu mã nguồn tại một số thời điểm trong quá trình phát triển. Để thuận tiện cho việc theo dõi, tôi đã đánh dấu mã nguồn tại các bước thực hiện (sẽ được giải thích trong phần tiếp theo). Khi clone mã nguồn về, thư mục dự án sẽ chứa mã nguồn mới nhất. Tuy nhiên, các bạn có thể nạp lại mã nguồn tại một bước trong các bước đã được đánh dấu.
Liệt kê danh sách các “đánh dấu” bằng lệnh git branch -a như sau:
Nạp mã nguồn tại một bước trong quá trình phát triển, chẳng hạn đổi mã nguồn về giai đoạn viết xong kiểm thử hàm createBook() dùng để tạo mới một đầu sách (mới viết lệnh kiểm thử, chưa viết chức năng hàm createBook() nên kiểm thử bị fail), ta sử dụng lệnh git checkout createbook-fail như sau:
Các bước thực hiện xây dựng ví dụ
Dưới đây là danh sách các nhãn đánh dấu các bước của quá trình phát triển ứng dụng minh họa. Các bạn hãy chạy Karma đồng thời checkout mã nguồn tuần tự theo các bước từ trên xuống và xem xét mã nguồn của các tệp bookmgr.js và bookmgr.Spec.js.
- empty-project: Chuẩn bị thư mục dự án (chưa có các tệp bookmgr.js, bookmgr.Spec.js và index.html).
- source-files: Tạo tệp mã nguồn javascript và html
- listbooks-fail: Viết kiểm thử cho hàm listBooks()
- listbooks-pass: Lập trình chức năng cho listBooks()
- loadeditform-fail: Viết kiểm thử cho hàm loadEditForm()
- loadeditform-pass: Lập trình chức năng cho loadEditForm()
- editform-html: Bổ sung giao diện HTML
- canceleditform-fail: Viết kiểm thử cho hàm cancelEditForm()
- canceleditform-pass: Lập trình chức năng cho cancelEditForm()
- saveeditform-fail1 & saveeditform-fail2: Viết kiểm thử cho hàm saveEditForm()
- saveeditform-pass: Lập trình chức năng cho saveEditForm()
- createbook-fail: Viết kiểm thử cho hàm createBook()
- createbook-pass: Lập trình chức năng cho createBook()
- updatebook-fail: Viết kiểm thử cho hàm updateBook()
- updatebook-pass: Lập trình chức năng cho updateBook()
- deletebook-fail: Viết kiểm thử cho hàm deleteBook()
- deletebook-pass: Lập trình chức năng cho deleteBook()
- bootstrap-theme: Áp dụng Boostrap-Theme làm đẹp giao diện
Tôi sẽ trình bày và giải thích tuần tự từng bước trong buổi Workshop. Trong bài viết này không tiện giải thích chi tiết, mong các bạn thông cảm.
Kết luận
Qua bài viết này, hy vọng các bạn trải nghiệm được phương pháp sử dụng Unit testing để phát triển ứng dụng AngularJS. Với cách làm này, bạn không cần phải liên tục nhìn vào giao diện của chức năng đang phát triển để kiểm tra tính đúng đắn của nó. Mặc dù việc viết mã lệnh kiểm thử có thể tạo cảm giác quá trình phát triển chậm chạp, tuy nhiên khi đã quen với cách làm này, bạn sẽ thấy đây là cách làm “chậm mà chắc”. Điều quan trọng là sau này khi bạn chỉnh sửa hoặc phát triển thêm tính năng vẫn có thể kiểm tra ngay các tính năng cũ vẫn hoạt động đúng thông qua Unit testing.
P/S: Bài tiếp theo sẽ phát triển tiếp chức năng kết nối dữ liệu trong RESTful WebService cho ví dụ minh họa trên.