Làm thế nào để bạn viết trường hợp kiểm tra đơn vị?


13

Đôi khi tôi kết thúc việc viết các trường hợp thử nghiệm đơn vị cho mã mà các nhà phát triển khác đã viết. Có những lúc tôi thực sự không biết nhà phát triển đang cố gắng làm gì (phần kinh doanh) và tôi chỉ thao tác với trường hợp thử nghiệm để có được đường màu xanh lá cây. Là những điều bình thường trong ngành công nghiệp?

Xu hướng bình thường là gì? Các nhà phát triển có nghĩa vụ phải viết các trường hợp thử nghiệm đơn vị cho mã do họ tự viết không?


2
"Dint"? "Dint" có nghĩa là gì?
S.Lott

Câu trả lời:


12

Hãy thử đọc bài đăng trên blog này: Viết bài kiểm tra đơn vị lớn: Thực tiễn tốt nhất và tồi tệ nhất .

Nhưng có vô số người khác trên web.

Trả lời trực tiếp câu hỏi của bạn ...

  1. "Xu hướng bình thường" - Tôi đoán điều này có thể khác với nơi này, điều bình thường đối với tôi có thể là kỳ lạ đối với người khác.
  2. Tôi sẽ nói (trong tùy chọn của tôi) nhà phát triển viết mã nên viết thử nghiệm, lý tưởng nhất là sử dụng các phương thức như TDD, nơi bạn sẽ viết thử nghiệm trước mã. Nhưng những người khác có thể có phương pháp và ý tưởng khác nhau ở đây!

Và cách bạn mô tả về việc viết các bài kiểm tra (trong câu hỏi của bạn) là hoàn toàn sai !!


9

Cách tiếp cận này làm cho bài kiểm tra đơn vị không có giá trị.

Bạn cần phải kiểm tra đơn vị thất bại khi một số hành động thực tế không hoạt động như dự định. Nếu bạn không làm như vậy và thậm chí có thể viết bài kiểm tra trước mã để kiểm tra, thì giống như có báo động khói không hoạt động.


8
Điều này hoàn toàn không đúng. Hay đúng hơn, đó là sự thật trong một thế giới lý tưởng, nhưng than ôi, thường thì chúng ta cách xa điều đó. Xem xét việc có mã kế thừa mà không cần kiểm tra và không có thông số kỹ thuật, và không có ai có thể tin cậy cho bạn biết chi tiết từng phút, một đoạn mã cụ thể được cho là chính xác để làm gì (đây thực tế trong một tỷ lệ lớn các dự án hiện có). Ngay cả trong trường hợp này, vẫn có thể viết các bài kiểm tra đơn vị để khóa trạng thái hiện tại của mã và để đảm bảo rằng bạn không phá vỡ bất cứ điều gì với tái cấu trúc, sửa lỗi hoặc tiện ích mở rộng trong tương lai.
Péter Török

2
Ngoài ra, tôi đoán bạn có nghĩa là "viết bài kiểm tra sau khi kiểm tra mã" phải không?
Péter Török

@ Péter, từ ngữ đã sai - bạn đã hiểu đúng. Nhưng, nếu bạn quyết định viết bài kiểm tra, họ nên làm một cái gì đó có ích. Chỉ cần gọi mã một cách mù quáng nói rằng đó là một thử nghiệm, theo ý kiến ​​của tôi - không phải thử nghiệm.

ørn, nếu bạn muốn nói rằng chúng tôi phải có những khẳng định có ý nghĩa trong các thử nghiệm đơn vị của chúng tôi, để xác minh rằng mã được thử nghiệm thực sự làm những gì chúng tôi nghĩ nó làm, tôi hoàn toàn đồng ý.
Péter Török

3

Nếu bạn không biết chức năng làm gì thì bạn không thể viết bài kiểm tra đơn vị cho nó. Đối với tất cả những gì bạn biết, nó thậm chí không làm những gì nó phải làm. Bạn cần tìm hiểu những gì nó phải làm trước tiên. THEN viết bài kiểm tra.


