2008-11-28 49 views
7

Tôi đã đọc một chút về thử nghiệm đơn vị và đã tự hỏi làm thế nào bạn kiểm tra đơn vị. Rõ ràng đơn vị thử nghiệm là nghĩa vụ phải phá vỡ một chương trình xuống thành "đơn vị" rất nhỏ và chức năng kiểm tra từ đó.Làm thế nào để bạn kiểm tra đơn vị?

Nhưng tôi tự hỏi, có đủ để đơn vị kiểm tra một lớp học không? Hay bạn lấy nó hơn nữa và các thuật toán kiểm tra đơn vị, công thức, v.v ...? Hoặc bạn có mở rộng nó đến các trang asp kiểm tra đơn vị/chức năng? Hay bạn thử nghiệm đơn vị ở tất cả?

Trả lời

4

Nhưng tôi tự hỏi, có đủ để đơn vị kiểm tra một lớp học không? Hay bạn lấy nó hơn nữa và các thuật toán kiểm tra đơn vị, công thức, v.v ...? Hoặc bạn có mở rộng nó đến các trang asp kiểm tra đơn vị/chức năng? Hay bạn thử nghiệm đơn vị ở tất cả?

Thuật toán phải nằm trong lớp và tự động phải là Đơn vị được kiểm tra.Một công thức nằm trong lớp như một hàm và chúng cũng là đơn vị cũng được thử nghiệm. Kiểm tra đơn vị kiểm tra hành vi, trạng thái và tất cả những thứ có thể được kiểm tra cho đơn vị phát triển nhỏ nhất. Vì vậy, có, thuật toán được kiểm tra với tất cả các chi tiết của nó. Sau đó, khi bạn có các lớp sử dụng lớp khác, bạn sẽ thực hiện các bài kiểm tra tích hợp (các bài kiểm tra này thường được kiểm tra bằng các chương trình Kiểm tra Đơn vị). Điều này sẽ giống nhau nhưng ở mức cao hơn.

2

i kiểm tra đơn vị tính năng, không phải là phương pháp hoặc lớp học riêng lẻ. Chi phí của việc viết và duy trì các bài kiểm tra đơn vị không phải là không đáng kể, và nói chung tôi không khuyên bạn nên viết các bài kiểm tra đơn vị cho mỗi chút mã. Tuy nhiên, các tính năng thử nghiệm đơn vị là đáng giá vì các tính năng là những gì mà khách hàng đang trả tiền cho bạn.

1

Chúng tôi thường lập trình trong thư viện Java cho máy. Một chương trình thường được hình thành bởi hơn hai mươi thư viện vì vậy những gì chúng tôi làm là kiểm tra đơn vị từng thư viện. Nó không phải là một nhiệm vụ dễ dàng vì nhiều lần các thư viện được ghép nối giữa nhau và điều này không nhiều lần có thể.

Mã của chúng tôi không phải là mô-đun như chúng tôi muốn nhưng chúng tôi phải sống với nó cho các vấn đề tương thích và ngắt khớp có nghĩa là phá vỡ khả năng tương thích trong nhiều trường hợp quá.

1

Tôi thử nghiệm nhiều giao diện công cộng nhất có thể (tôi đang sử dụng C++ nhưng ngôn ngữ không thực sự quan trọng). Khía cạnh quan trọng nhất là viết các bài kiểm tra khi bạn viết mã (ngay trước hoặc sau). Từ kinh nghiệm, tôi đảm bảo với bạn rằng việc phát triển theo cách này sẽ dẫn đến mã đáng tin cậy hơn. và sẽ làm cho nó dễ dàng hơn để duy trì (như những thay đổi mà phá vỡ các bài kiểm tra sẽ được rõ ràng ngay lập tức). Đối với tất cả các dự án, tôi khuyên bạn nên kiểm tra tài khoản ngay từ đầu - nếu bạn viết một lớp phụ thuộc vào một lớp phức tạp, sau đó sử dụng một giao diện để bạn có thể 'thử' các đối tượng phức tạp hơn khi thử nghiệm (truy cập cơ sở dữ liệu , truy cập mạng, v.v.)

