(Tại sao) điều quan trọng là một bài kiểm tra đơn vị không kiểm tra các phụ thuộc?


103

Tôi hiểu giá trị của kiểm thử tự động và sử dụng nó ở bất cứ nơi nào có vấn đề được chỉ định rõ để tôi có thể đưa ra các trường hợp kiểm thử tốt. Tuy nhiên, tôi đã nhận thấy rằng một số người ở đây và trên StackOverflow nhấn mạnh chỉ kiểm tra một đơn vị, không phải phụ thuộc vào nó. Ở đây tôi không thấy lợi ích.

Mocking / stubbing để tránh phụ thuộc kiểm tra thêm sự phức tạp cho các bài kiểm tra. Nó thêm các yêu cầu linh hoạt / tách rời nhân tạo vào mã sản xuất của bạn để hỗ trợ chế độ chế nhạo. (Tôi không đồng ý với bất kỳ ai nói rằng điều này thúc đẩy thiết kế tốt thiết kế tốt.)

Thứ hai, kiểm tra phụ thuộc có nghĩa là mã cấp thấp quan trọng được sử dụng ở mọi nơi sẽ được kiểm tra với các đầu vào khác với những người đã viết các bài kiểm tra của nó một cách rõ ràng. Tôi đã tìm thấy rất nhiều lỗi trong chức năng cấp thấp bằng cách chạy thử nghiệm đơn vị trên chức năng cấp cao mà không loại bỏ chức năng cấp thấp mà nó phụ thuộc vào. Lý tưởng nhất là những bài kiểm tra đơn vị đã được tìm thấy cho chức năng cấp thấp, nhưng những trường hợp bị bỏ lỡ luôn xảy ra.

Phía bên kia là gì? Có thực sự quan trọng là một bài kiểm tra đơn vị cũng không kiểm tra các phụ thuộc của nó không? Nếu vậy, tại sao?

Chỉnh sửa: Tôi có thể hiểu được giá trị của chế giễu phụ thuộc bên ngoài như cơ sở dữ liệu, mạng lưới, dịch vụ web, vv (Nhờ Anna Lear cho thúc đẩy tôi để làm rõ điều này.) Tôi đã đề cập đến sự phụ thuộc nội bộ , tức là các lớp khác, chức năng tĩnh vv mà không có bất kỳ phụ thuộc bên ngoài trực tiếp.


14
"áp đảo, thiết kế không tốt". Bạn sẽ phải cung cấp nhiều bằng chứng hơn thế. Rất nhiều người sẽ không gọi nó là "kỹ thuật hơn", mà là "thực hành tốt nhất".
S.Lott

9
@ S.Lott: Tất nhiên đây là chủ quan. Tôi chỉ không muốn có một loạt các câu trả lời về vấn đề này và nói rằng chế giễu là tốt bởi vì làm cho mã của bạn có thể chế giễu được sẽ thúc đẩy thiết kế tốt. Tuy nhiên, nói chung, tôi ghét việc xử lý mã được tách riêng theo những cách không có lợi ích rõ ràng hiện tại hoặc trong tương lai gần. Nếu bạn không có nhiều triển khai ngay bây giờ và không lường trước được việc có chúng trong tương lai gần, thì IMHO bạn chỉ nên mã hóa nó. Nó đơn giản hơn và không làm khách hàng nhàm chán với các chi tiết về sự phụ thuộc của đối tượng.
dsimcha

5
Tuy nhiên, nói chung, tôi ghét việc xử lý mã được ghép nối theo những cách không có cơ sở rõ ràng ngoại trừ thiết kế kém. Nó đơn giản hơn và không làm khách hàng nhàm chán với sự linh hoạt để kiểm tra mọi thứ một cách cô lập.
S.Lott

3
Tài khoản @ Tất nhiên tôi không gọi mã để được liên kết chặt chẽ hơn thiết kế đơn giản nhất, ngắn gọn nhất. Ngoài ra, khi bạn tạo ra các dòng trừu tượng sớm, chúng thường kết thúc ở những vị trí sai.
dsimcha

