Từ góc độ TDD, tôi có phải là người xấu nếu tôi kiểm tra điểm cuối trực tiếp thay vì giả không?


16

Tôi theo TDD một cách tôn giáo. Các dự án của tôi thường có phạm vi kiểm tra 85% hoặc tốt hơn, với các trường hợp thử nghiệm có ý nghĩa.

Tôi làm rất nhiều việc với HBase và giao diện máy khách chính, HTable, là một nỗi đau thực sự để chế giễu. Tôi phải mất 3 hoặc 4 lần để viết bài kiểm tra đơn vị của mình so với việc viết bài kiểm tra sử dụng điểm cuối trực tiếp.

Tôi biết rằng, về mặt triết học, các bài kiểm tra sử dụng giả nên ưu tiên hơn các bài kiểm tra sử dụng điểm cuối trực tiếp. Nhưng chế giễu HTable là một nỗi đau nghiêm trọng và tôi không thực sự chắc chắn rằng nó mang lại nhiều lợi thế hơn so với thử nghiệm đối với một phiên bản HBase trực tiếp.

Mọi người trong nhóm của tôi chạy một phiên bản HBase một nút trên máy trạm của họ và chúng tôi có các phiên bản HBase một nút chạy trên các hộp Jenkins của chúng tôi, vì vậy đó không phải là vấn đề về tính khả dụng. Các thử nghiệm điểm cuối trực tiếp rõ ràng mất nhiều thời gian hơn so với các thử nghiệm sử dụng giả, nhưng chúng tôi không thực sự quan tâm đến điều đó.

Ngay bây giờ, tôi viết các bài kiểm tra điểm cuối trực tiếp VÀ các bài kiểm tra dựa trên giả cho tất cả các lớp của tôi. Tôi rất muốn bỏ các giả, nhưng tôi không muốn chất lượng giảm sút.

Tất cả các bạn nghĩ gì?


8
Điểm cuối trực tiếp không thực sự là một bài kiểm tra đơn vị, phải không? Đây là một bài kiểm tra tích hợp. Nhưng cuối cùng có lẽ đó là một câu hỏi về chủ nghĩa thực dụng; bạn có thể dành thời gian để viết giả, hoặc dành thời gian viết các tính năng hoặc sửa lỗi.
Robert Harvey

4
Tôi đã nghe câu chuyện về những người sử dụng dịch vụ của bên thứ 3 bằng cách chạy thử nghiệm đơn vị dựa trên mã của chính họ ... được nối với điểm cuối trực tiếp. Giới hạn tỷ lệ không phải là điều mà kiểm thử đơn vị thường làm hoặc quan tâm.

14
Bạn không phải là người xấu. Bạn là một người tốt làm một điều xấu.
Kyralessa

14
Tôi theo TDD một cách tôn giáo Có lẽ đó là vấn đề? Tôi không nghĩ rằng bất kỳ phương pháp này có nghĩa là để được thực hiện nghiêm túc. ;)
Thất

9
Theo TDD một cách tôn giáo có nghĩa là bạn loại bỏ mã 15% chưa được phát hiện.
mouviciel

Câu trả lời:


23
  • Đề nghị đầu tiên của tôi là không chế giễu các loại bạn không sở hữu . Bạn đã đề cập đến HTable là một nỗi đau thực sự để chế giễu - có lẽ bạn nên bọc nó thay vào đó trong Bộ điều hợp hiển thị 20% các tính năng của HTable mà bạn cần và chế giễu trình bao bọc khi cần.

  • Điều đó đang được nói, giả sử chúng ta đang nói về các loại bạn sở hữu. Nếu các bài kiểm tra dựa trên giả của bạn tập trung vào các kịch bản đường dẫn hạnh phúc, nơi mọi thứ diễn ra suôn sẻ, bạn sẽ không mất bất cứ điều gì bỏ qua chúng vì các kiểm tra tích hợp của bạn có thể đã kiểm tra các đường dẫn chính xác.

    Tuy nhiên, các thử nghiệm biệt lập trở nên thú vị khi bạn bắt đầu suy nghĩ về cách hệ thống của mình được thử nghiệm sẽ phản ứng với mọi điều nhỏ nhặt có thể xảy ra như được xác định trong hợp đồng của cộng tác viên, bất kể đối tượng cụ thể thực tế mà nó đang nói đến. Đó là một phần của những gì một số người gọi là chính xác cơ bản . Có thể có nhiều trường hợp nhỏ và nhiều kết hợp của chúng. Đây là nơi các bài kiểm tra tích hợp bắt đầu trở nên tệ hại trong khi các bài kiểm tra bị cô lập sẽ vẫn nhanh và có thể quản lý được.

    Để cụ thể hơn, điều gì xảy ra nếu một trong các phương thức của bộ điều hợp HTable của bạn trả về một danh sách trống? Điều gì nếu nó trả về null? Điều gì nếu nó ném một ngoại lệ kết nối? Nó nên được xác định trong hợp đồng của Bộ chuyển đổi nếu bất kỳ điều nào trong số những điều đó có thể xảy ra, và bất kỳ người tiêu dùng nào của nó nên được chuẩn bị để đối phó với các tình huống này , do đó cần phải thử nghiệm cho chúng.

