Bạn đang xem bài viết Viết Unit Test Trong C# Với Nunit được cập nhật mới nhất tháng 12 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.
Ở trường đại học chắc các bạn đã được học khái niệm về Unit Test trong môn “Kiểm thử chất lượng phần mềm”. Nói một cách dễ hiểu, unit test tức là code dùng để test code ta đã viết.
Một số đặc điểm của unit test:
Code unit test phải ngắn gọn, dễ hiểu, dễ đọc.
Mỗi unit test là 1 đơn vi riêng biệt, độc lập, không phụ thuộc vào unit khác.
Mỗi unit test là 1 method trong test class, tên method cũng là tên UnitTest. Do đó ta nên đặt tên hàm rõ ràng, nói rõ unit test này test cái gì (Test_A_Do_B), tên method có thể rất dàiii cũng không sao.
Unit Test phải nhanh, vì nó sẽ được chạy để kiểm định lỗi mỗi lần build. Do đó trong unit test nên hạn chế các task tốn thời gian như gọi I/O, database, network,…
Unit Test nên test từng đối tượng riêng biệt. Vd: Unit Test cho Business Class thì chỉnh test chính BusinessClass đó, không nên dụng tới các class móc nối với nó (DataAccess Class chẳng hạn).
Một số bạn sẽ thắc mắc: “Ơ hay, trong business class thì phải gọi data access chứ?”, và “code mình dính chùm lắm, làm sao test từng class riêng được”.
Để viết unit test, các class của bạn phải có quan hệ “lõng lẽo” với nhau (loose coupling), nếu không viết được unit test nghĩa là các class dính với nhau quá chặt, sẽ khó thay đổi sau này. Hãy áp dụng các nguyên lý SOLID vào code, viết code với tư tưởng “viết sao để unit test được” sẽ là code của bạn uyển chuyển, dễ test hơn.
Về vấn đề Business Class và Data Access, các class không nên gọi trực tiếp lẫn nhau mà gọi thông qua interface. Khi unit test, ta sẽ thay các hiện thực interface này bằng các class giả, thay thế cho class data access thật. Mình sẽ nói rõ về vấn đề này ở những bài viết về Inversion of Control, Dependency Injection trong tương lai.
Một số lợi ích của Unit Test:
Nếu viết Unit Test một cách cẩn thận, code của bạn sẽ ít lỗi hơi, vì Unit Test sẽ phát hiện lỗi cho bạn.
Phát hiện những hàm chạy chậm và không hiệu quả thông qua thời gian chạy của Unit Test.
Tăng sự tự tin khi code, vì đã có Unit Test phát hiện lỗi.
Khi refactor code, sửa code hay thêm chức năng mới, Unit Test đảm bảo chương trình chạy đúng, phát hiện những lỗi tiềm tàng mà ta bỏ lỡ.
Unit Test trong C# với NUnitTrước đây, để viết Unit Test trong C#, ta thường phải tạo một project test riêng, sử dụng thư viện MSTest của Microsoft. MSTest hỗ trợ khá nhiều chức năng: Test dữ liệu từ database, đo performance hệ thống, xuất dữ liệu report. Tuy nhiên, do MSTest đi kèm với Visual Studio, không thể chạy riêng rẽ, lại khá nặng nề, do đó NUnit được nhiều người ưa thích hơn. NUnit có 1 bộ runner riêng, có thể chạy UnitTest độc lập không cần VisualStudio, ngoài ra nó cũng hỗ trợ một số tính năng mà MSTest không có (parameter test, Assert Throw).
Nếu bạn chưa bao giờ viết Unit Test, bắt đầu với NUnit cũng là 1 lựa chọn không tồi. Đầu tiên, ta hãy tạo 1 project console trong Visual Studio. Ta viết 1 class Calculator với các 2 hàm Add và Subtract:
public class Calculator { public int Add(int x, int y) { return x + y; } public int Subtract(int x, int y) { return x - y; } } using NUnit.Framework; [TestFixture] public class CalculatorTest { private Calculator _cal; [SetUp] public void Setup() { _cal = new Calculator(); } [Test] public void OnePlusOneEqualTwo() { Assert.AreEqual(2, _cal.Add(1, 1)); } [Test] public void TwoPlusTwoEqualFour() { Assert.AreEqual(4, _cal.Add(2, 2)); } [Test] public void FourPlusOneEqualFive() { Assert.AreEqual(5, _cal.Add(4, 1)); } }Giải thích một số annotation:
Annotation [TextFixture] đặt vào đầu class chứa các unit test, đánh dấu đây là một bộ các unit test.
Annotation [SetUp] để đánh dấu hàm setup. Hàm này sẽ được chạy vào đầu mỗi unit test.
Để chạy Unit Test, ta cần cài NUnit.TestAdapter, đây là bộ runner cho phép chạy các Unit Test của NUnit trong Visual Studio. Bạn cũng có thể dùng 1 trong 2 cách sau:
Tải NUnit GuiRunner về, mở file dll của project test, các unit test sẽ hiện ra để chạy.
Tải Reshaper. Reshaper cũng tích hợp sẵn 1 bộ Runner cho phép chạy Unit Test của NUnit.
Ta cố ý sửa lại code để code chạy sai. Chạy lại Unit Test, ta sẽ thấy các case đã fail. Unit Test đã tự động bắt lỗi chương trình cho bạn rồi đấy. Bấm vào từng test case, ta sẽ thấy kết quả mong muốn ở đoạn ” Excepted“, kết quả code chạy ở đoạn ” But was “.
Unit Test Trong C# Với Nunit Và Moq
Giới thiệu
Trong lập trình hướng đối tượng, mock object là các object mô phỏng các hành vi của object thật. Mock thường được sử dụng trong unit test.
Nói một cách chính xác thì mock object được tạo ra để giúp kiểm tra hành vi của object (thật) khác. Thế nên, mock là việc làm giả object thật và được kiểm soát sao cho luôn trả về giá trị mong muốn.
Object cung cấp các kết quả không xác định.
Có các trạng thái khó tạo ra hoặc tạo lại (ví dụ: lỗi đường truyền).
Chạy chậm (ví dụ truy vấn database, và nó cần phải được khởi tạo trước khi test).
Các hành vi có thể không tồn tại hoặc thay đổi.
Sẽ phải bao gồm thông tin và phương pháp dành riêng cho mục đích thử nghiệm.
Khi chúng ta tạo một mock object, chúng ta có thể cài đặt hành vi cho nó là strict hoặc loose behavior. Strict behavior có nghĩa là exception sẽ được tạo ra nếu những gì chưa được cài đặt trong interface được gọi. Trái lại, loose behaviour sẽ không tạo ra exception trong trường hợp này. Mặc định, mock được cài đặt loose behaviour.
Moq là gì?Moq là một thư viện được viết cho .NET được phát triển từ đầu để tận dụng tối đa .NET 3.5 (tức là các LinQ expression tree) và những tính năng trong C# 3.0 (tức là Lambda Expression) làm cho nó trở thành thư viện mock dễ sử dụng nhất, type-safe và tái cấu trúc có sẵn. Và nó hỗ trợ mock interface cũng như class. API của nó cực kỳ đơn giản, và không yêu cầu bất kỳ kiến thức hoặc kinh nghiệm nào trước đây với mock. Tuy nhiên trước đó bạn phải quen với việc sử dụng Lambda Expression.
Moq hướng đến sự đơn giản, strongly-typed và tối giản (nhưng vẫn đầy đủ tính năng), sử dụng theo hướng AAA (Arrange – Act – Assert).
Tác giả của Moq gọi nó là thư viện mock đơn giản nhất cho .NET. Tôi không chắc chắn lắm về điều đó, nhưng tôi có thể xác nhận rằng nó thật sự là một thư viện đơn giản nhưng mạnh mẽ, đó cũng là lý do mà tôi đặc biệt thích dùng Moq.
Bạn có thể định nghĩa mock cho:
Phương thức của Object (Object Methods)
Thuộc tính (Properties)
Event (Events)
Callback (Callbacks)
Xác nhận (Verifications)
Một vài tình huống nâng cao như xác nhận và thực thi nhiều interface.
Những framework khác
Nsubstitute: Hoàn hảo cho những người mới tiếp cận việc test, hoặc cho những người muốn test của họ có ít lambda hơn.
Rhino Mocks: Mã nguồn mở! Rhino Mocks là một mock framework động cho nền tảng .NET. Mục đích của nó là làm cho việc test dễ dàng hơn bằng cách cho phép lập trình viên tạo mock thực thi custom object và xác nhận sự tương tác sử dụng unit test.
TypeMock, chúng tôi NMock, FakeItEasy.
Cài đặtCó hai cách để cài đặt Moq, hoặc là sử dụng Nuget, hoặc là cài đặt thủ công.
Nếu cài đặt thủ công, chỉ cần download nó từ trang chủ, sau đó thêm reference vào project.
System Under TestLấy một đoạn code chúng ta cần test như sau:
public class CustomerService { private ICustomerRepository _repository; public CustomerService(ICustomerRepository repository) { _repository = repository; } public Customer GetCustomer(int id) { return _repository.GetCustomer(id); } } public interface ICustomerRepository { Customer GetCustomer(int id); } public class Customer { public string LastName { get; set; } public string FirstName { get; set; } }Như bạn có thể thấy, chúng ta có CustomerService phụ thuộc vào ICustomerRepository, đóng vai trò là giao diện cho một class, ví dụ như nó sẽ trả về dữ liệu khách hàng từ database. Tôi sẽ bỏ qua phần thực thi giao diện này bởi vì chúng ta sẽ mock nó, do chúng ta không muốn truy cập vào database rồi lấy dữ liệu của một Customer. Như đã nói trước đó, test cần phải có kết quả xác định, không phát sinh những thứ không mong muốn và chạy nhanh.
Ví dụ test đơn giảnTrong test đầu tiên, chúng ta sẽ tạo một mock cho interface IcustomerRepository và cài đặt các thông số mong muốn. Các thông số mong muốn gồm có: những tham số mà phương thức nhận vào, và kết quả trả về ra sao.
[TestMethod] public void GetCustomer_ValidId() { const int CUSTOMER_ID = 1; const string FNAME = "John"; const string LNAME = "Doe"; repository .Returns(new Customer { FirstName = FNAME, LastName = LNAME }); var service = new CustomerService(repository.Object); var customer = service.GetCustomer(CUSTOMER_ID); Assert.IsTrue(customer != null); Assert.IsTrue(customer.FirstName == FNAME); Assert.IsTrue(customer.LastName == LNAME); }Giải thích qua về đoạn test trên:
tạo ra một object thực thi tất cả phương thức và thuộc tính đã được định nghĩa trong interface ICustomerRepository.
Mặt khác, Moq sử dụng LinQ và Lambda Expression như sau:
repository .Returns(new Customer { FirstName = FNAME, LastName = LNAME });đoạn code trên làm 2 việc:
Phương thức Returns định nghĩa giá trị trả về trong quá trình test chạy.
sau khi cài đặt xong, Moq sẽ tạo ra một object giống như thế này:
public class SomeClassName: ICustomerRepository { public Customer GetCustomer(int id) { return new Customer { FirstName = "John", LastName = "Doe" }; } }Như bạn có thể thấy, class thực thi từ interface ICustomerRepository trả về giá trị có dạng “hardcoded”. Thay vì sử dụng Moq (hay bất kỳ framework nào khác), chúng ta có thể tự làm điều này, nhưng mà dùng framework làm cho mọi thứ đơn giản hơn.
Kết luậnMoq là framework đầu tiên mà tôi dùng do tính đơn giản cũng như số lượng tính năng mà nó mang lại. Việc giải thích các khái niệm mà M oq triển khai cho thành viên trong team thường rất đơn giản và dễ hiểu. Lưu ý rằng, ví dụ trong bài viết này là ví dụ đơn giản nhất, còn nhiều trường hợp khác test rất phức tạp cũng có thể dùng Moq. Trong phần tiếp theo sẽ giới thiệu rõ hơn cách sử dụng Moq. Happy coding!
Phần 1: Cách Viết Unit Test Trong C#
Bài viết sẽ hướng dẫn các bạn từng bước tạo, chạy và tối ưu Unit tests sử dụng Microsoft unit test framework. Chúng ta sẽ bắt với 1 project C# đang trong giai đoạn phát triển, chúng ra sẽ tạo các tests và chạy nó, xem xét kết quả.
Yêu cầu – Visual Studio 2023 – xem code ví dụ tại Sample Project for Creating Unit Tests.
1.Tạo một unit test projectBạn cần tạo trước project với code ví dụ tại Sample Project for Creating Unit Tests.
Trong New Project dialog box, chọn Installed, chọn Visual C#, và chọn Test.
trong danh sách, chọn Unit Test Project.
Trong Name box, đặt tên là BankTest, và chọn OK.The BankTests project is added to the the Bank solution.
Trong BankTests project, add reference đến BankAccount (project bạn muốn viết Unit test) trong solution.
2.Tạo một test classTrong test project bạn đổi tên chúng tôi thành chúng tôi Sau đó bạn mở file chúng tôi và bạn sẽ thấy code bên dưới
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankTests { [TestClass] public class BankAccountTests { [TestMethod] public void TestMethod1() { } } }Yêu cầu của một Test class
attribute [TestClass] là bắt buộc trong Microsoft unit testing framework để được quản lý cho bất kỳ class nào chứa unit test methods
Mỏi test method phải chứa attribute [TestMethod].
3.Tạo test method đầu tiênChúng ta sẽ viết unit test cho Debit method trong class BankAccount . .
Bằng các phân tích, chúng ta thấy được Debit method có ít nhất 3 trường hợp cần test:
Method ném ra Exception ArgumentOutOfRangeException Nếu số tiền rút lớn hơn số tiền có trong tài khoản.
Method ném ra Exception ArgumentOutOfRangeException nếu số tiền rút nhỏ hơn 0.
Nếu việc kiểm tra 1 và 2 là đúng, method sẽ trừ số tiền rút ra khỏi tài khoản.
Trong thử nghiệm đầu tiên của chúng ta, chúng ta xác minh bằng một số tiền hợp lệ (số ít hơn số dư tài khoản và lớn hơn số không) và trả về một số tiền chúng ta đã xác định trước.
Tạo một test method Chúng ta cập nhật file chúng tôi như bên dưới
using Microsoft.VisualStudio.TestTools.UnitTesting; using BankAccountNS; namespace BankTests { [TestClass] public class BankAccountTests { [TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); account.Debit(debitAmount); double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); } } }Trong test method Debit_WithValidAmount_UpdatesBalance chúng ta giả định tai khoản có beginningBalance = 11.99 và chúng ta sẽ rút debitAmount = 4.55 vậy số tiền còn lại phải là expected = 7.44. Chúng ta sử dụng AreEqual method để kiểm chứng tài khoản còn lại đúng với mong muốn.
Yêu cầu của Test method
Test method phải có attribute [TestMethod].
Test method phải return void.
Test method không có tham số.
4.Build và run test
Trong Build menu, chọn Build Solution. Nếu không có lỗi, Test Explorer window sẽ xuất hiện(bên trái), Debit_WithValidAmount_UpdatesBalance sẽ được liệt kê trong nhóm Not Run Tests.
Chọn Run All để run test. Trong Test Explorer status bar bắt đầu run. sau khi kết thúc test, thanh bar sẽ chuyển sang màu xanh lá test methods pass, hoặc đỏ nếu tests fail.
5.Sửa lỗi và chạy lại TestChúng ta cần kiểm tra lại method Debit.
Nguyên nhân lỗi
m_balance += amount;Cần sửa lại thành
m_balance -= amount;Chạy lại test Trong Test Explorer, chọn Run All để chạy lại hết các test method. Thanh trạng thái chuyển sanh màu xanh lá, và test được chuyển sang Passed Tests group.
Phần 2: Sử dụng Unit Test để cải thiện code
Bài viết Phần 1: Cách viết Unit Test trong C Sharp được dịch từ
https://msdn.microsoft.com/en-us/library/ms182532.aspx#BKMK_Create_a_unit_test_project
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.
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
Hướng Dẫn Viết Unit Test Trong Angular
Lợi ích của Unit test
Cải thiện design: Bắt tay vào code mà không để ý quá nhiều đến design là một lỗi phổ biến của các developer, việc viết unit test sẽ bắt buộc bạn phải suy nghĩ, thậm chí nghĩ đi nghĩ lại về design
Dễ dàng refactor: bởi vì bạn đã có các case test đảm bảo code của bạn chạy đúng như mong đợi, bạn có thể dễ dàng refactor code mà không lo sẽ tạo ra những bug mới
Test là một tài liệu về spec: nếu viết test chuẩn và đủ case, thì chỉ cần đọc test, ta cũng có thể hiểu rõ spec còn nhanh hơn cả đọc code
Việc viết test giúp developer tự tin hơn
Bạn có thể cho rằng việc viết test quá tốn thời gian, nhất là viết test FE, có khi nó còn lâu hơn cả viết code nữa, nhưng mình nghĩ nó sẽ giúp tiết kiệm thời gian hơn khi bạn muốn refactor code hay phát triển tính năng mới, giảm thiểu được cả thời gian để fix bug so với việc không viết test.
Giờ chúng ta sẽ bắt tay vào một ví dụ nhỏ nhưng khá đầy đủ sử dụng Angular, Jasmine và Karma. Phần tiếp theo của bài viết sẽ đề cập đến những điều sau:
Giải thích một chút về Karma và Jasmine
Karma config
Tạo một file test đơn giản
Test angular form
Test component với service
Tạo project Angular với Jasmine và KarmaInstall angular-cli và tạo project mới
Giải thích 1 chút về Jasmine và Karma không lại bảo nãy giờ cứ nói hoài mà không biết là gì
Jasmine: là một framework dùng để viết test, nó có các function có sẵn hỗ trợ viết các loại test khác nhau
Karma: là một Javascript tool được sử dụng để load ứng dụng và thực thi test của bạn. Karma sẽ được thực thi bằng dòng lệnh và sẽ hiển thị kết quả cho bạn biết mỗi khi bạn chạy trình duyệt.
Để chạy thử chỉ cần gõ ng test. Lệnh này sẽ thực thi các case test, mở trình duyệt, hiển thị kết quả trên trình duyệt và trong console.
Karma configGiờ hãy nhìn vào file Karma config được sinh ra từ angular-cli
frameworks: đây là nơi jasmine được set là framework để testing, nếu bạn muốn dùng 1 framework khác thì có thể điền vào đây.
autoWatch: nếu nó được set là true, test sẽ chạy chế độ watch mode, có nghĩa là mỗi khi bạn thay đổi bất cứ dòng code nào trong file test và lưu lại, nó sẽ tự động build lại và chạy lại.
browsers: đây là nơi để set trình duyệt và test sẽ chạy, mặc định sẽ là Chrome, nhưng bạn có thể sử dụng trình duyệt khác bằng cách khai báo ở đây.
Bắt đầu với một file test đơn giảnLướt qua 1 chút thì ở đây chúng ta đã
import các thư viện angular testing mà chúng ta sẽ sử dụng
Import các component phụ thuộc
Sử dụng describe để bắt đầu phần viết test với title trùng với tên component test.
Sử dụng async trước mỗi case test, mục đích là để các phần code không đồng bộ có thể kết thúc trước khi tiếp tục, nó tương tự với cách dùng async lúc viết code ý.
Trước khi chạy bất cứ case test nào trong Angular, bạn cần phải config Angular testbed. Nó giúp tạo 1 môi trường cho component đang được test. Bất cứ module, component, service nào mà component bạn đang test cần, thì đều phải được đưa vào trong testbed. Cuối cùng, sau khi config xong, bạn sẽ gọi đến hàm compileComponents().
Tiếp theo, chúng ta có 2 case test. Mình sẽ giải thích từng case một:
Case đầu tiên, chúng ta sẽ kiểm tra xem component có thực sự chứa text chúng ta kì vọng trong phần title hay không. Đầu tiên, chúng ta cần 1 instance của app.component, vì vậy chúng ta sử dụng hàm createComponent(), tạo 1 đối tượng fixture, cho phép chúng ta tạo 1 instance của component. Sau khi đã có instance của app.component, chúng ta có thể kiểm tra giá trị của thuộc tính title có giống với text chúng ta kì vọng hay không bằng hàm toEqual().
Test angular formBắt đầu với 1 file HTML chúng tôi có chứa form
Form này khá đơn giản nên không cần giải thích gì nhiều. Nút submit sẽ bị disabled nếu form invalid.
Tiếp theo đến contact.component.ts
Giờ đến file test
Trông phức tạp hơn nhiều so với file test trên nhỉ, đừng lo, mình sẽ giải thích cụ thể từng phần đây
Đầu tiên vẫn là phần import, không có gì khác lắm, ngoại trừ import thêm By để chọn element từ DOM.
Trong beforeEach(), ta dùng promise cho hàm compileComponent(), khi promise được resolved, chúng ta sẽ tạo instance của component trong này luôn, để đỡ phải viết lại trong mỗi case test.
Case đầu tiên chỉ đơn giản là kiểm tra giá trị thuộc tính text của component.
Case thứ 2 kiểm tra giá trị của biến submittedlà true khi hàm onSubmit() được gọi đến.
Case thứ 4 kiểm tra khi truyền vào những giá trị invalid, thuộc tính valid của form sẽ là false.
Cuối cùng, case thứ 5 ngược lại với case thứ 4, khi truyền vào những giá trị valid, thuộc tính valid của form sẽ là true.
Trước khi kết thúc bài viết, chúng ta sẽ đến với phần cuối cùng, là làm sao xử lý service khi component cần test sử dụng chúng.
Test component với serviceVí dụ một component sử dụng service
Component này sẽ gọi sang service để lấy danh sách users, lúc viết test thì việc lấy users từ đâu cũng ko quan trọng, nên ta có thể tạo component mocking cho service này.
Về cơ bản thì cũng giống mấy ví dụ trên, chỉ khác ở chỗ khi UserService được gọi đến, nó sẽ thay bằng UserServiceMock. UserServiceMock là một dummy service để trả về dummy data để chạy test. Vậy thôi, đó là cách bạn nên dùng để mock service cho component.
Nguồn: https://medium.com/swlh/angular-unit-testing-jasmine-karma-step-by-step-e3376d110ab4
Cập nhật thông tin chi tiết về Viết Unit Test Trong C# Với Nunit 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!