Xem xét cập nhật câu hỏi của bạn để làm rõ bất kỳ sự khác biệt nào bạn đang thực hiện. Tích hợp một chuỗi các ý kiến ​​là khó khăn. Vui lòng cập nhật câu hỏi để làm rõ và tập trung vào nó.
S.Lott

Câu trả lời:


116

Đó là một vấn đề định nghĩa. Một bài kiểm tra với các phụ thuộc là một bài kiểm tra tích hợp, không phải bài kiểm tra đơn vị. Bạn cũng nên có một bộ kiểm tra tích hợp. Sự khác biệt là bộ kiểm thử tích hợp có thể được chạy trong một khung kiểm tra khác và có thể không phải là một phần của bản dựng vì chúng mất nhiều thời gian hơn.

Đối với sản phẩm của chúng tôi: Các thử nghiệm đơn vị của chúng tôi được chạy với mỗi bản dựng, mất vài giây. Một tập hợp con của các bài kiểm tra tích hợp của chúng tôi chạy với mỗi lần đăng ký, mất 10 phút. Bộ tích hợp đầy đủ của chúng tôi được chạy mỗi đêm, mất 4 giờ.


4
Đừng quên các bài kiểm tra hồi quy để bao gồm các lỗi được phát hiện và sửa lỗi để ngăn việc giới thiệu lại chúng vào một hệ thống trong quá trình bảo trì trong tương lai.
RBerteig

2
Tôi sẽ không nhấn mạnh vào định nghĩa ngay cả khi tôi đồng ý với nó. Một số mã có thể có các phụ thuộc có thể chấp nhận như StringFormatter và nó vẫn được xem xét bởi hầu hết các bài kiểm tra đơn vị.
danidacar

2
danip: định nghĩa rõ ràng là quan trọng, và tôi sẽ nhấn mạnh vào chúng. Nhưng điều quan trọng là phải nhận ra rằng những định nghĩa đó là một mục tiêu. Chúng đáng để nhắm đến, nhưng bạn không phải lúc nào cũng cần một câu chuyện. Các bài kiểm tra đơn vị thường sẽ có sự phụ thuộc vào các thư viện cấp thấp hơn.
Jeffrey Faust

2
Ngoài ra, điều quan trọng là phải hiểu khái niệm về kiểm tra mặt tiền, đó là không kiểm tra cách các thành phần khớp với nhau (như kiểm tra tích hợp) mà chỉ kiểm tra một thành phần duy nhất. (tức là một đồ thị đối tượng)
Ricardo

1
Nó không chỉ về việc nhanh hơn mà còn cực kỳ tẻ nhạt hoặc không thể quản lý được, hãy tưởng tượng, nếu bạn không làm, cây hành hình chế giễu của bạn có thể đang phát triển theo cấp số nhân. Hãy tưởng tượng bạn chế nhạo 10 phụ thuộc trong đơn vị của mình nếu bạn đẩy chế độ giả lập thêm, giả sử 1 trong số 10 phụ thuộc đó được sử dụng ở nhiều nơi và nó có 20 phụ thuộc riêng, vì vậy bạn phải chế nhạo + 20 phụ thuộc khác, có khả năng trùng lặp ở nhiều nơi. tại điểm cuối cùng bạn phải giả định - ví dụ: cơ sở dữ liệu, để bạn không phải thiết lập lại và nó nhanh hơn như bạn đã nói
FantomX1

39

Thử nghiệm với tất cả các phụ thuộc tại chỗ vẫn còn quan trọng, nhưng đó là nhiều hơn trong lĩnh vực thử nghiệm tích hợp như Jeffrey Faust nói.

Một trong những khía cạnh quan trọng nhất của kiểm tra đơn vị là làm cho các bài kiểm tra của bạn đáng tin cậy. Nếu bạn không tin tưởng rằng một bài kiểm tra vượt qua thực sự có nghĩa là mọi thứ đều tốt và một bài kiểm tra thất bại thực sự có nghĩa là một vấn đề trong mã sản xuất, thì các bài kiểm tra của bạn gần như không hữu ích như chúng có thể.