Tóm lại: bạn sẽ không thấy bất kỳ sự suy giảm chất lượng nào bằng cách loại bỏ các bài kiểm tra dựa trên giả của mình nếu chúng đã kiểm tra chính xác những điều tương tự như các bài kiểm tra tích hợp của bạn . Tuy nhiên, cố gắng tưởng tượng các thử nghiệm biệt lập bổ sung (và thử nghiệm hợp đồng ) có thể giúp bạn nghĩ ra các giao diện / hợp đồng của mình một cách rộng rãi và tăng chất lượng bằng cách khắc phục các khiếm khuyết khó có thể nghĩ và / hoặc chậm để kiểm tra với các thử nghiệm tích hợp.


+1 Tôi thấy việc xây dựng các trường hợp cạnh với các thử nghiệm giả dễ dàng hơn nhiều so với việc điền vào cơ sở dữ liệu với các trường hợp đó.
Rob

Tôi đồng ý với hầu hết câu trả lời của bạn. Tuy nhiên, tôi không chắc là tôi đồng ý về phần Adaptor. HTable là một nỗi đau để chế giễu vì nó khá kim loại. Ví dụ: nếu bạn muốn thực hiện một thao tác lấy hàng loạt, bạn phải tạo một nhóm các đối tượng Get, đặt chúng vào danh sách, sau đó gọi HTable.batch (). Từ góc độ chế giễu, đây là một nỗi đau nghiêm trọng, bởi vì bạn phải tạo một Matcher tùy chỉnh kiểm tra danh sách các đối tượng bạn chuyển đến HTable.batch () và sau đó trả về kết quả chính xác cho danh sách các đối tượng get () đó. Một nỗi đau NGHIÊM TRỌNG.
sangfroid

Tôi cho rằng tôi có thể tạo ra một lớp bao bọc thân thiện, tốt đẹp cho HTable, người đảm nhiệm tất cả công việc dọn phòng đó, nhưng tại thời điểm đó ... tôi cảm thấy như mình đang xây dựng một khuôn khổ xung quanh HTable, và đó có thực sự là công việc của tôi không? Thông thường "Hãy xây dựng một khung!" là một dấu hiệu tôi đang đi sai hướng. Tôi có thể dành nhiều ngày để viết các lớp học để làm cho HBase trở nên thân thiện hơn và tôi không biết liệu đó có phải là cách sử dụng thời gian tuyệt vời của tôi không. Thêm vào đó, sau đó tôi đang theo dõi một giao diện hoặc trình bao bọc thay vì chỉ đối tượng HTable cũ và điều đó chắc chắn sẽ làm cho mã của tôi phức tạp hơn.
sangfroid

Nhưng tôi đồng ý với quan điểm chính của bạn, rằng người ta không nên viết giả cho các lớp họ không sở hữu. Và chắc chắn đồng ý rằng không có điểm nào trong việc viết một bài kiểm tra giả kiểm tra điều tương tự như bài kiểm tra tích hợp. Có vẻ như giả là tốt nhất để thử nghiệm giao diện / hợp đồng. Cảm ơn lời khuyên - điều này đã giúp tôi rất nhiều!
sangfroid

