02. (UnitTest) NUnit là gì? Viết TestCase cơ bản đầu tiên với NUnit - (Phần 1)
NUnit là gì?
- NUnit là một unit testing framework cho tất cả phiên bản .NET. NUnit ban đầu được phát triển dựa trên JUnit (framework unit testing dành cho ngôn ngữ Java). Tuy nhiên, phiên bản hiện tại NUnit đã hoàn toàn được viết lại và hỗ trợ trên nhiều nền tảng .NET.
- Framework này bao gồm một số phương thức khẳng định giá trị giúp đảm bảo rằng code cần được test hoạt động đúng với mong muốn.
- Nó cũng cũng cấp nhiều attributes để kiểm soát việc thực thi kiểm thử, thiết lập là môi trường kiểm thử hoặc loại bỏ chúng.
- Là công cụ phổ biến cho developer giúp đảm bảo rằng code của họ chất lượng cao và không có lỗi không mong muốn.
Đi vào chi tiết
Tạo class cần test
- Đầu tiên ta sẽ tạo một sln với 1 project là NUnitTutorial, sau đó tạo một project NUnitTutorial.UnitTests, thông thường project test sẽ có convention {Project cần test}.UnitTests. Tạo project UnitTests bằng cách tạo mới project và chọn project NUnit có sẵn: Sau đó thêm project reference là NUnitTutorial.
- Tiếp theo, trong project NUnitTutorial tạo một class LogAnalyzer có một method IsValidLogFileName, method này kiểm tra xem một file nào đó có đúng định dạng mong muốn, trong tình huống này thì định dạng mong muốn là txt, nếu là txt thì trả về file hợp lệ và ngược lại (Lưu ý là trong method trên tôi cố tình viết sai logic, lý do việc này bạn sẽ hiểu ở phía dưới) :
public bool IsValidLogFileName(string fileName)
{
if (fileName.EndsWith(".txt"))
{
return false;
}
return true;
}
Phương thức trên có vẻ đơn giản, nhưng cũng cần đảm bảo nó hoạt động đúng bussiness, chúng ta sẽ đi từ đơn giản trước để hiểu được những kiến thức cơ bản để có thể tạo nên một testcase.
Tạo class test
-
Trong project NUnitTutorial.UnitTests tạo một class tên là LogAnalyzerTests, thông thường class test sẽ được đặt tên theo quy tắc [Class cần test]Tests (ở đây class cần test là LogAnalyzer nên tên class test sẽ là LogAnalyzerTests). Ở class test, chúng ta sẽ tạo những method test ở đây, cách đặt tên method test theo quy tắc sau: [UnitName][ScenarioUnderTest][ExpectedBehavior].
- UnitName: tên của method, nhóm methods hoặc class cần test.
- ScenarioUnderTest: kịch bản mà test case này cần kiểm tra, ví dụ: user không tồn tại, trường dữ liệu null, dữ liệu sai định dạng...
- ExpectedBehavior: kết quả mong đợi cho kịch bản ở trên nếu nó xảy ra là gì.
-
NUnit sử dụng attribute để nhận dạng và load các test case, chúng cần ít nhất hai thuộc tính sau để có thể chạy:
- [TestFixture]: đánh dấu rằng một class chứa các test case.
- [Test]: đánh dấu đây là một method test, đặt attribute này trên method test.
-
Áp dụng quy tắc đặt tên method test và kịch bản truyền vào một file không hợp lệ và kết quả mong muốn là false, và một số atribute cơ bản nhất ta được class như sau:
[TestFixture]
public class LogAnalyzerTests
{
[Test]
public void IsValidFileName_BadExtension_ReturnsFalse()
{
}
}
Lưu ý: NUnit bắt buộc method test luôn để phạm vi truy cập là public, kiểu trả về là void hoặc Task, thông thường những trường hợp cơ bản sẽ không cần parameter, nếu có parameter thì nó sẽ đọc riêng từ attr của NUnit (phần có param sẽ trình bày phía sau).
- Ở trên ta đã viết được một method test là IsValidFileName_BadExtension_ReturnsFalse, tiếp theo chúng ta sẽ viết nội dung test, trước hết để viết nội dung test thì chúng ta tìm hiểu về AAA pattern trong việc viết test. AAA là viết tắt của Arrange - Act - Assert, đây là ba hành động thông thường trong một test case với NUnit:
- Arrange: tạo, thiết lập những giá trị, tài nguyên, dữ liệu cần thiết cho việc test.
- Act: thông thường chỉ là một dòng gọi đến phương thức cần test.
- Assert: kiểm tra xem kết quả ở Act có đúng với kết quả ta mong muốn hay không?
Ở đây là đoạn code áp dụng pattern trên, trong đoạn code này việc kiểm tra khẳng định dùng lớp Assert của NUnit, ta sẽ tìm hiểu ở phần sau:
[Test]
public void IsValidFileName_BadExtension_ReturnsFalse()
{
// Arrange
LogAnalyzer analyzer = new LogAnalyzer();
// Act
bool result = analyzer.IsValidLogFileName("filewithbadextension.foo");
// Assert
Assert.False(result);
}
Lớp Assert
-
Trước khi đi đến phần tiếp, chúng ta sẽ tìm hiểu về lớp Assert trong NUnit. Lớp Assert chứa các method static và nằm trong namespace NUnit.Framework. Là cầu nối giữa mã của bạn và NUnit framework, mục đích của nó là để kiểm tra một giả định nào đó có đúng với mong muốn hay không? Nếu khẳng định của bạn khác với mong đợi, NUnit sẽ nhận ra đây là một test fails và thông báo cho bạn. Bạn có thể chỉnh sửa nội dung thông báo hiện ra.
-
Lớp Assert có rất nhiều phương thức, sau đây là một số khẳng định hay sử dụng:
- Assert.True(condition): kết quả truyền vào nếu là true thì test case pass và ngược lại.
- Assert.False(condition): kết quả truyền vào nếu là false thì test case pass và ngược lại.
- Assert.That(actualObject, expectedObject): kiểm tra khẳng định của kết quả thực tế và kết quả mong đợi.
- Assert.AreEqual(expectedObject, actualObject, message): ở đây có thêm param message để chỉnh sửa nội dung thông báo nếu test case fails: Ví dụ: Assert.AreEqual(false, result, ''Thông báo lỗi là gì")
- Assert.AreSame(expectedObject, actualObject, message): tương tự.
Trong những method của lớp Assert thường có param cuối cùng là message để hiển thị rõ lỗi không mong đợi, nó là một tùy chọn. Và tôi không khuyến khích sử dụng nó, thay vì đó hãy đặt tên method test một cách rõ ràng và dễ hiểu.
Chạy test case đầu tiên
- Good, bây giờ chúng ta sẽ chạy test case vừa rồi viết, chúng ta vào Visual Studio, vào class test ấn chuột phải chọn Run Tests hoặc tổ hợp phím Ctrl + R, T.
- Kết quả như sau: Ồ, test case này fails, chúng ta đọc lỗi ở phần Message nhé. Kết quả mong đợi là False nhưng thực tế là trả về True. Khác với mong đợi của chúng ta khi viết method này? Hãy thử tưởng tượng, nếu không viết Unit Test thì khi nào chúng ta mới phát hiện ra lỗi này? Có phải là khi release lên môi trường dev hoặc test rồi dùng giao diện hay chạy API thử thì mới phát hiện? Với Unit Test thì ta chưa cần tốn công sức thực hiện một loạt các thao tác đó, ta đã có thể đảm bảo các trường hợp có đúng hay không? Ở đây ta phát hiện ra kết quả sai mong đợi là do code sai logic bussiness, bây giờ ta sẽ sửa lại cho đúng:
public bool IsValidLogFileName(string fileName)
{
if (!fileName.EndsWith(".txt"))
{
return false;
}
return true;
}
Chạy lại test case và case này sẽ pass:
Kết luận
Trong bài viết này chúng ta đã tìm hiểu NUnit là gì, một số Attr, các method trong lớp Assert của NUnit framework, cùng với quy tắc đặt tên project, class, method test sau đó chạy được test case đầu tiên. Trong bài sau chúng ta sẽ tìm hiểu thêm về một số Attr nữa trong NUnit và một số quy tắc trong việc viết Unit Test.
All rights reserved