Để làm cho bài kiểm tra của bạn đáng tin cậy, bạn phải làm một vài điều, nhưng tôi sẽ tập trung vào chỉ một cho câu trả lời này. Bạn phải đảm bảo chúng dễ chạy, để tất cả các nhà phát triển có thể dễ dàng chạy chúng trước khi kiểm tra mã. "Dễ chạy" có nghĩa là các thử nghiệm của bạn chạy nhanh không cần cấu hình hoặc thiết lập mở rộng để thực hiện. Lý tưởng nhất, bất kỳ ai cũng có thể kiểm tra phiên bản mới nhất của mã, chạy thử nghiệm ngay lập tức và xem chúng vượt qua.

Tóm tắt sự phụ thuộc vào những thứ khác (hệ thống tệp, cơ sở dữ liệu, dịch vụ web, v.v.) cho phép bạn tránh yêu cầu cấu hình và khiến bạn và các nhà phát triển khác ít bị ảnh hưởng hơn khi bạn nói "Ồ, thử nghiệm thất bại vì tôi không ' Tôi đã thiết lập chia sẻ mạng. Ồ tốt. Tôi sẽ chạy chúng sau. "

Nếu bạn muốn kiểm tra những gì bạn làm với một số dữ liệu, đơn vị của bạn sẽ kiểm tra mã logic nghiệp vụ đó không quan tâm đến cách bạn có được dữ liệu đó. Có thể kiểm tra logic cốt lõi của ứng dụng của bạn mà không phụ thuộc vào công cụ hỗ trợ như cơ sở dữ liệu là tuyệt vời. Nếu bạn không làm điều đó, bạn đang bỏ lỡ.

Tái bút: Tôi nên nói thêm rằng chắc chắn có thể áp đảo tên của khả năng kiểm tra. Lái thử ứng dụng của bạn giúp giảm thiểu điều đó. Nhưng trong mọi trường hợp, việc triển khai kém một cách tiếp cận không làm cho cách tiếp cận đó kém hiệu lực. Bất cứ điều gì cũng có thể bị lạm dụng và quá liều nếu người ta không tiếp tục hỏi "tại sao tôi lại làm điều này?" trong khi phát triển


Theo như phụ thuộc nội bộ, mọi thứ có một chút bùn. Cách tôi muốn nghĩ về nó là tôi muốn bảo vệ lớp mình càng nhiều càng tốt để thay đổi vì những lý do sai lầm. Nếu tôi có một thiết lập như thế này ...

public class MyClass 
{
    private SomeClass someClass;
    public MyClass()
    {
        someClass = new SomeClass();
    }

    // use someClass in some way
}

Tôi thường không quan tâm làm thế nào SomeClassđược tạo ra. Tôi chỉ muốn sử dụng nó. Nếu someClass thay đổi và bây giờ yêu cầu tham số cho hàm tạo ... đó không phải là vấn đề của tôi. Tôi không nên thay đổi MyClass để phù hợp với điều đó.

Bây giờ, đó chỉ là chạm vào phần thiết kế. Liên quan đến các bài kiểm tra đơn vị, tôi cũng muốn bảo vệ bản thân khỏi các lớp khác. Nếu tôi đang kiểm tra MyClass, tôi muốn biết rằng thực tế là không có sự phụ thuộc bên ngoài, rằng tại một số điểm, một số người đã không giới thiệu một kết nối cơ sở dữ liệu hoặc một số liên kết bên ngoài khác.

Nhưng một vấn đề thậm chí còn lớn hơn là tôi cũng biết rằng một số kết quả của các phương thức của tôi phụ thuộc vào đầu ra từ một số phương thức trên someClass. Nếu không chế nhạo / loại bỏ một sốClass, tôi có thể không có cách nào để thay đổi đầu vào theo nhu cầu. Nếu tôi may mắn, tôi có thể kết hợp môi trường của mình trong bài kiểm tra theo cách nó sẽ kích hoạt phản hồi đúng từ một sốClass, nhưng theo cách đó sẽ đưa sự phức tạp vào các bài kiểm tra của tôi và khiến chúng trở nên dễ vỡ.

