Ưu điểm và nhược điểm để làm mã giàn giáo thử nghiệm đơn vị phổ biến


8

Đối với dự án mà nhóm của tôi và tôi đang thực hiện, chúng tôi thường thấy rằng chúng tôi cần những đoạn mã giàn giáo lớn. Tạo các đối tượng miền với các giá trị chính xác, thiết lập các giả lập cho các kho lưu trữ, xử lý bộ đệm, ... là tất cả những điều xảy ra phổ biến trong các bài kiểm tra. Một số lần chúng tôi làm việc với cùng các đối tượng cơ bản là trung tâm của miền (người, ...) nên rất nhiều thử nghiệm tạo ra các phiên bản của các đối tượng này để các đối tượng khác hoạt động. Chúng tôi có rất nhiều giải pháp khác nhau bằng cách sử dụng tên miền cơ sở nên loại mã này thường được trải rộng trên các giải pháp đó.

Tôi đã suy nghĩ về việc tạo ra các lớp phổ biến làm rất nhiều giàn giáo này. Điều này sẽ cho phép chúng tôi yêu cầu một người được khởi tạo hoàn toàn với mọi thứ được thiết lập (truy cập qua kho lưu trữ, bộ nhớ đệm ...). Điều này loại bỏ mã trùng lặp khỏi các thử nghiệm đơn vị riêng lẻ của chúng tôi nhưng cũng có nghĩa là có một lượng lớn mã có thể 'quá nhiều' cho mỗi thử nghiệm (vì nó sẽ thiết lập một đối tượng đầy đủ chứ không chỉ các bộ phận cần thiết).

Có ai đã từng làm điều này? Có bất kỳ hiểu biết, nhận xét, suy nghĩ ... bạn có thể cung cấp có thể xác nhận hoặc vô hiệu hóa phương pháp này?


Tôi đã chỉnh sửa câu hỏi của bạn một chút trước khi di chuyển nó ở đây để xóa những thứ thường đi vào câu trả lời. Với việc bạn liệt kê những ưu điểm và nhược điểm trong chính câu hỏi, nó sẽ giảm cơ hội cho ai đó đưa ra câu trả lời toàn diện không trùng lặp với những gì bạn đã nói. Bằng cách này, các điểm bạn đã thực hiện sẽ xuất hiện một cách lý tưởng như là một phần của câu trả lời. Nếu họ không, vui lòng đăng lại chúng dưới dạng câu trả lời và việc bỏ phiếu của cộng đồng trên đó có thể cho bạn biết bạn có đúng với số tiền đó hay không.
Adam Lear

Câu trả lời:


4
Creating domain objects with correct values

Tôi sử dụng mẫu trình xây dựng để tạo các đối tượng miền cho các thử nghiệm như chi tiết trong cuốn sách " Phát triển phần mềm hướng đối tượng ". Các trình xây dựng có các phương thức tĩnh tạo các giá trị mặc định cho các đối tượng phổ biến với các phương thức để ghi đè các giá trị mặc định.

User user = UserBuilder.anAdminUser().withEmail("test@example.com").build();

Bạn có thể kết hợp những thứ này để tạo ra các đối tượng phức tạp hơn.

Chúng tôi cũng sử dụng tính kế thừa lớp trường hợp thử nghiệm với các mô phỏng thường được sử dụng cho các loại thử nghiệm đơn vị cụ thể - ví dụ: các thử nghiệm bộ điều khiển mvc thường yêu cầu các mô hình / cuống tương tự cho các đối tượng yêu cầu và phản hồi.


2

Thiết lập cho tất cả các thử nghiệm có thể là một ý tưởng tốt, đặc biệt nếu bạn thực hiện triển khai. Thay vì sử dụng giả, chúng tôi tạo, triển khai và điền vào cơ sở dữ liệu kiểm tra và sau đó trỏ thử nghiệm vào ví dụ. Không chính xác theo cách bạn nên làm theo hướng dẫn, nhưng nó hoạt động, thậm chí còn hơn thế đối với chúng tôi vì chúng tôi sử dụng mã triển khai của mình để làm điều đó.


Giả sử rằng không có sự phụ thuộc vào cơ sở dữ liệu nào và các đối tượng là của POCO, bạn vẫn sẽ xem xét một cơ sở dữ liệu để truy xuất chúng từ đâu chứ? Có phải duy trì một cơ sở dữ liệu chỉ được sử dụng để thử nghiệm khác với việc phải duy trì mã để tạo các đối tượng chỉ được sử dụng để thử nghiệm không?
JDT