Tôi có ít ý tưởng về những gì HTable thực sự làm và cách bạn sử dụng nó, vì vậy đừng lấy ví dụ về trình bao bọc của tôi cho bức thư. Tôi đã đề cập đến một trình bao bọc / bộ chuyển đổi bởi vì tôi nghĩ rằng điều cần bọc là tương đối nhỏ. Bạn không cần phải giới thiệu một bản sao một-một cho HTable, điều này tất nhiên sẽ là một nỗi đau, chứ đừng nói đến toàn bộ khung - nhưng bạn cần một đường nối , giao diện giữa lĩnh vực ứng dụng của bạn và HTable. Nó nên viết lại một số chức năng của HTable thành các thuật ngữ riêng của ứng dụng của bạn. Mẫu Kho lưu trữ là một hóa thân hoàn hảo của một đường may như vậy khi truy cập dữ liệu.
guillaume31

11

Về mặt triết học, các bài kiểm tra sử dụng giả nên ưu tiên hơn các bài kiểm tra sử dụng điểm cuối trực tiếp

Tôi nghĩ ít nhất, đó là một điểm gây tranh cãi hiện nay giữa những người đề xướng TDD.

Quan điểm cá nhân của tôi vượt xa điều đó để nói rằng thử nghiệm dựa trên giả chủ yếu là cách thể hiện một hình thức hợp đồng giao diện ; lý tưởng là nó bị hỏng (tức là thất bại) khi và chỉ khi bạn thay đổi giao diện . Và như vậy, trong một ngôn ngữ được gõ khá hợp lý như Java và khi sử dụng giao diện được xác định rõ ràng, nó gần như hoàn toàn thừa: trình biên dịch sẽ thông báo cho bạn nếu bạn đã thay đổi giao diện.

Ngoại lệ chính là khi bạn đang sử dụng một giao diện rất chung chung, có lẽ dựa trên các chú thích hoặc phản xạ, trình biên dịch không thể tự động cảnh sát một cách hữu ích. Thậm chí sau đó bạn nên kiểm tra xem liệu có cách nào để thực hiện xác nhận theo chương trình (eq một thư viện kiểm tra cú pháp SQL) chứ không phải bằng tay sử dụng giả.

Đó là trường hợp sau bạn đang làm khi kiểm tra với cơ sở dữ liệu cục bộ 'sống'; việc triển khai htable bắt đầu và áp dụng xác nhận hợp đồng toàn diện hơn nhiều so với hợp đồng mà bạn từng nghĩ sẽ viết ra bằng tay.

Thật không may, việc sử dụng thử nghiệm dựa trên giả phổ biến hơn nhiều là thử nghiệm:

  • vượt qua bất cứ mã nào tại thời điểm kiểm tra được viết
  • không đảm bảo về bất kỳ thuộc tính nào của mã ngoài mã đó tồn tại và loại chạy
  • thất bại bất cứ khi nào bạn thay đổi mã đó

Các xét nghiệm như vậy tất nhiên nên được xóa khỏi tầm nhìn.


1
Tôi không thể sao lưu này đủ. Tôi muốn có phạm vi bảo hiểm 1 phần với các bài kiểm tra tuyệt vời hơn phạm vi bao phủ 100pc.
Ian

3
Các thử nghiệm dựa trên giả thực sự mô tả hợp đồng được sử dụng bởi 2 đối tượng để nói chuyện với nhau, nhưng chúng vượt xa những gì hệ thống loại ngôn ngữ như Java có thể làm. Không chỉ là về chữ ký phương thức, họ còn có thể chỉ định phạm vi giá trị hợp lệ cho các đối số hoặc kết quả trả về, ngoại lệ nào được chấp nhận, theo thứ tự và số lần phương thức có thể được gọi, v.v ... Trình biên dịch sẽ không cảnh báo bạn nếu có là những thay đổi trong đó. Theo nghĩa đó tôi không nghĩ rằng họ là thừa. Xem infoq.com/presentations/integration-tests-scam để biết thêm thông tin về các bài kiểm tra dựa trên giả.
guillaume31

1
... đồng ý tức là kiểm tra logic xung quanh cuộc gọi giao diện
Rob

1
Chắc chắn có thể thêm các ngoại lệ không được kiểm soát, các điều kiện tiên quyết chưa được khai báo và trạng thái ẩn, vào danh sách những thứ làm cho giao diện ít bị gõ tĩnh hơn, và do đó biện minh cho thử nghiệm dựa trên giả thay vì biên dịch đơn giản. Tuy nhiên, vấn đề là khi các khía cạnh đó thay đổi, đặc điểm kỹ thuật của chúng được ẩn giấu và phân phối trong các thử nghiệm của tất cả các khách hàng. Có khả năng không được cập nhật, và vì vậy hãy ngồi đó im lặng giấu một con bọ đằng sau một con bọ xanh.
soru