Viết lại MyClass để chấp nhận một thể hiện của someClass trong hàm tạo cho phép tôi tạo một thể hiện giả của someClass trả về giá trị tôi muốn (thông qua khung mô phỏng hoặc bằng một mô phỏng thủ công). Tôi thường không phải giới thiệu một giao diện trong trường hợp này. Có nên làm như vậy hay không theo nhiều cách là một lựa chọn cá nhân có thể bị quyết định bởi ngôn ngữ bạn chọn (ví dụ: giao diện có nhiều khả năng trong C #, nhưng bạn chắc chắn sẽ không cần một thứ trong Ruby).


+1 Câu trả lời tuyệt vời, vì sự phụ thuộc bên ngoài là một trường hợp tôi không nghĩ đến khi tôi viết câu hỏi ban đầu. Tôi đã làm rõ câu hỏi của mình để trả lời. Xem bản chỉnh sửa mới nhất.
dsimcha

@dsimcha Tôi mở rộng câu trả lời của mình để đi sâu vào chi tiết hơn về điều đó. Hy vọng nó giúp.
Adam Lear

Adam, bạn có thể đề xuất một ngôn ngữ trong đó "Nếu someClass thay đổi và hiện yêu cầu tham số cho hàm tạo ... Tôi không nên thay đổi MyClass" có đúng không? Xin lỗi, điều đó chỉ xảy ra với tôi như một yêu cầu bất thường. Tôi có thể thấy không phải thay đổi các bài kiểm tra đơn vị cho MyClass, nhưng không phải thay đổi MyClass ... wow.

1
@moz Ý tôi là nếu cách tạo ra một số loại, MyClass không phải thay đổi nếu một số loại được đưa vào trong đó thay vì được tạo bên trong. Trong các trường hợp thông thường, MyClass không cần quan tâm đến các chi tiết thiết lập cho someClass. Nếu giao diện của someClass thay đổi, thì ừ ... MyClass vẫn sẽ phải sửa đổi nếu bất kỳ phương thức nào nó sử dụng bị ảnh hưởng.
Adam Lear

1
Nếu bạn giả định một sốClass khi kiểm tra MyClass, làm thế nào bạn phát hiện ra nếu MyClass sử dụng một sốClass không chính xác hoặc dựa vào một cách giải quyết chưa được kiểm tra của một sốClass có thể thay đổi?
tên

22

Ngoài vấn đề kiểm tra đơn vị và tích hợp, hãy xem xét các vấn đề sau.

Class Widget có sự phụ thuộc vào các lớp Thingamajig và WhatsIt.

Một bài kiểm tra đơn vị cho Widget thất bại.

Trong lớp học nào là vấn đề?

Nếu bạn trả lời "kích hoạt trình gỡ lỗi" hoặc "đọc mã cho đến khi tôi tìm thấy nó", bạn hiểu tầm quan trọng của việc chỉ kiểm tra đơn vị, không phải phụ thuộc.


3
@Brook: Làm thế nào về việc xem kết quả cho tất cả các phụ thuộc của Widget là gì? Nếu tất cả đều vượt qua, đó là một vấn đề với Widget cho đến khi được chứng minh khác đi.
dsimcha

4
@dsimcha, nhưng bây giờ bạn đang thêm độ phức tạp trở lại trong trò chơi để kiểm tra các bước trung gian. Tại sao không đơn giản hóa và chỉ làm các bài kiểm tra đơn vị đầu tiên? Sau đó làm bài kiểm tra tích hợp của bạn.
asoundmove

1
@dsimcha, nghe có vẻ hợp lý cho đến khi bạn vào một biểu đồ phụ thuộc không tầm thường. Giả sử bạn có một đối tượng phức tạp có sâu hơn 3 lớp với các phụ thuộc, nó biến thành tìm kiếm O (N ^ 2) cho vấn đề, thay vì O (1)
Brook

1
Ngoài ra, cách giải thích của tôi về SRP là một lớp nên có một trách nhiệm duy nhất ở cấp miền khái niệm / vấn đề. Không thành vấn đề nếu hoàn thành trách nhiệm đó đòi hỏi nó phải làm nhiều việc khác nhau khi được xem ở mức độ trừu tượng thấp hơn. Nếu được đưa đến mức cực đoan, SRP sẽ trái với OO vì hầu hết các lớp giữ dữ liệu và thực hiện các thao tác trên nó (hai điều khi được xem ở mức đủ thấp).
dsimcha

4
@Brook: Nhiều loại không làm tăng độ phức tạp mỗi se. Nhiều loại hơn là tốt nếu những loại đó có ý nghĩa khái niệm trong miền vấn đề và làm cho mã dễ dàng hơn, không khó hơn, để hiểu. Vấn đề là tách rời một cách giả tạo những thứ được kết hợp về mặt khái niệm ở cấp độ miền vấn đề (nghĩa là bạn chỉ có một triển khai, có thể sẽ không bao giờ có nhiều hơn một, v.v.) và tách riêng không phù hợp với các khái niệm miền có vấn đề. Trong những trường hợp này, thật ngớ ngẩn, quan liêu và dài dòng để tạo ra sự trừu tượng nghiêm trọng xung quanh việc thực hiện này.
dsimcha

14

Hãy tưởng tượng rằng lập trình giống như nấu ăn. Sau đó, kiểm tra đơn vị cũng giống như đảm bảo các thành phần của bạn tươi, ngon, v.v ... Trong khi đó, kiểm tra tích hợp cũng giống như đảm bảo bữa ăn của bạn ngon miệng.

Cuối cùng, đảm bảo rằng bữa ăn của bạn ngon (hoặc hệ thống của bạn hoạt động) là điều quan trọng nhất, mục tiêu cuối cùng. Nhưng nếu thành phần của bạn, ý tôi là, các đơn vị, công việc, bạn sẽ có một cách rẻ hơn để tìm hiểu.

Thật vậy, nếu bạn có thể đảm bảo rằng các đơn vị / phương pháp của bạn hoạt động, bạn có nhiều khả năng có một hệ thống hoạt động. Tôi nhấn mạnh "nhiều khả năng", trái ngược với "nhất định". Bạn vẫn cần các bài kiểm tra tích hợp của mình, giống như bạn vẫn cần ai đó nếm thử bữa ăn bạn nấu và nói với bạn rằng sản phẩm cuối cùng là tốt. Bạn sẽ có một thời gian dễ dàng hơn để đến đó với các thành phần tươi, đó là tất cả.


7
Và khi kiểm tra tích hợp của bạn thất bại, kiểm tra đơn vị có thể không gặp vấn đề.
Tim Williscroft

9
Để kéo dài một sự tương tự: Khi bạn thấy rằng bữa ăn của bạn có vị rất tệ, có thể phải mất một số điều tra để xác định rằng đó là do bánh mì của bạn bị mốc. Tuy nhiên, kết quả là bạn thêm một bài kiểm tra đơn vị để kiểm tra bánh mì bị mốc trước khi nấu, để vấn đề cụ thể đó không thể xảy ra lần nữa. Sau đó, nếu bạn có một bữa ăn thất bại sau đó, bạn đã loại bỏ bánh mì mốc là nguyên nhân.
Kyralessa

Yêu sự tương tự này!
thehowler

6

Các đơn vị kiểm tra bằng cách cách ly hoàn toàn chúng sẽ cho phép kiểm tra TẤT CẢ các biến thể dữ liệu và tình huống có thể được gửi đơn vị này. Bởi vì nó được cách ly với phần còn lại, bạn có thể bỏ qua các biến thể không có ảnh hưởng trực tiếp đến đơn vị được kiểm tra. điều này đến lượt nó sẽ làm giảm đáng kể sự phức tạp của các bài kiểm tra.

Thử nghiệm với các mức độ phụ thuộc khác nhau được tích hợp sẽ cho phép bạn kiểm tra các tình huống cụ thể có thể chưa được thử nghiệm trong các thử nghiệm đơn vị.

Cả hai đều quan trọng. Chỉ cần thực hiện kiểm tra đơn vị, bạn sẽ luôn xảy ra lỗi tinh vi phức tạp hơn khi tích hợp các thành phần. Chỉ thực hiện kiểm tra tích hợp có nghĩa là bạn đang kiểm tra một hệ thống mà không có sự tự tin rằng các bộ phận riêng lẻ của máy chưa được kiểm tra. Nghĩ rằng bạn có thể đạt được thử nghiệm hoàn thành tốt hơn chỉ bằng cách thực hiện kiểm thử tích hợp là gần như không thể vì càng nhiều thành phần bạn thêm số lượng kết hợp mục nhập tăng RẤT nhanh (nghĩ đến giai đoạn) và tạo ra một thử nghiệm với độ bao phủ đủ nhanh chóng trở nên không thể.

Vì vậy, trong ngắn hạn, ba cấp độ "thử nghiệm đơn vị" tôi thường sử dụng trong hầu hết các dự án của mình:

  • Các thử nghiệm đơn vị, được phân lập với các phụ thuộc bị nhạo báng hoặc sơ khai để kiểm tra địa ngục của một thành phần duy nhất. Lý tưởng nhất là một nỗ lực sẽ hoàn thành bảo hiểm.
  • Kiểm tra tích hợp để kiểm tra các lỗi tinh tế hơn. Kiểm tra tại chỗ được làm cẩn thận sẽ cho thấy các trường hợp giới hạn và điều kiện điển hình. Hoàn thành bảo hiểm thường là không thể, nỗ lực tập trung vào những gì sẽ làm cho hệ thống thất bại.
  • Kiểm tra thông số kỹ thuật để đưa dữ liệu thực tế khác nhau vào hệ thống, cung cấp dữ liệu (nếu có thể) và quan sát đầu ra để đảm bảo dữ liệu phù hợp với quy tắc và quy tắc kinh doanh.

Phụ thuộc tiêm là một phương tiện rất hiệu quả để đạt được điều này vì nó cho phép cách ly các thành phần để kiểm tra đơn vị rất dễ dàng mà không cần thêm độ phức tạp vào hệ thống. Kịch bản kinh doanh của bạn có thể không đảm bảo việc sử dụng cơ chế tiêm nhưng kịch bản thử nghiệm của bạn gần như sẽ. Điều này đối với tôi là đủ để thực hiện sau đó không thể thiếu. Bạn cũng có thể sử dụng chúng để kiểm tra các mức độ trừu tượng khác nhau một cách độc lập thông qua thử nghiệm tích hợp một phần.


4

Phía bên kia là gì? Có thực sự quan trọng là một bài kiểm tra đơn vị cũng không kiểm tra các phụ thuộc của nó không? Nếu vậy, tại sao?

Đơn vị. Có nghĩa là số ít.

Kiểm tra 2 điều có nghĩa là bạn có hai điều tất cả các phụ thuộc chức năng.

Nếu bạn thêm điều thứ 3, bạn sẽ tăng các phụ thuộc chức năng trong các bài kiểm tra ngoài tuyến tính. Sự kết nối giữa các thứ phát triển nhanh hơn số lượng của sự vật.

Có n (n-1) / 2 phụ thuộc tiềm năng trong số n mục đang được thử nghiệm.

Đó là lý do lớn.

Đơn giản có giá trị.


2

Hãy nhớ làm thế nào bạn lần đầu tiên học làm đệ quy? Prof của tôi đã nói "Giả sử bạn có một phương thức thực hiện x" (ví dụ: giải quyết fftimeacci cho bất kỳ x). "Để giải quyết cho x, bạn phải gọi phương thức đó cho x-1 và x-2". Cũng vậy, việc loại bỏ các phụ thuộc cho phép bạn giả vờ chúng tồn tại và kiểm tra xem đơn vị hiện tại có làm những gì cần làm hay không. Tất nhiên, giả định là bạn đang kiểm tra các phụ thuộc một cách chặt chẽ.

Đây thực chất là SRP tại nơi làm việc. Tập trung vào một trách nhiệm duy nhất ngay cả đối với các bài kiểm tra của bạn, loại bỏ số lượng tung hứng tinh thần bạn phải làm.


2

(Đây là một câu trả lời nhỏ. Cảm ơn @TimWilliscroft vì gợi ý.)

Lỗi dễ dàng hơn để bản địa hóa nếu:

  • Cả bài kiểm tra đơn vị và từng phần phụ thuộc của nó đều được kiểm tra độc lập.
  • Mỗi thử nghiệm thất bại khi và chỉ khi có lỗi trong mã được kiểm tra.

Điều này hoạt động độc đáo trên giấy. Tuy nhiên, như được minh họa trong mô tả của OP (phụ thuộc là lỗi), nếu các phụ thuộc không được kiểm tra, sẽ khó xác định vị trí của lỗi.


Tại sao các phụ thuộc sẽ không được kiểm tra? Có lẽ chúng ở cấp độ thấp hơn và dễ kiểm tra đơn vị hơn. Hơn nữa, với các thử nghiệm đơn vị bao gồm mã cụ thể, việc xác định vị trí lỗi sẽ dễ dàng hơn.
David Thornley

2

Rất nhiều câu trả lời hay. Tôi cũng muốn thêm một vài điểm khác:

Kiểm thử đơn vị cũng cho phép bạn kiểm tra mã của mình khi bạn phụ thuộc không tồn tại . Ví dụ: bạn hoặc nhóm của bạn chưa viết các lớp khác hoặc có thể bạn đang chờ đợi trên một giao diện được cung cấp bởi một công ty khác.

Kiểm tra đơn vị cũng có nghĩa là bạn không cần phải có một môi trường đầy đủ trên máy dev của mình (ví dụ: cơ sở dữ liệu, máy chủ web, v.v.). Tôi mạnh mẽ sẽ khuyên tất cả các nhà phát triển làm có một môi trường như vậy, tuy nhiên cắt giảm đó là, để lỗi repro vv Tuy nhiên, nếu vì một lý do nào đó không thể bắt chước các môi trường sản xuất sau đó kiểm tra đơn vị ít nhất cho yu một mức độ nào tin tưởng vào mã của bạn trước khi nó đi vào một hệ thống thử nghiệm lớn hơn.


0

Về các khía cạnh thiết kế: Tôi tin rằng ngay cả các dự án nhỏ cũng được hưởng lợi từ việc làm cho mã có thể kiểm tra được. Bạn không nhất thiết phải giới thiệu một cái gì đó như Guice (một lớp nhà máy đơn giản sẽ thường làm), nhưng tách biệt quá trình xây dựng từ logic lập trình dẫn đến

  • ghi lại rõ ràng sự phụ thuộc của mỗi lớp thông qua giao diện của nó (rất hữu ích cho những người mới tham gia nhóm)
  • các lớp trở nên rõ ràng hơn và dễ bảo trì hơn (một khi bạn đặt việc tạo biểu đồ đối tượng xấu xí vào một lớp riêng biệt)
  • khớp nối lỏng lẻo (làm cho thay đổi dễ dàng hơn nhiều)

2
Phương thức: Có, nhưng bạn phải thêm mã bổ sung và các lớp bổ sung để làm điều này. Mã phải ngắn gọn nhất có thể trong khi vẫn có thể đọc được. IMHO thêm các nhà máy và không có gì quá đáng trừ khi bạn có thể chứng minh rằng bạn cần hoặc rất có thể cần sự linh hoạt mà nó cung cấp.
dsimcha

0

Uh ... có những điểm tốt về kiểm tra đơn vị và tích hợp được viết trong những câu trả lời ở đây!

Tôi bỏ lỡ các quan điểm liên quan đến chi phí và thực tế ở đây. Điều đó nói rằng tôi thấy rõ lợi ích của các thử nghiệm đơn vị nguyên tử / rất cô lập (có thể độc lập cao với nhau và với tùy chọn chạy song song và không có bất kỳ phụ thuộc nào, như cơ sở dữ liệu, hệ thống tệp, v.v.) và thử nghiệm tích hợp (cấp cao hơn), nhưng ... đó cũng là vấn đề về chi phí (thời gian, tiền bạc, ...) và rủi ro .

Vì vậy, có những yếu tố khác, quan trọng hơn nhiều (như "phải kiểm tra cái gì" ) trước khi bạn nghĩ đến "cách kiểm tra" từ kinh nghiệm của tôi ...

Có phải khách hàng của tôi (ngầm) trả tiền cho số lượng viết thêm và duy trì các bài kiểm tra? Là một cách tiếp cận dựa trên thử nghiệm (viết thử nghiệm trước khi bạn viết mã) có thực sự hiệu quả về chi phí trong môi trường của tôi (phân tích rủi ro thất bại / phân tích chi phí, con người, thông số thiết kế, thiết lập môi trường thử nghiệm) không? Mã luôn có lỗi, nhưng nó có thể hiệu quả hơn về chi phí khi chuyển thử nghiệm sang sử dụng sản xuất (trong trường hợp xấu nhất!)?

Nó cũng phụ thuộc rất nhiều vào chất lượng mã (tiêu chuẩn) của bạn là gì hoặc các khung, IDE, nguyên tắc thiết kế, v.v. bạn và nhóm của bạn tuân theo và họ có kinh nghiệm như thế nào. Một mã được viết tốt, dễ hiểu, đủ tài liệu (lý tưởng là tự viết tài liệu), mô-đun, ... mã giới thiệu có khả năng ít lỗi hơn so với ngược lại. Vì vậy, "nhu cầu" thực sự, áp lực hoặc chi phí bảo trì / rủi ro tổng thể / rủi ro cho các thử nghiệm mở rộng có thể không cao.

Chúng ta hãy đưa nó đến mức cực đoan mà một đồng nghiệp trong nhóm của tôi đề xuất, chúng ta phải thử kiểm tra mã lớp mô hình Java EE thuần túy của chúng tôi với độ bao phủ 100% mong muốn cho tất cả các lớp trong và chế tạo cơ sở dữ liệu. Hoặc người quản lý muốn các thử nghiệm tích hợp được bao phủ với 100% tất cả các trường hợp sử dụng trong thế giới thực và quy trình làm việc trên web vì chúng tôi không muốn rủi ro cho bất kỳ trường hợp sử dụng nào thất bại. Nhưng chúng tôi có ngân sách eo hẹp khoảng 1 triệu euro, một kế hoạch khá chặt chẽ để mã hóa mọi thứ. Một môi trường khách hàng, nơi các lỗi ứng dụng tiềm năng sẽ không gây nguy hiểm lớn cho con người hoặc các công ty. Ứng dụng của chúng tôi sẽ được thử nghiệm nội bộ với (một số) thử nghiệm đơn vị quan trọng, thử nghiệm tích hợp, thử nghiệm khách hàng quan trọng với kế hoạch thử nghiệm được thiết kế, giai đoạn thử nghiệm, v.v. Chúng tôi không phát triển ứng dụng cho một số nhà máy hạt nhân hoặc sản xuất dược phẩm!

Bản thân tôi cố gắng viết bài kiểm tra nếu có thể và phát triển trong khi đơn vị kiểm tra mã của tôi. Nhưng tôi thường làm điều đó từ cách tiếp cận từ trên xuống (thử nghiệm tích hợp) và cố gắng tìm ra điểm tốt, nơi thực hiện "cắt lớp ứng dụng" cho các thử nghiệm quan trọng (thường là trong lớp mô hình). (bởi vì nó thường rất nhiều về các "lớp")

Hơn nữa, mã kiểm thử đơn vị và tích hợp không xuất hiện mà không có tác động tiêu cực về thời gian, tiền bạc, bảo trì, mã hóa, v.v ... Thật tuyệt và nên được áp dụng, nhưng hãy cẩn thận và xem xét các tác động khi bắt đầu hoặc sau 5 năm thử nghiệm được phát triển mã.

Vì vậy, tôi muốn nói rằng nó thực sự phụ thuộc rất nhiều vào sự tin tưởng và đánh giá chi phí / rủi ro / lợi ích ... như trong cuộc sống thực, nơi bạn không thể và không muốn chạy xung quanh với nhiều cơ chế an toàn 100%.

Đứa trẻ có thể và nên trèo lên một nơi nào đó và có thể ngã xuống và tự làm đau mình. Chiếc xe có thể ngừng hoạt động vì tôi đổ đầy nhiên liệu sai (đầu vào không hợp lệ :)). Bánh mì nướng có thể bị đốt cháy nếu nút thời gian ngừng hoạt động sau 3 năm. Nhưng tôi không, không bao giờ muốn lái xe trên đường cao tốc và cầm vô lăng tách rời trong tay :)

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.