2

Bedwyr Humphreys đang nói về một giải pháp Builder mà tôi đã sử dụng một vài lần và nó thực sự hoạt động tốt. Hầu như không có sự sao chép mã và xây dựng các đối tượng miền một cách sạch đẹp.

User user = UserBuilder.anAdminUser().withEmail("test@example.com").build();

Tôi không phải là một fan hâm mộ của việc tạo mã (giàn giáo, codemith, lblgen, ..). Nó chỉ giúp bạn viết mã trùng lặp nhanh hơn nhiều, không thực sự thân thiện với bảo trì. Nếu một khung làm cho bạn viết nhiều mã (kiểm tra) trùng lặp, có thể bạn cần tìm cách di chuyển cơ sở mã ra khỏi khung.

Nếu bạn tiếp tục viết mã kho lưu trữ, bạn có thể giải quyết vấn đề này với kho lưu trữ cơ sở chung và có một lớp kiểm tra cơ sở chung mà đơn vị kiểm tra của bạn kế thừa từ đó.

Để tránh sao chép mã AOP cũng có thể giúp cho những việc như đăng nhập, lưu trữ, ...


1

Bạn có thể muốn xem xét lại thiết kế mã bạn đang kiểm tra. Có lẽ nó cần một số trường hợp của mẫu thiết kế Facade? Mã kiểm tra của bạn có thể sử dụng Mặt tiền và sẽ đơn giản hơn.


Đó là một cách tiếp cận hợp lệ - nhưng không phải cho cơ sở mã chúng ta có. Tôi hiện đang làm việc với các lớp Builder tạo các thông báo dựa trên XML từ các đối tượng miền của chúng tôi. Không có số lượng các lớp mặt tiền sẽ ngăn tôi khỏi phải cắm vào các đối tượng được xây dựng đầy đủ tại một số điểm - điều mà tôi đã phải làm nhiều lần trong các giải pháp khác nhau.
JDT

1

Tôi có thể liên quan đến câu hỏi này. Trong nhóm của tôi, chúng tôi đã thử làm TDD trước đây và đó là một câu chuyện tương tự, quá nhiều bài kiểm tra đòi hỏi rất nhiều phương pháp giàn giáo / tiện ích mà chúng tôi đơn giản không có. Do áp lực thời gian và một vài quyết định không đúng đắn khác, chúng tôi đã kết thúc với các bài kiểm tra đơn vị là những thứ rất dài và được phát minh lại. Trong quá trình phát hành, những bài kiểm tra đơn vị đó trở nên phức tạp và khó bảo trì, chúng tôi đã phải bỏ chúng.

Tôi hiện đang làm việc với một vài nhà phát triển khác để giới thiệu lại TDD vào nhóm, nhưng thay vì chỉ nói với mọi người, hãy viết bài kiểm tra, lần này chúng tôi muốn làm điều đó một cách cẩn thận và mọi người có các kỹ năng phù hợp và các công cụ phù hợp. Sự vắng mặt của mã hỗ trợ chung là một điều chúng tôi đã xác định nơi chúng tôi cần cải thiện để khi những người khác bắt đầu viết bài kiểm tra, tất cả mã họ viết sẽ nhỏ và đi vào điểm chính.

