Là các bài kiểm tra tích hợp có nghĩa là lặp lại tất cả các bài kiểm tra đơn vị?


36

Giả sử tôi có một chức năng (được viết bằng Ruby, nhưng mọi người nên hiểu):

def am_I_old_enough?(name = 'filip')
   person = Person::API.new(name)
   if person.male?
      return person.age > 21
   else
      return person.age > 18
   end
end

Trong thử nghiệm đơn vị tôi sẽ tạo ra bốn thử nghiệm để bao gồm tất cả các kịch bản. Mỗi người sẽ sử dụng Person::APIđối tượng giả với các phương thức male?còn sơ khai và age.

Bây giờ nói đến việc viết các bài kiểm tra tích hợp. Tôi cho rằng Person :: API không nên bị chế giễu nữa. Vì vậy, tôi sẽ tạo chính xác bốn trường hợp thử nghiệm giống nhau, nhưng không chế nhạo đối tượng Person :: API. Đúng không?

Nếu có, thì điểm của việc viết bài kiểm tra đơn vị là gì, nếu tôi chỉ có thể viết bài kiểm tra tích hợp giúp tôi tự tin hơn (khi tôi làm việc trên các vật thể thực sự, không phải cuống hay giả)?


3
Chà, một trong những điểm là, bằng cách chế nhạo / kiểm tra đơn vị nó, bạn có thể tách biệt mọi vấn đề với mã của mình. Nếu kiểm tra tích hợp thất bại, bạn không biết mã của ai bị hỏng, mã của bạn hoặc API.
Chris Wohlert

9
Chỉ có bốn bài kiểm tra? Bạn có sáu độ tuổi ranh giới bạn nên kiểm tra: 17, 18, 19, 20, 21, 22 ...;)
David Arno

22
@FilipBartuzi, tôi giả sử phương pháp đang kiểm tra xem một người đàn ông trên 21 tuổi chẳng hạn? Như hiện tại được viết, nó không làm điều đó, nó chỉ đúng nếu chúng trên 22 tuổi. "Trên 21" trong tiếng Anh có nghĩa là "21+". Vì vậy, có một lỗi trong mã của bạn. Các lỗi như vậy được bắt bằng cách kiểm tra các giá trị biên, tức là 20, 21, 22 đối với nam, 17,18,19 đối với nữ trong trường hợp này. Vì vậy, ít nhất sáu bài kiểm tra là cần thiết.
David Arno

6
Chưa kể các trường hợp 0 ​​và -1. Nó có nghĩa là gì đối với một người được -1 tuổi? Mã của bạn nên làm gì nếu API của bạn trả về một thứ gì đó vô nghĩa?
RubberDuck

9
Điều này sẽ dễ kiểm tra hơn rất nhiều nếu bạn truyền đối tượng người làm tham số.
JeffO

Câu trả lời:


72

Không, kiểm tra tích hợp không nên chỉ nhân đôi phạm vi kiểm tra đơn vị. Họ có thể nhân đôi một số phạm vi bảo hiểm, nhưng đó không phải là vấn đề.

Điểm của kiểm tra đơn vị là đảm bảo rằng một chút chức năng cụ thể hoạt động chính xác và hoàn toàn như dự định. Một bài kiểm tra đơn vị am_i_old_enoughsẽ kiểm tra dữ liệu với các độ tuổi khác nhau, chắc chắn là các dữ liệu gần ngưỡng, có thể là tất cả các độ tuổi xảy ra ở người. Sau khi bạn viết bài kiểm tra này, tính toàn vẹn của am_i_old_enoughsẽ không bao giờ bị nghi ngờ nữa.

Điểm của kiểm tra tích hợp là xác minh rằng toàn bộ hệ thống, hoặc sự kết hợp của một số lượng lớn các thành phần thực hiện đúng khi được sử dụng cùng nhau . Khách hàng không quan tâm đến một chức năng tiện ích cụ thể mà bạn đã viết, họ quan tâm rằng ứng dụng web của họ được bảo mật đúng cách chống lại sự truy cập của người chưa thành niên, bởi vì nếu không thì các cơ quan quản lý sẽ có lừa.