Viết nhiều thử nghiệm sẽ xuất hiện để làm chậm bạn xuống nhưng trên thực tế, trong suốt thời gian tồn tại của một dự án, bạn sẽ mất ít thời gian hơn để sửa lỗi.

Kiểm tra thường xuyên - nếu nó có thể bị hỏng, nó sẽ - và tốt hơn nó phá vỡ khi thử nghiệm của bạn hơn khi khách hàng đang cố gắng sử dụng nó.

2

Đây là những hướng dẫn chung tôi thấy hữu ích cho kiểm tra đơn vị:

1) Xác định đối tượng Boundary (Win/WebForms, CustomControls vv).

2) Xác định kiểm soát các đối tượng (đối tượng lớp Business)

3) Hãy chắc chắn để Viết Đơn vị kiểm tra ít nhất để kiểm soát các đối tượng phương pháp nào gọi bởi đối tượng ranh giới.

Bằng cách này bạn sẽ chắc chắn rằng bạn đang bao gồm các khía cạnh chức năng chính (tính năng) của ứng dụng và bạn không có nguy cơ thử nghiệm vi mô (trừ khi bạn muốn).

4

Tôi sử dụng các bài kiểm tra đơn vị làm công cụ để đánh giá liệu một cái gì đó vẫn hoạt động hay không, sau khi đã thực hiện một số thay đổi đối với mã (ví dụ: refactoring, fixing a bug, add a enhancement). Vì tôi sử dụng Java, các bài kiểm tra đơn vị phần lớn được tự động sử dụng JUnit. Ijust gọi một kịch bản dòng lệnh và chạy hàng trăm kiểm tra để xác minh rằng mã không bị hỏng.

1

Nó không đủ để chỉ đơn vị kiểm tra một lớp học. Các lớp học làm việc cùng nhau và điều đó cũng phải được kiểm tra.

Có đơn vị nhiều hơn chỉ là lớp học:

  • mô-đun,
  • lớp,
  • khuôn khổ.

Và có tất nhiên các dạng thử nghiệm khác nhau, ví dụ: hội nhập và chấp nhận.

Tôi thử nghiệm những điều tôi thấy khó khăn, những điều tôi nghĩ có thể thay đổi, giao diện và những điều tôi phải sửa. Và tôi chủ yếu bắt đầu với thử nghiệm, cố gắng đảm bảo rằng tôi hiểu vấn đề tôi đang cố giải quyết.

2

Tôi là một người thử nghiệm đơn vị khá cẩu thả, nhưng sau đó tôi là một học giả, vì vậy hầu hết các chương trình của tôi là kịch bản để sử dụng riêng của tôi hoặc các chương trình nặng hơn cho nghiên cứu của tôi. Rất nhiều công việc của tôi là trên trình biên dịch, vì vậy việc kiểm tra đơn vị cổ điển khó khăn --- ví dụ như không dễ dàng để kiểm tra đơn vị cấp phát đăng ký trừ khi bạn biên dịch bao quanh nó, và tại thời điểm đó bạn cũng có thể kiểm tra hồi quy.