Tôi chưa có nhiều kinh nghiệm trong lĩnh vực này như tôi muốn, nhưng một vài điều tôi đề xuất dựa trên công việc chúng tôi đã làm cho đến nay và một số bài tập về nhà tôi đã làm:

  1. Mã thông thường là một điều tốt. Làm cùng một công việc 5 lần không có ý nghĩa và dưới áp lực thời gian, ít nhất 4 trong số những lần đó sẽ được thực hiện một nửa.
  2. Kế hoạch của tôi là xây dựng khuôn khổ chung, sau đó xây dựng đội ngũ lãnh đạo TDD bao gồm 4 - 6 nhà phát triển. Sau đó đã viết bài kiểm tra đơn vị, tìm hiểu khuôn khổ và cung cấp phản hồi về nó. Sau đó, những người này đi ra ngoài với phần còn lại của nhóm và hướng dẫn những người khác sản xuất các bài kiểm tra đơn vị có thể bảo trì, sử dụng sức mạnh của khung. Cũng có những kẻ này thu thập thông tin phản hồi và đưa nó trở lại vào khuôn khổ.
  3. Đối với các ví dụ bạn đã cung cấp với lớp Person, tôi thực sự đang điều tra việc sử dụng các khung mockpp hoặc googlemock . Hiện tại đang nghiêng về googlemock, nhưng vẫn chưa thử. Trong cả hai trường hợp, tại sao viết một cái gì đó có thể được "mượn"
  4. Hãy cẩn thận về việc tạo ra các đồ đạc "thần" để khởi tạo các đối tượng cho tất cả các thử nghiệm bất kể các thử nghiệm đó có thực sự cần các đối tượng đó hay không. Đây là cái mà xUnit Test Forms gọi là "General Fixture Pattern". Điều này có thể gây ra một số vấn đề như a) mỗi thử nghiệm mất quá nhiều thời gian để chạy do mã thiết lập quá mức và b) các thử nghiệm kết thúc có quá nhiều phụ thuộc không cần thiết. Trong khung của chúng tôi, mỗi lớp kiểm tra chọn chính xác các tính năng cần thiết để thực hiện, do đó không bao gồm hành lý không cần thiết (trong tương lai chúng tôi có thể thay đổi nó thành từng phương thức chọn độc lập). Tôi có một số cảm hứng từ Boost và Modern C ++ Designvà đã đưa ra một lớp mẫu cơ sở có một mpl :: vector các tính năng cần thiết và xây dựng hệ thống phân cấp lớp tùy chỉnh cụ thể cho thử nghiệm đó. Một số đội trưởng giải mã cruch thực sự tiện lợi nhẫn siêu điên ma thuật mẫu :)

1

"Bất kỳ vấn đề nào trong khoa học máy tính đều có thể được giải quyết bằng một lớp bổ sung bổ sung. Nhưng điều đó thường sẽ tạo ra một vấn đề khác." - David Wheeler

(từ chối trách nhiệm: Tôi là một phần của nhóm của JDT, vì vậy tôi có thêm một số kiến ​​thức bên trong về vấn đề được trình bày ở đây)

Vấn đề cốt yếu ở đây là các đối tượng trong khung công tác mong đợi một kết nối cơ sở dữ liệu, vì nó dựa trên khung CSLA của Rockford Lhotka một cách lỏng lẻo. Điều này làm cho việc chế nhạo chúng gần như không thể (vì bạn phải thay đổi khung để hỗ trợ điều này) và cũng vi phạm nguyên tắc hộp đen mà một bài kiểm tra đơn vị nên có.

Bản thân giải pháp đề xuất của bạn, mặc dù không phải là một ý tưởng tồi, sẽ không chỉ đòi hỏi RẤT NHIỀU công việc để có được một giải pháp ổn định, mà còn thêm một lớp các lớp khác cần duy trì và mở rộng, thêm phức tạp hơn nữa vào một tình hình phức tạp.

Mặc dù tôi đồng ý rằng bạn nên luôn tìm kiếm giải pháp tốt nhất, nhưng trong tình huống thực tế như thế này, việc thực tế cũng có giá trị của nó.

Và thực tiễn cho thấy các tùy chọn sau:

Sử dụng một cơ sở dữ liệu.

Vâng, tôi biết về mặt kỹ thuật nói nó không phải là một bài kiểm tra đơn vị "thực sự" nữa, nhưng nói đúng ra thời điểm bạn vượt qua một ranh giới lớp trong bài kiểm tra của mình, nó cũng không phải là một bài kiểm tra đơn vị thực sự nữa. Điều chúng ta cần tự hỏi mình ở đây là, chúng ta có muốn thử nghiệm đơn vị 'thuần túy' sẽ yêu cầu vô số giàn giáo và mã keo hay chúng ta muốn mã thử nghiệm ?

Bạn cũng có thể sử dụng thực tế là khung được sử dụng đóng gói tất cả quyền truy cập cơ sở dữ liệu cho bạn và chạy thử nghiệm của bạn đối với cơ sở dữ liệu hộp cát sạch. Sau đó, nếu bạn chạy từng thử nghiệm trong giao dịch của riêng mình và quay lại vào cuối mỗi thử nghiệm 'logic', bạn không nên có bất kỳ vấn đề nào về sự phụ thuộc lẫn nhau hoặc thứ tự thử nghiệm.

Đừng thử và ra khỏi cơ sở dữ liệu một cơ sở dữ liệu.


Sam, xem bình luận của tôi về câu trả lời của Tony Hopkinson. Bạn có làm như vậy không nếu chúng ta đang xử lý một dự án chỉ là các lớp POCO?
JDT