"Đặc điểm kỹ thuật của họ là ẩn": không phải nếu bạn viết các bài kiểm tra hợp đồng cho các giao diện của mình ( blog.thecodewhisperer.com/2011/07/07/contract-tests-an-example ) và bám sát chúng khi thiết lập giả.
guillaume31

5

Thử nghiệm dựa trên điểm cuối sẽ mất bao lâu để chạy thử nghiệm dựa trên giả? Nếu nó dài hơn đáng kể, thì đúng, nó đáng để đầu tư thời gian viết bài kiểm tra của bạn để làm cho bài kiểm tra nhanh hơn - bởi vì bạn sẽ phải chạy chúng nhiều lần. Nếu nó không dài hơn đáng kể, mặc dù các bài kiểm tra dựa trên điểm cuối không phải là bài kiểm tra đơn vị "thuần túy", miễn là chúng làm tốt công việc kiểm tra đơn vị, không có lý do gì để tôn giáo về nó.


4

Tôi hoàn toàn đồng ý với phản hồi của guillaume31, không bao giờ chế giễu các loại mà bạn không sở hữu!.

Thông thường, một thử nghiệm đau (chế nhạo một giao diện phức tạp) phản ánh một vấn đề trong thiết kế của bạn. Có lẽ bạn cần một số trừu tượng giữa mô hình của bạn và mã truy cập dữ liệu của bạn, ví dụ biểu mẫu bằng cách sử dụng kiến ​​trúc lục giác và mô hình kho lưu trữ theo cách thông thường nhất để giải quyết loại vấn đề này.

Nếu bạn muốn thực hiện kiểm tra tích hợp để kiểm tra mọi thứ, hãy thực hiện kiểm tra tích hợp, nếu bạn muốn thực hiện kiểm tra đơn vị vì bạn đang kiểm tra logic của mình, hãy thực hiện kiểm tra đơn vị và cách ly sự kiên trì. Nhưng khi thực hiện kiểm tra tích hợp vì bạn không biết cách tách logic của mình khỏi hệ thống bên ngoài (hoặc vì cô lập nỗi đau) là mùi lớn, bạn đang chọn tích hợp trên đơn vị cho một giới hạn trong thiết kế của bạn không phải là nhu cầu thực sự để kiểm tra tích hợp.

Hãy xem mẫu nói chuyện này Ian Cooper: http://vimeo.com/68375232 , anh ấy nói về kiến ​​trúc và thử nghiệm hình lục giác, anh ấy nói về khi nào và cái gì để chế giễu, một cuộc nói chuyện thực sự truyền cảm hứng giải quyết nhiều câu hỏi như của bạn về TDD thực sự .


1

TL; DR - Cách tôi nhìn thấy, nó phụ thuộc vào số tiền bạn bỏ ra cho các bài kiểm tra, và liệu có tốt hơn khi chi tiêu nhiều hơn cho hệ thống thực tế của bạn thay vào đó.

Phiên bản dài:

Một số câu trả lời hay ở đây, nhưng tôi cho rằng nó khác: thử nghiệm là một hoạt động kinh tế cần phải tự trả lại và nếu thời gian bạn bỏ ra không được trả lại cho sự phát triển và độ tin cậy của hệ thống (hoặc bất cứ điều gì khác bạn muốn thoát ra của các bài kiểm tra) sau đó bạn có thể đang đầu tư tồi; bạn đang kinh doanh trong việc xây dựng các hệ thống, không phải viết bài kiểm tra. Do đó, giảm nỗ lực viết và duy trì các bài kiểm tra là rất quan trọng.

Ví dụ: một số giá trị chính tôi đạt được từ các bài kiểm tra là:

  • Độ tin cậy (và do đó tốc độ phát triển): mã tái cấu trúc / tích hợp khung mới / trao đổi một thành phần / cổng sang một nền tảng khác, hãy tự tin rằng công cụ vẫn hoạt động
  • Phản hồi thiết kế: phản hồi "sử dụng mã" cổ điển của TDD / BDD trên các giao diện cấp thấp / trung bình của bạn