3

Trong thế giới thực, việc viết bài kiểm tra đơn vị cho mã của người khác là hoàn toàn bình thường. Chắc chắn, nhà phát triển ban đầu đã thực hiện điều này rồi, nhưng thường thì bạn sẽ nhận được mã kế thừa khi việc này chưa được thực hiện. Nhân tiện, không quan trọng là mã kế thừa đó đã xuất hiện từ nhiều thập kỷ trước từ một thiên hà xa, rất xa hay liệu một trong những đồng nghiệp của bạn đã kiểm tra nó trong tuần trước hay liệu bạn đã viết nó ngày hôm nay, mã kế thừa là mã mà không cần kiểm tra

Hãy tự hỏi: tại sao chúng ta viết bài kiểm tra đơn vị? Đi đến Green rõ ràng chỉ là một phương tiện để kết thúc, mục tiêu cuối cùng là chứng minh hoặc bác bỏ các xác nhận về mã đang được thử nghiệm.

Giả sử bạn có một phương pháp tính căn bậc hai của một số dấu phẩy động. Trong Java, giao diện sẽ định nghĩa nó là:

public double squareRoot(double number);

Không quan trọng bạn đã viết bản thực hiện hay liệu người khác đã làm, bạn muốn khẳng định một vài thuộc tính của SquareRoot:

  1. rằng nó có thể trả về các gốc đơn giản như sqrt (4.0)
  2. rằng nó có thể tìm thấy một gốc thực sự như sqrt (2.0) với độ chính xác hợp lý
  3. rằng nó tìm thấy sqrt (0,0) là 0,0
  4. rằng nó ném IllegalArgumentException khi được cấp số âm, tức là trên sqrt (-1.0)

Vì vậy, bạn bắt đầu viết những điều này như các bài kiểm tra cá nhân:

@Test
public void canFindSimpleRoot() {
  assertEquals(2, squareRoot(4), epsilon);
}

Rất tiếc, thử nghiệm này đã thất bại:

java.lang.AssertionError: Use assertEquals(expected, actual, delta) to compare floating-point numbers

Bạn đã quên về số học dấu phẩy động. OK, bạn giới thiệu double epsilon=0.01và đi:

@Test
public void canFindSimpleRootToEpsilonPrecision() {
  assertEquals(2, squareRoot(4), epsilon);
}

và thêm các bài kiểm tra khác: cuối cùng

@Test
@ExpectedException(IllegalArgumentException.class)
public void throwsExceptionOnNegativeInput() {
  assertEquals(-1, squareRoot(-1), epsilon);
}

và rất tiếc, một lần nữa:

java.lang.AssertionError: expected:<-1.0> but was:<NaN>

Bạn nên thử nghiệm:

@Test
public void returnsNaNOnNegativeInput() {
  assertEquals(Double.NaN, squareRoot(-1), epsilon);
}

Chúng ta đã làm gì ở đây? Chúng tôi bắt đầu với một vài giả định về cách thức hoạt động của phương pháp và thấy rằng không phải tất cả đều đúng. Sau đó, chúng tôi đã tạo ra bộ thử nghiệm Green, để viết ra bằng chứng rằng phương thức này hoạt động theo các giả định đã sửa của chúng tôi. Bây giờ khách hàng của mã này có thể dựa vào hành vi này. Nếu ai đó đã trao đổi việc triển khai thực tế của SquareRoot với một thứ khác, ví dụ như thứ gì đó thực sự đã tạo ra một ngoại lệ thay vì trả lại NaN, các thử nghiệm của chúng tôi sẽ nắm bắt được điều này ngay lập tức.