Nhưng có một số ngoại lệ lớn. Tôi làm rất nhiều trong số các kịch bản trong Lua, được chia thành các mô-đun (một tệp nguồn có thể và thường là một mô-đun). Nếu tôi đang làm việc trên các công cụ mới, như chúng ta hãy nói các tiện ích để tương tác với trình bao, tôi sẽ chỉ thả một số xét nghiệm đơn vị bên trong mô-đun chính nó. trong đó chúng chạy mỗi khi mô-đun được tải. Lua quá nhanh đến mức thường không quan trọng. Dưới đây là một số ví dụ:

 
assert(os.quote [[three]] == [[three]]) 
assert(os.quote [[three"]] == [['three"']]) 
assert(os.quote [[your mama]] == [['your mama']]) 
assert(os.quote [[$i]] == [['$i']]) 

Nếu tôi là một con chó tốt Tôi viết một số xét nghiệm đơn giản như trước khi tôi viết hàm.

Điều khác tôi làm với thử nghiệm đơn vị là nếu nó khó khăn, tôi kiểm tra luật đại số sử dụng QuickCheck, là công cụ kiểm tra ngẫu nhiên cần được xem. Đó là công cụ duy nhất mà tôi từng sử dụng để kiểm tra đơn vị thú vị. Một liên kết có treo lơ lửng, nhưng bạn có thể tìm thấy Tom Moertel's story about the ICFP programming contest trên blog của mình.

Hy vọng bạn thấy điều này hữu ích. QuickCheck đã lưu thịt xông khói của tôi nhiều lần. Gần đây nhất, tôi đã thử nghiệm mã cho phép biến đổi cosin rời rạc bằng cách sử dụng số học hợp lý chính xác --- sau đó chuyển nó sang C!

1

Chỉ vì nó biên dịch không có nghĩa là nó chạy! Đó là bản chất của thử nghiệm đơn vị. Hãy thử mã.Hãy chắc chắn rằng nó đang làm những gì bạn nghĩ rằng nó đã làm.

Cho phép đối mặt với nó, nếu bạn chuyển đổi ma trận từ MATLAB, thật dễ dàng để làm hỏng dấu cộng hoặc dấu trừ ở đâu đó. Đó là loại điều khó thấy. Nếu không thử nó, bạn chỉ không biết liệu nó có hoạt động chính xác hay không. Gỡ lỗi 100 dòng mã dễ hơn rất nhiều so với việc gỡ lỗi 100.000 dòng mã.


Một số người coi đây là cực đoan. Họ cố gắng kiểm tra mọi điều có thể tưởng tượng được. Thử nghiệm trở thành một kết thúc cho chính nó.

Điều đó có thể hữu ích sau này trong các giai đoạn bảo trì. Bạn có thể nhanh chóng kiểm tra để đảm bảo cập nhật của bạn không bị hỏng.

Nhưng chi phí liên quan có thể làm tê liệt phát triển sản phẩm! Và những thay đổi trong tương lai làm thay đổi chức năng có thể bao gồm chi phí cập nhật kiểm tra rộng rãi.

(Nó cũng có thể nhận được lộn xộn đối với đa luồng và thực hiện lệnh tùy ý với.)


Cuối cùng, trừ khi có chỉ định khác, kiểm tra của tôi cố gắng để rơi xuống đất giữa.

Tôi tìm cách thử nghiệm ở mức chi tiết lớn hơn, cung cấp phương tiện xác minh chức năng cơ bản chung. Tôi không lo lắng quá nhiều về mọi tình huống hàng rào có thể xảy ra. (Đó là những gì các macro ASSERT dành cho.)

Ví dụ: Khi tôi viết mã để gửi/nhận tin nhắn qua UDP, tôi đã thử nghiệm nhanh để gửi/nhận dữ liệu bằng cách sử dụng lớp đó qua giao diện loopback. Không có gì lạ mắt. Nhanh chóng, nhanh chóng, & mã bẩn. Tôi chỉ muốn thử nó. Để chắc chắn rằng nó đã thực sự làm việc trước khi tôi xây dựng một cái gì đó trên đầu trang của nó.

Ví dụ khác: Đọc hình ảnh camera từ máy ảnh Firewire. Tôi đã ném nhanh & ứng dụng GTK bẩn để đọc hình ảnh, xử lý chúng và hiển thị chúng trong thời gian thực. Những người khác gọi đó là thử nghiệm tích hợp. Nhưng tôi có thể sử dụng nó để xác minh giao diện Firewire của mình, lớp hình ảnh của tôi, biến đổi RGB RGGB-> RGB của tôi, định hướng hình ảnh của tôi & căn chỉnh, ngay cả khi máy ảnh được lắp đặt lộn ngược một lần nữa. Thử nghiệm chi tiết hơn sẽ chỉ được bảo đảm nếu điều này đã chứng minh là không đủ.

Mặt khác, ngay cả đối với một cái gì đó đơn giản như:

template<class TYPE> inline TYPE MIN(const TYPE & x, const TYPE & y) { return x > y ? y : x; } 
template<class TYPE> inline TYPE MAX(const TYPE & x, const TYPE & y) { return x < y ? y : x; } 

Tôi đã viết một 1 dòng HIỂN THỊ vĩ mô để chắc chắn rằng tôi đã không sai lầm dấu:

SHOW(MIN(3,4)); SHOW(MAX(3,4)); 

Tất cả Tôi muốn làm là để xác minh rằng nó đã làm những gì nó nên làm trong trường hợp chung. Tôi lo lắng ít hơn về cách nó xử lý NaN/+ -Infinity/(double, int) hơn là một trong các đồng nghiệp đã quyết định thay đổi thứ tự đối số và goofed.


Công cụ khôn ngoan, có rất nhiều công cụ kiểm tra đơn vị trên mạng. Nếu nó giúp bạn, nhiều quyền lực hơn cho bạn. Nếu không, bạn không thực sự cần phải quá ưa thích.

tôi sẽ thường viết một chương trình thử nghiệm mà bãi dữ liệu vào và ra khỏi một lớp học, và sau đó in nó tất cả ra ngoài với một chương trình vĩ mô:

#define SHOW(X) std::cout << # X " = " << (X) << std::endl 

(Ngoài ra, nhiều người trong lớp học của tôi có thể tự nhận in bằng một built-in hành < < (ostream &) phương pháp. Đây là một kỹ thuật khá hữu ích để gỡ lỗi cũng như để thử nghiệm!)

Makefiles có thể được trivially mở rộng để tự động tạo tập tin đầu ra từ các chương trình kiểm tra, và để tự động so sánh (diff) các tệp đầu ra này với kết quả đã biết (được xem xét).

Không ưa thích, có lẽ hơi kém thanh lịch hơn, nhưng khi kỹ thuật thực hiện điều này rất hiệu quả, nhanh chóng triển khai và chi phí rất thấp. (Điều nào có lợi thế khi người quản lý của bạn từ chối lãng phí thời gian vào công cụ kiểm tra đó.)


Một ý nghĩ cuối cùng tôi sẽ để lại cho bạn. Điều này sẽ làm cho tôi bị đánh dấu xuống, vì vậy KHÔNG làm điều đó!

Cách đây một thời gian, tôi cần một chương trình thử nghiệm. Đó là một yêu cầu có thể giao được. Bản thân chương trình phải xác minh rằng một lớp khác đang hoạt động đúng. Nhưng nó không thể truy cập datafiles bên ngoài. (Chúng tôi không thể dựa vào nơi chương trình sẽ được định vị liên quan đến bất kỳ thứ gì khác. Không có đường dẫn tuyệt đối.) Khuôn khổ kiểm thử đơn vị cho dự án không tương thích với trình biên dịch mà tôi đã được yêu cầu sử dụng. Nó cũng phải ở trong một tập tin. Hệ thống makefile của dự án không hỗ trợ liên kết nhiều tệp với nhau cho một chương trình thử nghiệm thấp. (Các chương trình ứng dụng, chắc chắn. Họ có thể sử dụng thư viện. Nhưng chỉ có một tập tin duy nhất cho mỗi chương trình thử nghiệm.)

Vì vậy, Thiên Chúa tha thứ cho tôi, tôi "đã phá vỡ các quy tắc" ...

< xấu hổ >
Tôi đã sử dụng các macro. Khi một macro #define được đặt, dữ liệu được ghi vào tệp .c thứ hai làm bộ khởi tạo cho mảng cấu trúc. Sau đó, khi phần mềm được biên dịch lại, và tệp .c thứ hai (với mảng cấu trúc) đã đượC#included và macro #define không được thiết lập, nó đã so sánh kết quả mới so với dữ liệu đã lưu trước đó. Có, tôi # bao gồm tệp .c. O 'sự xấu hổ của tất cả.
</xấu hổ >

Nhưng nó có thể được thực hiện ...

Các vấn đề liên quan