Thông thường khi nói về các tiêu chuẩn mã hóa, chúng ta đề cập đến mã của chính chương trình, nhưng còn các bài kiểm tra đơn vị thì sao? Có hướng dẫn tiêu chuẩn mã hóa nào đó là duy nhất cho các bài kiểm tra đơn vị không? Họ là ai?
Thông thường khi nói về các tiêu chuẩn mã hóa, chúng ta đề cập đến mã của chính chương trình, nhưng còn các bài kiểm tra đơn vị thì sao? Có hướng dẫn tiêu chuẩn mã hóa nào đó là duy nhất cho các bài kiểm tra đơn vị không? Họ là ai?
Câu trả lời:
Ngoài đỉnh đầu, tôi có thể nghĩ ra ba điểm khác biệt trong phong cách mã hóa cho mã kiểm tra.
Trong phương pháp kiểm tra đặt tên, tôi theo mô hình của shouldDoSomethingWhenSomeConditionHolds
.
Trong thử nghiệm, thông thường tuân theo mẫu khoảng cách sau:
@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
// Some lines
// of setup code
// go here.
// The action being tested happens after a blank line.
// An assertion follows another blank line.
}
Một số nhấn mạnh chỉ một khẳng định cho mỗi bài kiểm tra, nhưng điều này là xa phổ quát.
DRY (Đừng lặp lại chính mình) ít được xem xét trong mã kiểm tra hơn trong mã sản xuất. Mặc dù một số mã lặp lại nên được đặt trong phương thức setUp hoặc lớp testUtils, việc phấn đấu không lặp lại trong mã kiểm tra sẽ dẫn đến các thử nghiệm không khớp và không linh hoạt, điều này không khuyến khích tái cấu trúc.
Roy Osherove đề xuất mẫu sau để đặt tên cho các bài kiểm tra của bạn:
NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior()
Xem http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStiterias.aspx
NameOfMethodUnderTestStateUnderTestExpectedBehavior()
;)
Điều chính là phải nhớ rằng các bài kiểm tra đơn vị về cơ bản là các thông số kỹ thuật nhỏ. Điều này có nghĩa là sự nhấn mạnh phải luôn luôn dễ đọc.
Thứ nhất, điều này có nghĩa là tên phải truyền đạt rõ ràng những gì đang được thử nghiệm và những gì đang được khẳng định.
Thứ hai, mặc dù đôi khi bị lãng quên, đó là thông số kỹ thuật mà họ nên làm như vậy - chỉ định hành vi. Đó là, các bài kiểm tra đơn vị không nên chứa logic - hoặc có khả năng chúng rơi vào bẫy lặp lại chức năng của chương trình thay vì kiểm tra nó.
Đôi khi các bài kiểm tra sẽ liên quan đến các đối tượng phức tạp để thiết lập, bạn nên cố gắng tách logic thiết lập này khỏi các thử nghiệm của mình bằng cách sử dụng một cái gì đó như mẹ đối tượng hoặc trình tạo dữ liệu thử nghiệm .
Tôi sẽ làm tròn với một vài khuyến nghị cuốn sách:
Các mẫu thử nghiệm xUnit: Tái cấu trúc Mã kiểm tra: Cuốn sách tuyệt vời, một số người cho rằng nó hơi khô khan nhưng tôi không nghĩ vậy. Đi vào rất nhiều chi tiết về rất nhiều cách tổ chức kiểm tra khác nhau và làm thế nào để duy trì chúng. Có liên quan nếu bạn đang sử dụng một cái gì đó như NUnit, vv
Nghệ thuật kiểm tra đơn vị: Với các ví dụ trong .Net : Cuốn sách hay nhất về sự khéo léo của việc viết và duy trì các bài kiểm tra. Mặc dù thực sự mới nhưng tôi thấy các phần chế giễu đã có một chút ngày vì cú pháp AAA bây giờ khá chuẩn chứ không phải là một cách khác để làm điều đó.
Phát triển phần mềm hướng đối tượng, được hướng dẫn bởi các bài kiểm tra : Cuốn sách này thật tuyệt vời! Cho đến nay, cuốn sách thử nghiệm đơn vị tốt nhất và là cuốn sách tiên tiến duy nhất đưa thử nghiệm đơn vị là công dân hạng nhất trong quá trình thiết kế. Đã đọc nó khi nó là một phiên bản beta công khai và được giới thiệu kể từ đó. Ví dụ làm việc thực tế tuyệt vời được sử dụng trong suốt cuốn sách. Mặc dù vậy, tôi khuyên bạn nên đọc cuốn sách của Roy.
Đừng đặt logic trong các bài kiểm tra đơn vị của bạn. Ví dụ: giả sử bạn đang thử nghiệm một phương thức thêm, bạn có thể có một cái gì đó như thế này:
void MyTest_SaysHello()
{
string name = "Bob";
string expected = string.Format("Hello, {0}", name);
IMyObjectType myObject = new MyObjectType();
string actual = myObject.SayHello(name);
Assert.AreEqual(expected, actual);
}
Trong trường hợp cụ thể này, bạn có thể lặp lại logic tương tự như trong bài kiểm tra, vì vậy về cơ bản, bạn đang kiểm tra "1 + 1 == 1 + 1", thay vì "1 + 1 == 2", đó là Thử nghiệm "thực sự". Vì vậy, những gì bạn thực sự muốn mã kiểm tra của bạn trông giống như:
void MyTest_SaysHello()
{
string expected = "Hello, Bob";
IMyObjectType myObject = new MyObjectType();
string actual = myObject.SayHello("Bob");
Assert.AreEqual(expected, actual);
}
Tên phương thức mô tả dài. Hãy nhớ rằng, các phương thức kiểm tra không bao giờ được gọi từ mã (chúng được gọi bởi trình chạy thử nghiệm đơn vị phát hiện và gọi chúng thông qua phản xạ), do đó, thật điên rồ và có tên phương thức dài 50-80 ký tự. Quy ước đặt tên cụ thể (trường hợp lạc đà, dấu gạch dưới, "nên", "phải", "khi", "đã cho", v.v.) không thực sự quan trọng miễn là tên trả lời ba câu hỏi:
Phương pháp kiểm tra nên ngắn gọn .
Phương pháp thử nên có cấu trúc đơn giản, tuyến tính . Không có hoặc cấu trúc vòng lặp.
Các phương pháp thử nghiệm phải tuân theo mẫu "sắp xếp hành động-khẳng định" .
Mỗi bài kiểm tra nên kiểm tra một điều . Điều này thường có nghĩa là một khẳng định cho mỗi bài kiểm tra. Một bài kiểm tra như thế { Do A; Assert B; Assert C; }
nên được tái cấu trúc thành hai: { Do A; Assert B; }
và{ Do A; Assert C; }
Tránh dữ liệu ngẫu nhiên hoặc những thứ như 'DateTime.Now'
Đảm bảo rằng tất cả các thành viên bộ ghép đo được trả lại tình trạng ban đầu của họ vào cuối của bài kiểm tra (ví dụ như sử dụng một teardown )
Ngay cả khi bạn loại bỏ trùng lặp một cách tàn nhẫn trong mã sản xuất của mình, sao chép mã trong đồ đạc thử nghiệm là mối quan tâm nhỏ hơn nhiều.
Tương tự như những gì Farmboy đã đề cập, định dạng tên phương thức của tôi
<MethodName>Should<actionPerformed>When<Condition>
ví dụ
GetBalanceShouldReturnAccountBalance() {