Ví dụ này là tầm thường, nhưng thường thì bạn thừa hưởng những đoạn mã lớn mà không rõ nó thực sự làm gì. Trong trường hợp đó, việc đặt một khai thác thử nghiệm xung quanh mã là bình thường. Bắt đầu với một vài giả định cơ bản về cách thức hoạt động của mã, viết các bài kiểm tra đơn vị cho chúng, kiểm tra. Nếu Green, tốt, viết nhiều bài kiểm tra. Nếu màu đỏ, bây giờ bạn có một xác nhận thất bại rằng bạn có thể chống lại một thông số kỹ thuật. Có lẽ có một lỗi trong mã kế thừa. Có thể thông số kỹ thuật không rõ ràng về đầu vào cụ thể này. Có lẽ bạn không có thông số kỹ thuật. Trong trường hợp đó, hãy viết lại bài kiểm tra sao cho ghi lại hành vi không mong muốn:

@Test
public void throwsNoExceptionOnNegativeInput() {
  assertNotNull(squareRoot(-1)); // Shouldn't this fail?
}

Theo thời gian, bạn kết thúc với một khai thác thử nghiệm ghi lại cách mã thực sự hoạt động và trở thành một loại thông số được mã hóa. Nếu bạn muốn thay đổi mã kế thừa hoặc thay thế nó bằng một mã khác, bạn có khai thác thử nghiệm để xác minh rằng mã mới hoạt động giống nhau hoặc mã mới hoạt động khác nhau theo cách được mong đợi và được kiểm soát (ví dụ: thực tế nó là mã sửa lỗi mà bạn mong đợi nó sẽ sửa). Khai thác này không phải hoàn thành vào ngày đầu tiên, trên thực tế, có một khai thác không đầy đủ hầu như luôn luôn tốt hơn so với không có khai thác nào cả. Có một khai thác có nghĩa là bạn có thể viết mã khách hàng của mình dễ dàng hơn, bạn biết nơi mong đợi mọi thứ sẽ bị phá vỡ khi bạn thay đổi một cái gì đó và nơi chúng bị phá vỡ khi cuối cùng chúng đã làm.

Bạn nên cố gắng thoát ra khỏi suy nghĩ rằng bạn phải viết bài kiểm tra đơn vị chỉ vì bạn phải làm, giống như bạn sẽ điền vào các trường bắt buộc trên một biểu mẫu. Và bạn không nên viết bài kiểm tra đơn vị chỉ để làm cho dòng màu đỏ màu xanh lá cây. Bài kiểm tra đơn vị không phải là kẻ thù của bạn, bài kiểm tra đơn vị là bạn của bạn.


1

Khi tôi viết test case (cho máy in) tôi cố gắng nghĩ về từng thành phần nhỏ .... và tôi có thể làm gì để có thể phá vỡ nó. Vì vậy, giả sử máy quét, nó sử dụng các lệnh nào (trong ngôn ngữ công việc máy in pjl) tôi có thể viết gì để kiểm tra từng bit chức năng .... Bây giờ tôi có thể làm gì để thử và phá vỡ nó.

Tôi cố gắng làm điều đó cho từng thành phần chính, nhưng khi nói đến phần mềm và không quá nhiều phần cứng, bạn muốn xem xét từng phương thức / chức năng và kiểm tra ranh giới, v.v.


1

Có vẻ như bạn đang làm việc với các nhà phát triển khác (hoặc duy trì mã được viết bởi các nhà phát triển khác), những người không thực hiện kiểm tra đơn vị. Trong trường hợp đó, tôi nghĩ rằng bạn chắc chắn muốn biết đối tượng hoặc phương thức mà bạn đang thử nghiệm phải làm gì, sau đó tạo một thử nghiệm cho nó.

Nó sẽ không phải là TDD vì bạn đã không viết bài kiểm tra trước, nhưng bạn có thể cải thiện tình hình. Bạn cũng có thể muốn tạo một bản sao của các đối tượng được thử nghiệm với các sơ khai để có thể thiết lập rằng các thử nghiệm của bạn hoạt động đúng khi mã bị lỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.