Thử nghiệm đối với một điểm cuối trực tiếp vẫn sẽ cung cấp những điều này.

Một số nhược điểm để thử nghiệm đối với điểm cuối trực tiếp:

  • Thiết lập môi trường - cấu hình và chuẩn hóa môi trường chạy thử nghiệm là công việc nhiều hơn và các thiết lập môi trường khác nhau có thể dẫn đến hành vi khác nhau một cách tinh tế
  • Không trạng thái - làm việc chống lại điểm cuối trực tiếp có thể kết thúc việc thúc đẩy các bài kiểm tra viết dựa trên trạng thái điểm cuối đột biến, rất mong manh và khó lý luận (nghĩa là khi có điều gì đó không thành công, có phải là do thất bại không?)
  • Môi trường chạy thử nghiệm rất mong manh - nếu thử nghiệm thất bại, đó là thử nghiệm, mã hoặc điểm cuối trực tiếp?
  • Tốc độ chạy - điểm cuối trực tiếp thường chậm hơn và đôi khi khó song song hơn
  • Tạo các trường hợp cạnh để thử nghiệm - thường là tầm thường với một bản giả, đôi khi là một điểm đau với điểm cuối trực tiếp (ví dụ: các trường hợp khó cài đặt là lỗi vận chuyển / HTTP)

Nếu tôi ở trong tình huống này, và những hạn chế dường như không phải là vấn đề trong khi chế nhạo điểm cuối làm chậm bài kiểm tra của tôi, tôi sẽ kiểm tra điểm cuối trực tiếp trong một nhịp tim, miễn là tôi chắc chắn kiểm tra lại sau một thời gian để thấy rằng những hạn chế không trở thành vấn đề trong thực tế.


1

Từ góc độ thử nghiệm, có một số yêu cầu bắt buộc phải:

  • Kiểm tra (đơn vị hoặc cách khác) không bao giờ có cách chạm vào dữ liệu sản xuất
  • Kết quả từ một thử nghiệm không bao giờ được ảnh hưởng đến kết quả của một thử nghiệm khác
  • Bạn phải luôn bắt đầu từ một vị trí đã biết

Đó là một thách thức lớn khi kết nối với bất kỳ nguồn nào duy trì trạng thái bên ngoài các bài kiểm tra của bạn. Đó không phải là TDD "thuần túy", nhưng nhóm Ruby on Rails đã giải quyết vấn đề này theo cách có thể phù hợp với mục đích của bạn. Khung kiểm tra đường ray hoạt động theo cách này:

  • Cấu hình thử nghiệm được chọn tự động khi chạy thử nghiệm đơn vị
  • Cơ sở dữ liệu đã được tạo và khởi tạo khi bắt đầu chạy thử nghiệm đơn vị
  • Cơ sở dữ liệu đã bị xóa sau khi chạy thử nghiệm đơn vị
  • Nếu sử dụng SqlLite, cấu hình thử nghiệm đã sử dụng cơ sở dữ liệu RAM

Tất cả công việc này đã được tích hợp vào bộ kiểm tra và nó hoạt động khá tốt. Có rất nhiều điều nữa, nhưng những điều cơ bản là đủ cho cuộc trò chuyện này.

Trên các nhóm khác nhau mà tôi đã làm việc theo thời gian, chúng tôi sẽ đưa ra các lựa chọn sẽ thúc đẩy mã được kiểm tra ngay cả khi đó không phải là con đường chính xác nhất. Lý tưởng nhất, chúng tôi sẽ bọc tất cả các cuộc gọi đến một cửa hàng dữ liệu với mã chúng tôi kiểm soát. Về lý thuyết, nếu bất kỳ dự án cũ nào có được tài trợ mới, chúng tôi có thể quay lại và chuyển chúng khỏi cơ sở dữ liệu bị ràng buộc với Hadoop bị ràng buộc bằng cách tập trung sự chú ý của chúng tôi vào một số ít các lớp học.

Các khía cạnh quan trọng là không gây rối với dữ liệu sản xuất và đảm bảo bạn đang thực sự kiểm tra những gì bạn nghĩ rằng bạn đang kiểm tra. Điều thực sự quan trọng là có thể đặt lại dịch vụ bên ngoài về đường cơ sở đã biết theo yêu cầu - ngay cả từ mã của bạn.

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.