Kiểm tra tuổi của người dùng là một phần nhỏ của chức năng đó, nhưng kiểm tra tích hợp không kiểm tra xem chức năng tiện ích của bạn có sử dụng giá trị ngưỡng chính xác hay không. Nó kiểm tra xem người gọi có đưa ra quyết định đúng dựa trên ngưỡng đó hay không, liệu chức năng tiện ích có được gọi hay không, liệu các điều kiện khác để truy cập có được thỏa mãn hay không, v.v.

Lý do chúng ta cần cả hai loại thử nghiệm về cơ bản là có sự bùng nổ kết hợp các kịch bản có thể xảy ra cho đường dẫn thông qua một cơ sở mã mà việc thực thi có thể thực hiện. Nếu chức năng tiện ích có khoảng 100 đầu vào có thể và có hàng trăm chức năng tiện ích, thì việc kiểm tra xem điều đúng xảy ra trong mọi trường hợp sẽ đòi hỏi nhiều, hàng triệu trường hợp thử nghiệm. Bằng cách đơn giản kiểm tra tất cả các trường hợp trong phạm vi rất nhỏ và sau đó kiểm tra các kết hợp phổ biến, có liên quan hoặc có thể xảy ra đối với các phạm vi này, trong khi giả sử rằng các phạm vi nhỏ này đã chính xác, như đã được chứng minh bằng thử nghiệm đơn vị , chúng tôi có thể đánh giá khá tự tin rằng hệ thống đang thực hiện những gì nó cần, mà không chìm đắm trong các kịch bản thay thế để kiểm tra.


6
"chúng tôi có thể nhận được một đánh giá khá tự tin rằng hệ thống đang làm những gì cần thiết, mà không chìm đắm trong các kịch bản thay thế để kiểm tra." Cảm ơn bạn. Tôi thích khi ai đó tiếp cận kiểm tra tự động với sự tỉnh táo.
jpmc26

1
JB Rainsberger có một bài nói chuyện hay về các bài kiểm tra và vụ nổ kết hợp mà bạn đang viết trong đoạn cuối, được gọi là "Các bài kiểm tra tích hợp là một trò lừa đảo" . Nó không quá nhiều về các bài kiểm tra tích hợp, nhưng vẫn khá thú vị.
Bart van Nierop

The customer doesn't care about a particular utility function you wrote, they care that their web app is properly secured against access by minors-> Đó là suy nghĩ rất thông minh, cảm ơn! Vấn đề là khi bạn làm dự án cho chính mình. Thật khó để phân chia suy nghĩ của bạn giữa việc trở thành một lập trình viên và là người quản lý sản phẩm cùng một lúc
Filip Bartuzi

14

Câu trả lời ngắn gọn là không". Phần thú vị hơn là tại sao / làm thế nào tình huống này có thể phát sinh.

Tôi nghĩ rằng sự nhầm lẫn đang phát sinh do bạn đang cố gắng tuân thủ các thực hành kiểm tra nghiêm ngặt (kiểm tra đơn vị so với kiểm tra tích hợp, chế nhạo, v.v.) đối với mã dường như không tuân thủ các thực tiễn nghiêm ngặt.

Điều đó không có nghĩa là mã là "sai", hoặc các thực tiễn cụ thể đó tốt hơn các quy tắc khác. Đơn giản là một số giả định được thực hiện bởi các thực tiễn thử nghiệm có thể không áp dụng trong tình huống này và nó có thể giúp sử dụng một mức độ "nghiêm ngặt" tương tự trong thực tiễn mã hóa và thực hành thử nghiệm; hoặc ít nhất, để thừa nhận rằng chúng có thể bị mất cân bằng, điều này sẽ khiến một số khía cạnh không thể áp dụng hoặc dư thừa.

Lý do rõ ràng nhất là chức năng của bạn đang thực hiện hai nhiệm vụ khác nhau:

  • Nhìn lên Persondựa trên tên của họ. Điều này đòi hỏi phải thử nghiệm tích hợp, để đảm bảo nó có thể tìm thấy Personcác đối tượng có lẽ được tạo / lưu trữ ở nơi khác.
  • Tính xem a Personcó đủ tuổi hay không, dựa trên giới tính của họ. Điều này đòi hỏi thử nghiệm đơn vị, để đảm bảo tính toán thực hiện như mong đợi.