Trừ khi bạn đang thử nghiệm một thuật toán tự tồn tại mà không cần tài nguyên bên ngoài, chắc chắn. Ý tưởng là cơ sở dữ liệu 'kiểm tra' của bạn chỉ chứa dữ liệu tối thiểu và mọi dữ liệu kiểm tra phi cơ sở hạ tầng sẽ cần được chèn bởi chính các kiểm tra, do đó giảm chi phí bảo trì của bạn. Nhưng phải thừa nhận rằng, với các đối tượng POCO 'rõ ràng', trường hợp đối với cơ sở dữ liệu thử nghiệm không mạnh bằng.
Sam

0

Tôi sẽ cảnh báo vì có quá nhiều mã làm quá nhiều 'ma thuật đen' mà không có nhà phát triển biết chính xác những gì đang được thiết lập. Ngoài ra, trong thời gian, bạn sẽ trở nên rất phụ thuộc vào mã / dữ liệu này. Đó là lý do tại sao tôi không phải là người hâm mộ dựa trên các bài kiểm tra của bạn trên cơ sở dữ liệu kiểm tra. Tôi tin rằng cơ sở dữ liệu kiểm tra là để thử nghiệm như một người dùng, không phải cho các thử nghiệm tự động.

Điều đó nói rằng, vấn đề của bạn là có thật. Tôi sẽ thực hiện một số phương pháp phổ biến để thiết lập dữ liệu bạn cần thường xuyên. Tốt nhất, hãy thử tham số hóa các phương thức, bởi vì các thử nghiệm nhất định cần dữ liệu khác nhau.

Nhưng tôi sẽ tránh tạo đồ thị đối tượng lớn. Tốt nhất là chạy thử nghiệm với mức tối thiểu của dữ liệu họ cần. Nếu có nhiều dữ liệu khác, bạn có thể bất ngờ ảnh hưởng đến kết quả kiểm tra của bạn (trường hợp xấu nhất).

Tôi muốn giữ các bài kiểm tra của mình là "silo'ed" nhất có thể. Đó là một câu hỏi chủ quan mặc dù. Nhưng tôi sẽ sử dụng các phương thức phổ biến với các tham số để bạn có thể thiết lập dữ liệu thử nghiệm của mình chỉ trong một vài dòng mã.


0

Tất cả các khả năng tóm tắt trong các câu trả lời:

Sử dụng mẫu Builder (Bedwyr Humphreys, DXM và Pascal Mestdach)

Ưu điểm:

  • Không sao chép mã trong các thử nghiệm
  • Có thể kết hợp các nhà xây dựng khác nhau cho các thử nghiệm phức tạp
  • Giao diện sạch sẽ
  • Đồ thị đối tượng lớn từ các nhà xây dựng có thể ảnh hưởng đến kết quả thử nghiệm

Nhược điểm:

  • Nhà xây dựng phải được viết và bảo trì
  • Mã xây dựng cũng phải được kiểm tra
  • Mã xây dựng sẽ cần chải chuốt và chú ý liên tục

Sử dụng cơ sở dữ liệu thử nghiệm (Tony Hopkinson và Sam)

Ưu điểm:

  • Sự đơn giản
  • Tất cả dữ liệu ở một nơi trung tâm
  • Có thể sử dụng mã dữ liệu đã được phát triển
  • Có thể sử dụng cho các đối tượng miền không phải là POCO (ví dụ: Bản ghi hoạt động, ...)

Nhược điểm:

  • Yêu cầu sử dụng DAL có thể can thiệp vào các bài kiểm tra
  • Không 'thuần' TDD
  • 'Hộp đen', cần xem cơ sở dữ liệu để xem dữ liệu nào mà đối tượng của bạn chứa

Tạo các đối tượng miền trên mỗi bài kiểm tra (Peter)

Ưu điểm:

  • Mã kiểm tra bị cô lập
  • Không có 'hộp đen', những gì bạn thấy trong mã kiểm tra là những gì bạn nhận được

Nhược điểm:

  • Sao chép mã cho các đối tượng phổ biến

Sử dụng Mặt tiền cho các đối tượng miền (Raedwald)

Ưu điểm:

  • Các bài kiểm tra đơn giản

Nhược điểm:

  • Không thể sử dụng trong mọi trường hợp
  • Mã ẩn đằng sau Facade cũng cần thử nghiệm
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.