Bạn đang xem bài viết Unit Test Dùng Để Làm Gì Và Kinh Nghiệm Viết Unit Test Tốt Nhất được cập nhật mới nhất tháng 9 năm 2023 trên website Ezlearning.edu.vn. Hy vọng những thông tin mà chúng tôi đã chia sẻ là hữu ích với bạn. Nếu nội dung hay, ý nghĩa bạn hãy chia sẻ với bạn bè của mình và luôn theo dõi, ủng hộ chúng tôi để cập nhật những thông tin mới nhất.
Đâu là sự khác biệt giữa một unit test tốt và dở? Làm thế nào để bạn có thể viết được các unit test tốt? Điều này không được rõ ràng lắm. Thậm chí nếu bạn là một lập trình viên tài ba với nhiều thập niên kinh nghiệm, kiến thức và thói quen hiện tại của bạn sẽ không tự động giúp bạn viết ra được các unit test tốt, bởi vì nó là một dạng khác của lập trình và hầu hết mọi người bắt đầu với giả định sai lầm vô ích về những gì mà các unit test cần phải đạt được.
Hầu hết các unit test mà tôi thấy là khá vô ích. Tôi không đổ lỗi cho các nhà phát triển phần mềm: thông thường, anh ta hoặc cô ta khi được yêu cầu viết unit test, thì họ sẽ cài đặt NUnit và bắt đầu tung ra một loạt các [Test] method. Một khi họ nhìn thấy những đèn đỏ và xanh lá cây, thì họ cho rằng mình đã làm việc đó một cách chính xác. Đó là một giả định tồi! Điều đó rất dễ viết ra những unit test tồi mà thêm rất ít giá trị cho một dự án trong khi lạm phát chi phí thay đổi mã nguồn thì tăng theo cấp số nhân. Điều đó có làm bạn bận tâm?
Unit test không phải dùng để tìm bugVì vậy, nếu bạn đang cố gắng tìm kiếm bug, thì có một cách hiệu quả hơn nhiều đó là hãy chạy toàn bộ ứng dụng với nhau như nó sẽ chạy trong môi trường thực tế, giống như bạn làm công việc kiểm tra thủ công một cách tự nhiên vậy. Nếu bạn tự động hóa kiểu test này để phát hiện những sai sót khi chúng xảy ra trong tương lai, đây được gọi là integration testing và thường sử dụng các kỹ thuật và công nghệ khác hơn là unit test. Bạn có muốn sử dụng các công cụ thích hợp nhất cho mỗi công việc không?
Tìm kiếm bug (những thứ không làm việc như bạn muốn)
Kiểm thử thủ công (đôi khi cả kiểm thử tích hợp tự động)
Phát hiện hồi quy (những thứ đang làm việc tốt nhưng đã bất ngờ ngừng hoạt động)
Các kiểm thử tích hợp tự động (đôi khi cũng bao gồm cả kiểm thử thủ công, mặc dù khá tốn thời gian)
Thiết kế các thành phần trong phần mềm mạnh mẽ
Unit testing (trong quy trình TDD)
(Lưu ý: có một ngoại lệ, nơi các unit test rất hiệu quả trong việc phát hiện bug. Đó là khi bạn đang tái cấu trúc code của một đơn vị (unit) nhưng không có nghĩa là để thay đổi hành vi của nó. Trong trường hợp này, các unit test có thể cho bạn biết nếu hành vi của đơn vị (unit) đó có thay đổi hay không.)
Vậy nếu unit test không phải để tìm bug, thì nó để làm gì?Tôi cá là bạn đã nghe câu trả lời này hàng trăm lần rồi, nhưng vì quan niệm sai lầm cố hữu trong kiểm thử cứ treo lơ lửng trong tâm trí của các nhà phát triển phần mềm, tôi sẽ nói lại cái nguyên tắc của nó. Một bậc thầy về TDD đã nói rằng, “TDD là một quá trình thiết kế, chứ không phải là một quá trình kiểm thử”. Hãy để tôi giải thích thêm: TDD là một cách mạnh mẽ trong việc thiết kế các thành phần phần mềm (“units”) tương tác để hành vi của chúng được xác định thông qua các unit test. Tất cả chỉ có vậy!
Những unit test tốt vs dởTDD sẽ giúp bạn cung cấp các thành phần phần mềm hoạt động theo thiết kế của bạn. Một bộ unit test tốt là vô cùng có giá trị: nó là tài liệu thiết kế của bạn, khiến cho việc tái cấu trúc và mở rộng code của bạn được dễ dàng hơn trong khi giữ lại một cái nhìn tổng quan rõ ràng về hành vi của mỗi thành phần. Tuy nhiên, một bộ unit test tồi là vô cùng đau thương: nó chẳng chứng tỏ bất cứ điều gì rõ ràng cả, và có thể làm cản trở nghiêm trọng khả năng tái cấu trúc hoặc thay đổi code của bạn theo bất kỳ cách nào.
Các kiểm thử của bạn nằm ở đâu trên thang mức độ sau?
Ở đầu kia của thang mức độ, các kiểm thử tích hợp (integration test) không biết về cách codebase của bạn được chia nhỏ thành các đơn vị (unit), nhưng thay vào đó nó cho thấy cách toàn bộ hệ thống ứng xử đối với người dùng bên ngoài như thế nào. Chúng có chi phí hợp lý để duy trì (vì không quan trọng việc bạn tái cấu trúc hoạt động nội bộ trong hệ thống của bạn như thế nào, nó sẽ không ảnh hưởng đến hành vi bên ngoài) và chúng chứng tỏ được rất nhiều về những tính năng thực sự làm việc hiện nay.
Bí quyết để viết những unit test tuyệt vờiHãy làm cho mỗi test độc lập với tất cả những phần khác
Bất kỳ hành vi nhất định nào cũng nên được xác định tại một và chỉ duy nhất một test. Nếu không, sau này khi bạn thay đổi hành vi đó, bạn sẽ phải thay đổi rất nhiều test. Các hệ quả của nguyên tắc này bao gồm:
Đừng làm những assertion không cần thiết
Những hành vi cụ thể nào mà bạn đang kiểm thử? Nó sẽ gây phản tác dụng nếu cứ Assert() bất cứ thứ gì mà cũng đã được assert bằng test khác: nó chỉ làm tăng tần suất của những thất bại vô nghĩa mà chẳng cải thiện unit test một chút nào cả. Điều này cũng áp dụng cho việc gọi Verify() không cần thiết – nếu nó không phải là hành vi cốt lõi dưới test đó, thì hãy dừng việc quan sát về nó! Đôi khi, cộng đồng TDD thường diễn đạt điều này bằng cách nói rằng “chỉ có duy nhất một assertion hợp lý trên mỗi test”.
Hãy nhớ rằng, các unit test là một thiết kế chỉ rõ một hành vi nào đó sẽ làm việc như thế nào, không phải là một danh sách các quan sát của tất cả mọi thứ mà phần code đó thực hiện.
Kiểm thử chỉ một unit code tại một thời điểm
Kiến trúc của bạn phải hỗ trợ việc testing units (tức là, các class hoặc mọi nhóm rất nhỏ của các class) độc lập, chứ không phải là tất cả chúng kết lại với nhau. Nếu không, bạn sẽ có rất nhiều chồng chéo giữa các test, vì vậy việc thay đổi một unit ảnh hưởng ra bên ngoài và gây ra thất bại ở khắp mọi nơi.
Nếu bạn không thể làm được điều này, thì kiến trúc của bạn đang làm hạn chế chất lượng công việc của bạn – hãy xem xét sử dụng Inversion of Control.
Giả lập tất cả những dịch vụ và trạng thái bên ngoài
Nếu không, hành vi trong những dịch vụ bên ngoài sẽ chồng chéo lên nhiều test, và trạng thái dữ liệu khác nhau trong mỗi unit test có thể ảnh hưởng đến kết quả của nhau.
Bạn chắc chắn phải nhận một kết quả sai nếu chạy các test của mình theo một thứ tự xác định, hoặc nếu chúng chỉ làm việc khi cơ sở dữ liệu hoặc kết nối mạng của bạn đang hoạt động.
Tránh những điều kiện tiên quyết không cần thiết
(Bằng cách này, tôi sẽ không tính đẩy nhiều điểm dữ liệu thông qua các test tương tự (ví dụ, bằng cách sử dụng các [TestCase] API của NUnit) là vi phạm quy tắc độc lập này. Quá trình test có thể hiển thị nhiều thất bại nếu một cái gì đó thay đổi, nhưng nó vẫn chỉ có một phương pháp test để duy trì, vì vậy điều đó cũng tốt.)
Đừng sử dụng unit test trong phần thiết lập cấu hình
Theo định nghĩa, các thiết lập cấu hình của bạn không phải là một phần của bất kỳ unit code nào (đó là lý do tại sao bạn trích xuất các thiết lập ra khỏi code của unit của bạn). Ngay cả khi bạn có thể viết một unit test để kiểm tra cấu hình của mình, nó chỉ đơn thuần buộc bạn phải xác định cấu hình tương tự tại một vị trí dự phòng bổ sung. Xin chúc mừng: nó chứng tỏ rằng bạn có thể copy và paste!
Cá nhân tôi coi việc sử dụng những thứ như các filter trong chúng tôi MVC như là cấu hình. Các filter như [Authorize] hoặc [RequiresSsl] là các cấu hình tùy chọn gắn vào trong code của bạn. Bằng mọi cách viết một kiểm thử tích hợp (integration test) cho các hành vi bên ngoài-quan sát được (externally-observable), nhưng nó là vô nghĩa để thử unit testing cho sự hiện diện của các thuộc tính của filter trong mã nguồn của bạn – một lần nữa nó chỉ chứng tỏ rằng bạn có thể copy và paste. Điều đó không giúp bạn thiết kế bất cứ điều gì, và nó sẽ chẳng bao giờ phát hiện bất kỳ lỗi nào cả.
Đặt tên các unit test của bạn một cách rõ ràng và nhất quán
Nếu bạn đang kiểm thử action Purchase của ProductController hành động như thế nào khi hết hàng trong kho (stock is zero), sau đó có thể có một lớp test fixture được gọi là PurchasingTests cùng với một unit test gọi là ProductPurchaseAction_IfStockIsZero_RendersOutOfStockView(). Cái tên này mô tả đối tượng (action Purchase của ProductController), kịch bản (hết hàng trong kho), và kết quả (hiển thị trên view là “hết hàng”). Tôi không biết liệu có một cái tên cho mô hình đặt tên này hay không, mặc dù tôi biết nhiều người khác cũng làm theo cách này.
Tránh sử dụng những tên unit test không rõ nghĩa như Purchase() hoặc OutOfStock(). Việc bảo trì sẽ rất khó khăn nếu bạn không biết là mình đang cố duy trì cái gì.
Kết luậnKhông còn nghi ngờ gì nữa, unit testing có thể làm tăng đáng kể chất lượng dự án của bạn. Nhiều người trong ngành cho rằng việc có thêm bất kỳ unit test thì tốt hơn là không có gì, nhưng tôi không đồng tình với quan điểm đó: một bộ test có thể là một tài sản tuyệt vời, hoặc nó có thể là một gánh nặng rất lớn mà không mang lại giá trị gì nhiều. Nó phụ thuộc vào chất lượng của những test này, mà dường như được xác định bởi mức độ các nhà phát triển hiểu rõ những mục tiêu và nguyên tắc của unit testing.
Unit Test Là Gì? Giới Thiệu Về Unit Test Và Ví Dụ
Lời nói đầu.
Dành cho các bạn lười biếng =]]. Nêú các bạn không muốn đọc lý thuyết thì scroll xuống để xem ví dụ về cách viết unit test và hãy xem mình là ở vị trí nào?
Bất cứ ai đã tham gia vào vòng đời phát triển phần mềm dù ít hay nhiều kinh nghiệm đều cũng đã từng nghe tới Unit Test. Unit Test là một cơ chế chấp nhận để khám phá phần mềm hoạt động tốt như thế nào theo các yêu cầu được chỉ định. Mặc dù mục đích của kiểm tra là tìm ra các lỗi, nhưng nó không thể đảm bảo sự vắng mặt của các lỗi khác, bất kể các trường hợp kiểm thử đã được thiết kế sáng tạo như thế nào.
Có nhiều công ty không quan trọng vấn đề này nhưng nếu Công TY bạn bắt buộc nghiêm ngặt vấn đề này thì tôi tin và tôi viết vị trí của bạn đang ở đâu. Một lập trình viên lúc nào cũng cận thẩn trong việc code thì lúc nào cũng phải có test case.
Tham gia cùng chúng tôi:
Facebook: Cộng đồng lập trình javascript
Facebook Cộng đồng giới thiệu bài viết, website, sản phẩm tăng traffic.
Bài viết này sẽ cung cấp cho bạn những điều sau đây:
Unit Test là gì?
Unit Test có cần thiết không?
Unit Test có nhược điểm gì?
Viết Unit Test thông qua ví dụ.
#Unit Test là gì?Bản thân bài kiểm tra đơn vị là một đoạn mã ngắn hoặc đoạn mã được thiết kế để xác minh hành vi của một đơn vị cụ thể để tạo ra kết quả vượt qua hoặc thất bại. Mục đích của thử nghiệm đơn vị là cho phép các nhà phát triển chạy càng nhiều thử nghiệm đơn vị càng tốt để xác định các lỗ hổng tiềm năng. Khi ứng dụng đã vượt qua thử nghiệm đơn vị, các hình thức thử nghiệm khác sau đó sẽ cần được áp dụng để xác nhận thêm.
#Unit Test có cần thiết không?Câu trả lời đương nhiên là cần thiết với một Lập Trình Viên có trách nhiệm với những dòng code của chính bản thân mình.
1 – Phát triển nhanh hơn.Một khi các devloper viết các test case thì việc gỡ bug sẽ ít dành thời gian hơn và sau đó sẽ tự tin hơn về việc thực hiện các thay đổi code. Những kỹ năng về mọi mặt sẽ phát triển nhanh hơn các Lập Trình Viên bình thường.
Tính cận thận và trách nhiệm trong những bài unit test cũng khẳng định ở bên ngoài cuộc sống của họ.
2 – Cấu trúc Code tốt hơn.Khi các nhà phát triển viết unit tests, sự nhấn mạnh của họ là suy nghĩ về cách mã của họ sẽ được sử dụng trên toàn hệ thống, điều này thường dẫn đến thiết kế tốt hơn.
Và còn nhiều lợi ích khác như là giảm công việc cho các tester, giảm giá thành chi phí code, giúp giảm chi phí cho việc bảo trì trong tương lai…
#Unit Test có nhược điểm gì?Mặc dù các lợi ích của Unit Test đang bắt đầu được hiểu rộng rãi hơn, nhưng vẫn còn một số lý do tại sao nó không được áp dụng đầy đủ hơn, điều này khiến tiềm năng của nó không được thực hiện.
1 – Không có thời gian cho Unit Test.Viết Unit Test là tốn thời gian đó là lý do tại sao rất khó để đáp ứng thời hạn. Trong thực tế, Unit Test có thể tiết kiệm rất nhiều thời gian và nỗ lực phát triển trong thời gian dài.
2 – Unit tests khác với viết codeĐúng, bạn hãy nghĩ rằng để viết được một unit test đôi khi còn mất thời gian hơn viết một chức năng code. Và có thể có những Lập Trình Viên viết được code nhưng chưa chắc viết được test case. Không có gì đảm bảo, ngay cả khi mã được kiểm tra kỹ lưỡng, sẽ không có lỗi.
#Viết Unit Test thông qua ví dụBây giờ mình sẽ làm một bài tập nho nhỏ cho các bạn hiểu về cách thức viết một unit test như thế nào?
Mình sẽ lấy bài toàn Viết hoa chữ cái đầu tiên của mỗi từ trong Câu trong bài Sự Khác Biệt Về Kinh Nghiệm Trong Lập Trình Javascript để làm ví dụ:
Sử dụng reduce() làm tăng hiệu quả và điều quan tâm là hiệu suất. Giải pháp dùng reduce() and map().
const rest = word.slice(1); const firstLtr = word.charAt(0); return firstLtr.toUpperCase() + rest.toLowerCase(); } if(!phrase) return phrase; [first, …rest] = phrase.split(‘ ‘); capitalize(first)) } Unit Test:
Tôi đã viết một hàm trợ giúp khẳng định và một số trường hợp thử nghiệm. Đây không phải là một bài kiểm tra toàn diện
return fun(input) === expected ? ‘passed’ : `failed on input=${input}. expected ${expected}, but got ${fun(input)}`; } Test cases:
let testCases = [ {input: "I'm a little tea pot", expected: "I'm A Little Tea Pot"}, {input: "sHoRt AnD sToUt", expected: "Short And Stout"}, {input: "sHoRt AnD sToUt", expected: "Short And Stout"}, {input: "tôi là một lập trình viên javascript", expected: "Tôi Là Một Lập Trình Viên Javascript"}, {input: "HERE IS MY HANDLE HERE IS MY SPOUT", expected: "Here Is My Handle Here Is My Spout"}, {input: "", expected: ""}, {input: undefined, expected: undefined}, ]Làm bài kiểm tra này, bạn sẽ vượt qua tất cả các bài kiểm tra:
console.log(testResult); output: 0: “passed” 1: “passed” 2: “passed” 3: “passed” 4: “passed” 5: “passed”
#Kết LuậnTham gia cùng chúng tôi:
Facebook: Cộng đồng lập trình javascript
Facebook Cộng đồng giới thiệu bài viết, website, sản phẩm tăng traffic.
Tham khảo tại:
https://www.guru99.com/unit-testing-guide.html https://areknawo.com/lets-talk-js-unit-testing/ https://blog.testlodge.com/what-is-unit-testing/
Unit Test Là Gì? 10 Frameworks Unit Test Cho Javascript
Thông thường khi làm một dự án web lớn thì nó sẽ được chia thành nhiều phần nhỏ để dễ dàng phát triển cũng như chỉnh sửa. Unit test có nhiệm vụ giúp bạn thực hiện kiểm tra các chức năng đó có chạy đúng theo yêu cầu hay không. Nó sẽ có hai loại unit test chính là Manual và Automated. Một số lợi ích khi bạn sử dụng unit test là:
Giúp cải thiện chất lượng đoạn mã trong chương trình.
Thời gian tìm lỗi được phát hiện nhanh hơn.
Cung cấp documentation cho trang web.
Đơn giản hóa quá trình gỡ lỗi.
Tiết kiệm chi phí khi xây dựng trang web.
Giúp bạn hiểu rõ hơn về hệ thống của mình thông qua những test case do bạn viết.
Những Framework Unit Test Dành Cho Lập Trình ViênMochaJS là một framwork testing được sử dụng phổ biến trong lập trình web và hỗ trợ cho cả back-end(Nodejs) và front-end. Nó giúp bạn thực hiện kiếm tra không đồng bộ một cách đơn giản và dễ dàng. Ngoài ra nó còn có cộng động lập trình viên hỗ trợ đông đảo, nhiều hướng dẫn ví dụ chi tiết và được nhiều công ty cũng như website lớn tin tưởng sử dụng.
Jest là một framwork testing tập trung vào sự đơn giản. Nó có thể làm việc với Babel, TypeScript, Node, React, Angular, Vue… Với các bài test được chạy song song trong các quy trình riêng nhằm tối đa hiệu suất cho chương trình. Ngoài ra nó còn có tài liệu hướng dẫn chi tiết, yêu cầu thiết lập không phức tạp và dễ dàng có thể mở rộng để phù hợp với yêu cầu của lập trình viên.
AVA là một framework testing cho Javascript với API ngắn gọn và đưa ra những thông báo lỗi chi tiết trong quá trình kiểm tra. Một số điểm mạnh nó là cú pháp đơn giản, viết các test cho cú pháp Javascript mới nhất, hỗ trợ chức năng không đồng bộ, cung cấp chức năng promise…
Jasmine là một framework testing dùng để kiểm tra các đoạn mã Javascript. Với cú pháp đơn giản giúp bạn viết test case một cách dễ dàng. Một số điểm mạnh là hỗ trợ cho cả front-end và back-end, có tài liệu mở rộng khi sử dụng với các framework khác, tốc độ thực thi nhanh, không sử dụng bất kỳ thư viện bổ sung nào…
Karma mang lại một môi trường testing hiệu quả cho các nhà phát triển với các tính năng hữu ích như là có thể kiểm tra code trên nhiều thiết bị như trình duyệt, điện thoại, máy tính bảng…, mô tả các testing với Jasmine, Mocha, QUnit…, dễ dàng gỡ lỗi trực tiếp từ IDE thông qua WebStorm hay Google Chrome.
Puppeteer là một thư viện NodeJS cung cấp các high-level API để sử dụng cho các ứng dụng dành riêng cho trình duyệt như kiểm tra thu thập dữ liệu, testing UI, kiểm tra các chrome extension, xem các vấn đề về hiệu suất, chụp ảnh màn hình và PDF của các trang…
Nightwatch là một thư viện được xây dựng bằng NodeJS dễ dàng sử dụng cho các ứng dụng và trang web. Với cú pháp đơn giản, mạnh mẽ cho pháp bạn viết các test case một cách nhanh chóng thông qua Javascript và CSS. Quản lý tự động các dịch vụ Selenium hoặc WebDriver (ChromeDriver, GeckoDriver, Edge, Safari) trong một quy trình con riêng biệt. Sử dụng API WebDriver của W3C để điều khiển các trình duyệt thực hiện các lệnh và xác nhận trên các phần tử DOM.
Cypress là một testing framework giúp bạn kiểm tra nhanh chóng dễ dàng với mọi thứ chạy trên trình duyệt. Một sổ điểm mạnh của nó là cách thiết lập đơn giản, tự động tải lại khi các test case thay đổi, các hình ảnh được chụp tự động khi chạy test case, có thể gỡ lỗi trực tiếp thông qua các cụ phổ biến như Chrome DevTools…
Tape là một testing framework nhỏ gọn cung cấp bare-metal code giúp lập trình viên hoàn toàn tự do trong việc viết test case cho cả front-end và back-end. Ngoài ra nó cũng hỗ trợ cho ES6, coffee script tiêu chuẩn, Typescript và có thể chạy trên hầu hết các trình duyệt phổ biến hiện nay. Một hạn chế là nó không hỗ trợ global do vậy bạn cần thêm Tape vào mỗi tệp kiểm tra khi muốn thực hiện testing.
Chai là một testing framework cho NodeJS và trình duyệt. Nó cung cấp 2 loại là TDD(Test-Driven Development) tập trung vào kiểm tra quy trình nội bộ, hiệu suất của code và BDD(Behaviour-Driven Development) ưu tiên giá trị được đưa ra trong yêu cầu. Ngoài ra nó cũng các bài viết hướng dẫn chi tiết cho người mới bắt đầu cũng như cộng đồng lập trình viên hỗ trợ đông đảo.
Một số bài viết hướng dẫn sử dụng unit testJestAvaJasmineKarma
Tổng kết:Unit Test Là Gì? Khái Niệm Và Vai Trò
1. Khái niệm về Unit Test Unit Test là gì?
Unit Test là một loại kiểm thử phần mềm trong đó các đơn vị hay thành phần riêng lẻ của phần mềm được kiểm thử. Kiểm thử đơn vị được thực hiện trong quá trình phát triển ứng dụng. Mục tiêu của Kiểm thử đơn vị là cô lập một phần code và xác minh tính chính xác của đơn vị đó.
Unit là gì?Một Unit là một thành phần PM nhỏ nhất mà ta có thể kiểm tra được như các hàm (Function), thủ tục (Procedure), lớp (Class), hoặc các phương thức (Method).
Vì Unit được chọn để kiểm tra thường có kích thước nhỏ và chức năng hoạt động đơn giản, chúng ta không khó khăn gì trong việc tổ chức, kiểm tra, ghi nhận và phân tích kết quả kiểm tra nên việc phát hiện lỗi sẽ dễ dàng xác định nguyên nhân và khắc phục cũng tương đối dễ dàng vì chỉ khoanh vùng trong một Unit đang kiểm tra.
Mỗi UT sẽ gửi đi một thông điệp và kiểm tra câu trả lời nhận được đúng hay không, bao gồm:
Các kết quả trả về mong muốn
Các lỗi ngoại lệ mong muốn
Các đoạn mã UT hoạt động liên tục hoặc định kỳ để thăm dò và phát hiện các lỗi kỹ thuật trong suốt quá trình phát triển, do đó UT còn được gọi là kỹ thuật kiểm nghiệm tự động. UT có các đặc điểm sau:
Đóng vai trò như những người sử dụng đầu tiên của hệ thống.
Chỉ có giá trị khi chúng có thể phát hiện các vấn đề tiềm ẩn hoặc lỗi kỹ thuật.
Khi làm Unit test chúng ta thường thấy các khái niệm sau:
Assertion: Là một phát biểu mô tả các công việc kiểm tra cần tiến hành, thí dụ: AreEqual(), IsTrue(), IsNotNull()… Mỗi một UT gồm nhiều assertion kiểm tra dữ liệu đầu ra, tính chính xác của các lỗi ngoại lệ ra và các vấn đề phức tạp khác như: – Sự tồn tại của một đối tượng – Điều kiện biên: Các giá trị có vượt ra ngoài giới hạn hay không – Thứ tự thực hiện của các luồng dữ liệu …
Test Point: Là một đơn vị kiểm tra nhỏ nhất, chỉ chứa đơn giản một assertion nhằm khẳng định tính đúng đắn của một chi tiết mã nào đó. Mọi thành viên dự án đều có thể viết một test point. Test Case: Là một tập hợp các test point nhằm kiểm tra một đặc điểm chức năng cụ thể, thí dụ toàn bộ giai đoạn người dùng nhập dữ liệu cho đến khi thông tin được nhập vào cơ sở dữ liệu. Trong nhiều trường hợp kiểm tra đặc biệt và khẩn cấp có thể không cần đến test case.
Test Suite: Là một tập hợp các test case định nghĩa cho từng module hoặc hệ thống con.
Regression Testing (hoặc Automated Testing): Là phương pháp kiểm nghiệm tự động sử dụng một phần mềm đặc biệt. Cùng một loại dữ liệu kiểm tra giống nhau nhưng được tiến hành nhiều lần lặp lại tự động nhằm ngăn chặn các lỗi cũ phát sinh trở lại. Kết hợp Regression Testing với Unit Testing sẽ đảm bảo các đoạn mã mới vẫn đáp ứng yêu cầu thay đổi và các đoạn mã cũ sẽ không bị ảnh hưởng bởi các hoạt động bảo trì.
Production Code: Phần mã chính của ứng dụng được chuyển giao cho khách hàng.
Unit Testing Code: Phần mã phụ để kiểm tra mã ứng dụng chính, không được chuyển giao cho khách hàng.
2.Vòng đời Unit TestUT có 3 trạng thái cơ bản:
Fail (trạng thái lỗi)
Ignore (tạm ngừng thực hiện)
Pass (trạng thái làm việc)
Toàn bộ UT được vận hành trong một hệ thống tách biệt. Có rất nhiều PM hỗ trợ thực thi UT với giao diện trực quan. Thông thường, trạng thái của UT được biểu hiện bằng các màu khác nhau: màu xanh (pass), màu vàng (ignore) và màu đỏ (fail)
Được vận hành lặp lại nhiều lần
Tự động hoàn toàn
Độc lập với các UT khác.
3. Thiết kế Unit testMỗi UT đều được tiết kế theo trình tự sau:
Thiết lập các điều kiện cần thiết: khởi tạo các đối tượng, xác định tài nguyên cần thiết, xây dựng các dữ liệu giả…
Triệu gọi các phương thức cần kiểm tra.
Kiểm tra sự hoạt động đúng đắn của các phương thức.
Dọn dẹp tài nguyên sau khi kết thúc kiểm tra.
4. Ứng dụng Unit test
Kiểm tra mọi đơn vị nhỏ nhất là các thuộc tính, sự kiện, thủ tục và hàm.
Kiểm tra các trạng thái và ràng buộc của đối tượng ở các mức sâu hơn mà thông thường chúng ta không thể truy cập được.
Kiểm tra các quy trình (process) và mở rộng hơn là các khung làm việc(workflow – tập hợp của nhiều quy trình)
5. Lợi ích của việc áp dụng Unit testThời gian đầu, người ta thường do dự khi phải viết UT thay vì tập trung vào code cho các chức năng nghiệp vụ. Công việc viết Unit Test có thể mất nhiều thời gian hơn code rất nhiều nhưng lại có lợi ích sau:
Tạo ra môi trường lý tưởng để kiểm tra bất kỳ đoạn code nào, có khả năng thăm dò và phát hiện lỗi chính xác, duy trì sự ổn định của toàn bộ PM và giúp tiết kiệm thời gian so với công việc gỡ rối truyền thống.
Phát hiện các thuật toán thực thi không hiệu quả, các thủ tục chạy vượt quá giới hạn thời gian.
Phát hiện các vấn đề về thiết kế, xử lý hệ thống, thậm chí các mô hình thiết kế.
Phát hiện các lỗi nghiêm trọng có thể xảy ra trong những tình huống rất hẹp.
Tạo hàng rào an toàn cho các khối mã: Bất kỳ sự thay đổi nào cũng có thể tác động đến hàng rào này và thông báo những nguy hiểm tiềm tàng.
Trong môi trường làm việc Unit Test còn có tác dụng rất lớn đến năng suất làm việc:
Giải phóng chuyên viên QA khỏi các công việc kiểm tra phức tạp.
Tăng sự tự tin khi hoàn thành một công việc. Chúng ta thường có cảm giác không chắc chắn về các đoạn mã của mình như liệu các lỗi có quay lại không, hoạt động của module hiện hành có bị tác động không, hoặc liệu công việc hiệu chỉnh mã có gây hư hỏng đâu đó…
Là công cụ đánh giá năng lực của bạn. Số lượng các tình huống kiểm tra (test case) chuyển trạng thái “pass” sẽ thể hiện tốc độ làm việc, năng suất của bạn.
6. Cách code hiệu quả với Unit TestPhân tích các tình huống có thể xảy ra đối với mã. Đừng bỏ qua các tình huống tồi tệ nhất có thể xảy ra, thí dụ dữ liệu nhập làm một kết nối cơ sở dữ liệu thất bại, ứng dụng bị treo vì một phép toán chia cho không, các thủ tục đưa ra lỗi ngoại lệ sai có thể phá hỏng ứng dụng một cách bí ẩn…
Mọi UT phải bắt đầu với trạng thái “fail” và chuyển trạng thái “pass” sau một số thay đổi hợp lý đối với mã chính.
Mỗi khi viết một đoạn mã quan trọng, hãy viết các UT tương ứng cho đến khi bạn không thể nghĩ thêm tình huống nào nữa.
Nhập một số lượng đủ lớn các giá trị đầu vào để phát hiện điểm yếu của mã theo nguyên tắc:
Nếu nhập giá trị đầu vào hợp lệ thì kết quả trả về cũng phải hợp lệ
Nếu nhập giá trị đầu vào không hợp lệ thì kết quả trả về phải không hợp lệ
Sớm nhận biết các đoạn mã không ổn định và có nguy cơ gây lỗi cao, viết UT tương ứng để khống chế.
Ứng với mỗi đối tượng nghiệp vụ (business object) hoặc đối tượng truy cập dữ liệu (data access object), nên tạo ra một lớp kiểm tra riêng vì những lỗi nghiêm trọng có thể phát sinh từ các đối tượng này.
Để ngăn chặn các lỗi có thể phát sinh trở lại thực thi tự động tất cả UT mỗi khi có một sự thay đổi quan trọng, hãy làm công việc này mỗi ngày. Các UT lỗi cho chúng ta biết thay đổi nào là nguyên nhân gây lỗi.
Để tăng hiệu quả và giảm rủi ro khi viết các UT, cần sử dụng nhiều phương thức kiểm tra khác nhau. Hãy viết càng đơn giản càng tốt.
Cuối cùng, viết UT cũng đòi hỏi sự nỗ lực, kinh nghiệm và sự sáng tạo như viết PM.
Unit Test Với Junit 4X
Trong bài viết này chúng ta cùng tìm hiểu về test và unit test bằng JUnit 4.x.
1.1 Code under testNhững đoạn code được kiểm thử thường gọi code under test. Nếu bạn đang kiểm thử một ứng dụng nào đó thì nó được gọi là application under test.
1.2 Test fixtureĐây là các điều kiện để có thể bắt đầu kiểm thử. Ví dụ như là một đoạn String cố định được sử dụng để làm input cho một method nào đó. Chúng ta chỉ có thể kiểm thử nếu đoạn test đó có đầy đủ các thông số truyền vào.
1.3 Unit test và unit testingMột unit test là một đoạn code nhỏ được viết bởi developer nhằm mục đích kiểm tra một hàm hay chức năng riêng biệt nào đó có kết quả đúng như kì vọng hay không. Tỉ lệ các đoạn code được kiểm tra bằng unit test được gọi là test coverage. Phạm vi kiểm tra của một unit test thường là một method hoặc một class. Những method hay class có phụ thuộc lẫn nhau nên được tách biệt ra khi viết unit test. Vì vậy, unit test không phù hợp để kiểm thử những interface phức tạp hoặc một component. Chúng ta nên sử dụng integration test cho những phạm vi lớn và phức tạp này.
1.4 Integration testMột kiểm thử tích hợp (integration test) có nhiệm vụ kiểm tra hoạt động của một component hoặc một tập hợp các component. Loại kiểm thử này còn được biết đến với cái tên funtional test.
Integration test sẽ kiểm tra toàn bộ hệ thống có làm việc như mong muốn không, do đó chúng giúp làm giảm các công việc kiểm thử thủ công.
1.5 Performance testKiểm thử hiệu năng được sử dụng để đánh giá các thành phần trong phần mềm được dùng đi dùng lại nhiều lần. Mục đích là để kiểm tra khả năng chịu tải cao, tốc độ tải trong điều kiện nhiều request.
1.6 Behavior và state testingMột đoạn test được gọi là behavior test nếu nó kiểm tra các phương thức với các parameter truyền vào là chính xác và không quan tâm đến kết quả trả về là gì. Một đoạn test được gọi là state testing nếu nó validate kết quả trả về.
1.7 Testing frameworkTrong java thì chúng ta có một vài framework hỗ trợ việc kiểm thử. Tiêu biểu nhất là JUnit và TestNG. Trong bài viết này chúng ta sẽ tìm hiểu về JUnit 4.x.
1.8 Những đoạn test nên đặt ở đâu?Thông thường thì các đoạn unit test sẽ được tạo trong một folder hoặc một package riêng, tránh lẫn lộn với những đoạn code chính. Theo chuẩn build project của Maven và Gradle thì
src/main/java là nơi chứa Java class
src/test/java là nơi chứa test class.
Cung cấp Annotation để xác định việc xác thực phương thức.
Cung cấp Asertion cho kết quả mong muốn.
Cung cấp các Runner cho việc chạy thử.
Giúp viết code nhanh hơn mà chất lượng ngày càng tăng.
@Test – Đánh dấu một method là một method dùng để kiểm thử.
@Before và @After : đánh dấu vị trí bắt đầu và kết thúc của một method test trong một class.
@BeforeClass và AfterClass: Đánh dấu method chạy đầu tiên và cuối cùng trong một class test.
@Ignore hoặc @Ignore("Why disabled"): đánh dấu đoạn test nên được disabled. Nó được sử dụng khi các đoạn code chính đã được thay đổi nhưng các test case chưa được cập nhật hoặc điều chỉnh hoặc thời gian thực thi quá lâu nếu phải bao gồm cả nó. Tốt nhất là nên kèm theo giải thích tại sao lại disabled khi sử dụng annotation này.
@Test(timeout=100): Đoạn test sẽ được đánh là thất bại nếu thời gian thực thi lớn hơn 100 miliseconds.
Ví dụ:
public class SampleTest { @BeforeClass public static void setUpBeforeClass() throws Exception {Khi chạy đoạn code trên thì thứ tự thực thi sẽ là:
Method được đánh dấu @BeforeClass.
Method được đánh dấu @Before.
Method kiểm thử đầu tiên được đánh dấu @Test (ở đây là test1()).
Method được đánh dấu @After.
Method được đánh dấu @Before.
Method kiểm thử thứ hai được đánh dấu @Test ( ở đây là test2()).
Method được đánh dấu @After.
Method được đánh dấu @AfterClass.
# 4. Assertions Khi muốn xác nhận một kết quả trả về có đúng như mong muốn không, chúng ta có danh sách Junit assertion cũ như sau:
org.junit.Assert.assertArrayEquals
org.junit.Assert.assertEquals
org.junit.Assert.assertFalse
org.junit.Assert.assertNotNull
org.junit.Assert.assertNotSame
org.junit.Assert.assertNull
org.junit.Assert.assertSame
org.junit.Assert.assertTrue
Từ phiên bản JUnit4, chúng ta có thêm một method org.junit.Assert.assertThat cho phép sử dụng các matcher để xác nhận tốt hơn:
Dễ đọc hơn
assertThat(actual, is(equalTo(expected))); dễ đọc hơn assertEquals(expected, actual);
assertThat(actual, is(not(equalTo(expected)))); tốt hơnassertFalse(expected.equals(actual));
Thông báo lỗi tốt hơn
Linh hoạt hơn
Có thể sử dụng nhiều điều kiện để assert bằng cách dùng các matcher như anyOf hay allOf.
Nếu phương thức bạn cần kiểm thử có throw các exceptions thì chúng ta cũng có vài cách để kiểm tra xem nó có throw đúng như trong điều kiện mong muốn không. Ví dụ như chúng ta tạo một phương thức để đọc file và nó sẽ trả về một exception với message “The file ${file_name} does not exit!” trong trường hợp không tìm thấy file đó.
@Test(expected = FileNotFoundException.class) public void testReadFile() throws IOException { FileReader reader = new FileReader("test.txt"); reader.read(); reader.close(); } @Test public void testReadFile2() { try { FileReader reader = new FileReader("test.txt"); reader.read(); reader.close(); fail("Expected an IOException to be thrown"); } catch (IOException e) { assertThat(e.getMessage(), is("test.txt (No such file or directory)")); } } @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testReadFile3() throws IOException { thrown.expect(IOException.class); thrown.expectMessage(startsWith("test.txt (No such file or directory)")); FileReader reader = new FileReader("test.txt"); reader.read(); reader.close(); }Thông thường chúng ta cần kiểm tra một method đơn với nhiều loại data test khác nhau hoặc nhiều input khác nhau. Trong trường hợp này chúng ta có Parameterized để thực hiện kiểm thử một cách dễ dàng và dễ đọc.
https://javacodehouse.com/blog/junit-tutorial/ http://www.vogella.com/tutorials/JUnit/article.html
Viết Unit Test Cho Javascript Với Jasmine
Blog có khá nhiều bài về code rồi nên hôm nay mình sẽ viết một bài để đổi gió.
1. Nhắc lại sơ về Unit TestTrước khi có unit test, các lập trình viên thường code theo kiểu: code – test – fix lại – code tiếp – test lại – fix tiếp. Đôi khi chỉ vì sửa 1 lỗi nho nhỏ mà ta phải test lại rất nhiều lần. Để giải quyết vấn đề này, unit test và automation test ra đời. Mình không phải QA chuyên nghiệp nên không dám múa rìu qua mắt thợ, chỉ nói sơ về định nghĩa của 2 loại test này:
Unit test: Đây là test do developer viết, được chạy để kiểm tra các hàm do developer viết ra có sai hay ko. Unit test thường được chạy mỗi khi build để đảm bảo các hàm đều chạy đúng sau khi ta sửa code.
Automation test: Đây là test do QA viết, được chạy để kiểm thử hệ thống (Nếu không có automation test thì QA kiểm thử bằng tay, gọi làm manual test).
Bài viết này chỉ tập trung vào unit test. Đây là test mà developer chúng ta phải viết. Các thư viện thường dùng để viết unit test là jUnit (Java), nUnit (C#), thư viện test của Microsoft, … Một số khái niệm cần biết trong unit test:
Setup: Đây là hàm được chạy trước khi chạy các test case, thường dùng để khai báo dữ liệu, cài đặt các biến.
Teardown: Đây là hàm được chạy sau khi các test case chạy xong, thường dùng để xóa dữ liệu, giải phóng bộ nhớ.
Assert: Mỗi test case sẽ có 1 hoặc nhiều câu lệnh Assert, để kiểm tra tính đúng đắn của hàm. Vd: Assert.Equals(4, Add(2,2));
Mock: Giả sử chương trình của bạn được chia làm 2 module: A và B. Module A đã code xong, B thì chưa. Để test module A, ta dùng mock để làm giả module B, không cần phải đợi tới khi module B code xong mới test được.
2. Giới thiệu về Jasmine 3. Demo JasmineĐể đơn giản, chúng ta sẽ tạo 1 file spec mới làm ví dụ, đặt tên là chúng tôi Ta sửa lại file html như sau:
function Calculator() { chúng tôi = function(a, b) { return a+b;}; this.minus = function(a, b) { return a-b;}; this.multiply = function(a, b) { return a*b;}; this.divide = function(a,b) {return a/b;} ; }Một số unit test cộng trừ nhân chia
Hàm describe dùng để gom nhóm, ghi chú cho nhiều unit test.
Hàm it tương đương với 1 unit test.
Hàm expect chính là hàm assert để kiểm tra tính đúng đắn của unit test
describe("Cộng trừ", function() { var cal = new Calculator(); it("Một với một là hai", function() { expect(2).toBe(cal.add(1,1)); }); it("Hai với hai là bốn", function() { expect(4).toBe(cal.add(2,2)); }); it("Năm trừ hai bằng ba", function() { expect(3).toBe(cal.minus(5,2)); }); }); describe("Nhân chia", function() { var cal = new Calculator(); it("Năm nhân hai bằng mười", function() { expect(10).toBe(cal.multiply(5,2)); }); it("Sáu chia hai bằng ba", function() { expect(3).toBe(cal.divide(6,2)); }); });Chạy lại file SpecRunner.html, ta được kết quả. Giả sử ta cố ý sửa lại cho hàm minus chạy sai, ta sẽ thấy unit test báo hàm sai như sau: Bài viết tới đây là kết thúc. Ở phần 2, mình sẽ hướng dẫn chi tiết hơn về cách dùng hàm setup, teardown và mock với Jasmine. Các bạn có thể tải code sample của bài viết này ở đây: https://github.com/conanak99/jasmine-sample.
Cập nhật thông tin chi tiết về Unit Test Dùng Để Làm Gì Và Kinh Nghiệm Viết Unit Test Tốt Nhất trên website Ezlearning.edu.vn. Hy vọng nội dung bài viết sẽ đáp ứng được nhu cầu của bạn, chúng tôi sẽ thường xuyên cập nhật mới nội dung để bạn nhận được thông tin nhanh chóng và chính xác nhất. Chúc bạn một ngày tốt lành!