Bằng cách nhóm các tác vụ này lại với nhau thành một khối mã, bạn không thể chạy cái này mà không có cái kia. Khi bạn muốn kiểm tra các phép tính, bạn buộc phải tìm kiếm một Person(từ cơ sở dữ liệu thực hoặc từ sơ khai / giả). Khi bạn muốn kiểm tra xem tra cứu có tích hợp với phần còn lại của hệ thống không, bạn cũng buộc phải thực hiện phép tính theo tuổi. Chúng ta nên làm gì với tính toán đó? Chúng ta nên bỏ qua nó, hoặc kiểm tra nó? Đó dường như là tình huống chính xác mà bạn mô tả trong câu hỏi của mình.

Nếu chúng ta tưởng tượng một sự thay thế, chúng ta có thể tự mình tính toán:

def is_old_enough?(person)
   if person.male?
      return person.age > 21
   else 
      return person.age > 18
   end
end

Vì đây là một phép tính thuần túy, chúng tôi không cần thực hiện các thử nghiệm tích hợp trên nó.

Chúng tôi cũng có thể bị cám dỗ để viết riêng nhiệm vụ tra cứu:

def person_from_name(name = 'filip')
   return Person::API.new(name)
end

Tuy nhiên, trong trường hợp này, chức năng rất gần với Person::API.newđiều đó tôi muốn nói rằng bạn nên sử dụng nó thay vào đó (nếu tên mặc định là cần thiết, liệu nó có được lưu trữ tốt hơn ở nơi khác, như thuộc tính lớp không?).

Khi viết các bài kiểm tra tích hợp cho Person::API.new(hoặc person_from_name) tất cả những gì bạn cần quan tâm là liệu bạn có nhận lại được mong đợi hay không Person; tất cả các tính toán dựa trên tuổi được quan tâm ở nơi khác, vì vậy các bài kiểm tra tích hợp của bạn có thể bỏ qua chúng.


11

Một điểm khác tôi muốn thêm vào câu trả lời của Killian là các bài kiểm tra đơn vị chạy rất nhanh, vì vậy chúng tôi có thể có 1000 bài trong số đó. Một thử nghiệm tích hợp thường mất nhiều thời gian hơn vì nó đang gọi các dịch vụ web, cơ sở dữ liệu hoặc một số phụ thuộc bên ngoài khác, vì vậy chúng tôi không thể chạy các thử nghiệm tương tự (1000 giây) cho các kịch bản tích hợp vì chúng sẽ mất quá nhiều thời gian.

Ngoài ra, kiểm tra đơn vị thường được chạy khi xây dựng (trên máy xây dựng) và kiểm tra tích hợp chạy sau khi triển khai trên môi trường / máy.

Thông thường, một người sẽ chạy 1000 bài kiểm tra đơn vị của chúng tôi cho mỗi bản dựng và sau đó là 100 bài kiểm tra tích hợp có giá trị cao hoặc hơn sau mỗi lần triển khai. Chúng tôi có thể không đưa từng bản dựng để triển khai, nhưng điều đó không sao vì bản dựng chúng tôi thực hiện để triển khai các bài kiểm tra tích hợp sẽ được chạy. Thông thường, chúng tôi muốn giới hạn các thử nghiệm này để chạy trong vòng 10 hoặc 15 phút vì chúng tôi không muốn giữ quá trình triển khai quá lâu.

Ngoài ra, trên lịch trình hàng tuần, chúng tôi có thể chạy bộ hồi quy các bài kiểm tra tích hợp bao gồm nhiều kịch bản hơn vào cuối tuần hoặc các thời điểm khác. Việc này có thể mất nhiều thời gian hơn 15 phút vì nhiều kịch bản sẽ được đề cập, nhưng thông thường không có ai làm việc trên Sat / Sun để chúng tôi có thể mất nhiều thời gian hơn với các bài kiểm tra.


không áp dụng cho các ngôn ngữ động (tức là không có giai đoạn xây dựng)
Filip Bartuzi
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.