Làm cách nào để kiểm tra mã phụ thuộc vào các API phức tạp (ví dụ Amazon S3)?


13

Tôi đang vật lộn với việc thử nghiệm một phương pháp tải tài liệu lên Amazon S3, nhưng tôi nghĩ câu hỏi này áp dụng cho bất kỳ API phụ thuộc / tầm thường bên ngoài nào. Tôi chỉ đưa ra ba giải pháp tiềm năng nhưng không có giải pháp nào thỏa đáng:

  1. Đừng chạy mã, thực sự tải lên tài liệu, kiểm tra với API của AWS rằng nó đã được tải lên và xóa nó khi kết thúc bài kiểm tra. Điều này sẽ làm cho bài kiểm tra rất chậm, sẽ tốn tiền mỗi khi bài kiểm tra được chạy và sẽ không trả lại kết quả tương tự.

  2. Mock S3. Đây là siêu lông bởi vì tôi không biết gì về bên trong của đối tượng đó và nó cảm thấy sai lầm vì nó quá phức tạp.

  3. Chỉ cần đảm bảo rằng MyObject.upload () được gọi với các đối số phù hợp và tin tưởng rằng tôi đang sử dụng đúng đối tượng S3. Điều này làm phiền tôi vì không có cách nào để biết chắc chắn tôi đã sử dụng API S3 một cách chính xác từ các thử nghiệm.

Tôi đã kiểm tra cách Amazon kiểm tra SDK của riêng họ và họ thực hiện mọi thứ. Họ có một người trợ giúp 200 dòng mà chế giễu. Tôi không cảm thấy nó thực tế đối với tôi để làm điều tương tự.

Tôi giải quyết điều này như thế nào?


Không phải là một câu trả lời, nhưng trong thực tế, chúng tôi sử dụng ba phương pháp bạn đã tiếp xúc.
jlhonora

Câu trả lời:


28

Có hai vấn đề chúng ta phải xem xét ở đây.

Đầu tiên là bạn dường như đang xem xét tất cả các bài kiểm tra của bạn từ góc độ kiểm tra đơn vị. Các bài kiểm tra đơn vị là vô cùng có giá trị, nhưng không phải là loại kiểm tra duy nhất. Các thử nghiệm thực sự có thể được chia thành nhiều lớp khác nhau, từ các thử nghiệm đơn vị rất nhanh đến các thử nghiệm tích hợp ít nhanh hơn đến các thử nghiệm chấp nhận chậm hơn . (Có thể có nhiều lớp hơn nữa bị phá vỡ, như các bài kiểm tra chức năng .)

Thứ hai là bạn đang trộn lẫn các cuộc gọi đến mã của bên thứ ba với logic kinh doanh của bạn, tạo ra các thách thức thử nghiệm và có thể làm cho mã của bạn dễ vỡ hơn.

Các bài kiểm tra đơn vị nên nhanh và nên được chạy thường xuyên. Việc phụ thuộc chế độ giả giúp giữ cho các thử nghiệm này chạy nhanh, nhưng có khả năng đưa ra các lỗ hổng trong phạm vi bảo hiểm nếu sự phụ thuộc thay đổi và giả lập không. Mã của bạn có thể bị hỏng trong khi các bài kiểm tra của bạn vẫn chạy màu xanh lá cây. Một số thư viện chế giễu sẽ cảnh báo bạn nếu giao diện của người phụ thuộc thay đổi, những người khác không thể.

Mặt khác, các kiểm tra tích hợp được thiết kế để kiểm tra các tương tác giữa các thành phần, bao gồm các thư viện của bên thứ ba. Không nên sử dụng giả ở cấp độ thử nghiệm này vì chúng tôi muốn xem đối tượng thực tế tương tác với nhau như thế nào. Bởi vì chúng tôi đang sử dụng các đối tượng thực tế, các thử nghiệm này sẽ chậm hơn và chúng tôi sẽ không chạy chúng gần như thường xuyên như các thử nghiệm đơn vị của chúng tôi.

Các thử nghiệm chấp nhận nhìn ở mức độ cao hơn, kiểm tra rằng các yêu cầu cho phần mềm được đáp ứng. Các thử nghiệm này chạy với toàn bộ hệ thống hoàn chỉnh sẽ được triển khai. Một lần nữa, không nên chế nhạo.

Một hướng dẫn mọi người đã tìm thấy có giá trị liên quan đến giảkhông chế giễu các loại bạn không sở hữu . Amazon sở hữu API thành S3 để họ có thể đảm bảo nó không thay đổi bên dưới chúng. Mặt khác, bạn không có những đảm bảo này. Do đó, nếu bạn giả lập API S3 trong các thử nghiệm của mình, nó có thể thay đổi và phá vỡ mã của bạn, trong khi tất cả các thử nghiệm của bạn đều hiển thị màu xanh lá cây. Vậy làm thế nào để chúng tôi đơn vị kiểm tra mã sử dụng thư viện của bên thứ ba?

Vâng, chúng tôi không. Nếu chúng tôi làm theo hướng dẫn, chúng tôi không thể chế giễu các đối tượng chúng tôi không sở hữu. Nhưng nếu chúng ta sở hữu những phụ thuộc trực tiếp, chúng ta có thể chế nhạo họ. Nhưng bằng cách nào? Chúng tôi tạo trình bao bọc riêng cho API S3. Chúng tôi có thể làm cho nó trông rất giống API S3 hoặc chúng tôi có thể làm cho nó phù hợp với nhu cầu của chúng tôi chặt chẽ hơn (ưu tiên). Chúng ta thậm chí có thể làm cho nó trừu tượng hơn một chút, nói một PersistenceServicethay vì một AmazonS3Bucket. PersistenceServicesẽ là một giao diện với các phương thức như #save(Thing)#fetch(ThingId), các loại phương thức chúng ta có thể muốn xem (đây là những ví dụ, bạn thực sự có thể muốn các phương thức khác nhau). Bây giờ chúng ta có thể triển khai PersistenceServiceAPI S3 (giả sử a S3PersistenceService), gói gọn nó khỏi mã gọi của chúng tôi.

Bây giờ đến mã gọi API S3. Chúng ta cần thay thế các cuộc gọi đó bằng các cuộc gọi đến một PersistenceServiceđối tượng. Chúng tôi sử dụng tiêm phụ thuộc để truyền của chúng tôi PersistenceServicevào đối tượng. Điều quan trọng không phải là yêu cầu a S3PersistenceService, mà là yêu cầu a PersistenceService. Điều này cho phép chúng tôi trao đổi thực hiện trong các thử nghiệm của chúng tôi.

Tất cả các mã được sử dụng để sử dụng API S3 trực tiếp bây giờ đều sử dụng của chúng tôi PersistenceServiceS3PersistenceServicegiờ đây chúng tôi thực hiện tất cả các cuộc gọi đến API S3. Trong các thử nghiệm của chúng tôi, chúng tôi có thể giả lập PersistenceService, vì chúng tôi sở hữu nó và sử dụng giả để đảm bảo rằng mã của chúng tôi thực hiện các cuộc gọi chính xác. Nhưng bây giờ lá làm thế nào để kiểm tra S3PersistenceService. Nó có cùng một vấn đề như trước đây: chúng tôi không thể kiểm tra đơn vị mà không gọi cho dịch vụ bên ngoài. Vì vậy, chúng tôi không đơn vị kiểm tra nó. Chúng tôi có thể giả định các phụ thuộc API S3, nhưng điều này sẽ mang lại cho chúng tôi ít nhiều sự tự tin. Thay vào đó, chúng tôi phải kiểm tra nó ở cấp độ cao hơn: kiểm tra tích hợp.

Điều này nghe có vẻ hơi rắc rối khi nói rằng chúng ta không nên đơn vị kiểm tra một phần mã của mình, nhưng hãy nhìn vào những gì chúng ta đã đạt được. Chúng tôi đã có một loạt mã ở khắp nơi mà chúng tôi không thể kiểm tra đơn vị mà bây giờ có thể được kiểm tra đơn vị thông qua PersistenceService. Chúng tôi có thư viện bên thứ ba lộn xộn trong một lớp thực hiện. Lớp đó sẽ cung cấp các chức năng cần thiết để sử dụng API, nhưng không có logic kinh doanh bên ngoài nào được đính kèm. Do đó, một khi nó được viết, nó sẽ rất ổn định và không nên thay đổi nhiều. Chúng tôi có thể dựa vào các thử nghiệm chậm hơn mà chúng tôi không chạy thường xuyên vì mã ổn định.

Bước tiếp theo là viết các bài kiểm tra tích hợp cho S3PersistenceService. Chúng nên được phân tách bằng tên hoặc thư mục để chúng tôi có thể chạy chúng tách biệt khỏi các bài kiểm tra đơn vị nhanh của chúng tôi. Kiểm thử tích hợp thường có thể sử dụng các khung kiểm tra tương tự như kiểm thử đơn vị nếu mã đủ thông tin, vì vậy chúng tôi không cần phải tìm hiểu một công cụ mới. Mã thực tế cho bài kiểm tra tích hợp là những gì bạn sẽ viết cho Tùy chọn 1 của mình.


câu hỏi là làm thế nào để bạn chạy thử nghiệm tích hợp hay đúng hơn là e2e cho API mà bạn trưng ra. Bạn không thể chế nhạo Dịch vụ kiên trì vì những lý do rõ ràng. Hoặc là tôi đã hiểu nhầm một cái gì đó, hoặc thêm một lớp khác vào giữa API ứng dụng và API AWS, sẽ không mang lại cho bạn điều gì hơn là có thời gian dễ dàng hơn để thực hiện các bài kiểm tra đơn vị
Yerken 17/2/2017

@Yerken Khi tôi đang nghĩ về nó, tôi khá chắc chắn rằng tôi có thể điền vào một câu trả lời dài khác cho câu hỏi đó. Điều đó thậm chí có thể đáng giá cho bạn bởi vì bạn có thể nhận được nhiều hơn chỉ là phản ứng của tôi.
cbojar

4

Bạn cần làm cả hai.

Chạy, tải lên và xóa là một bài kiểm tra tích hợp. Nó giao tiếp với một hệ thống bên ngoài và do đó có thể được dự kiến ​​sẽ chạy chậm. Nó có thể không phải là một phần của mỗi bản dựng bạn làm tại địa phương, nhưng nó phải là một phần của bản dựng CI hoặc bản dựng hàng đêm. Điều đó bù đắp cho sự chậm chạp của các thử nghiệm đó và vẫn cung cấp giá trị của việc thử nghiệm tự động.

Bạn cũng cần unittests chạy nhanh hơn. Vì nói chung là thông minh để không khó phụ thuộc vào hệ thống bên ngoài quá nhiều (vì vậy bạn có thể trao đổi thực hiện hoặc chuyển đổi), có lẽ bạn nên thử và viết một giao diện đơn giản trên S3 mà bạn có thể mã hóa. Mock giao diện đó trong unittests để bạn có thể có unittests chạy nhanh.

Các thử nghiệm đầu tiên kiểm tra xem mã của bạn có thực sự hoạt động với S3 không, các thử nghiệm thứ hai mà mã của bạn gọi chính xác mã nói chuyện với S3.


2

Tôi muốn nói rằng điều đó phụ thuộc vào mức độ phức tạp của việc bạn sử dụng API .

  1. Bạn chắc chắn cần phải thực hiện ít nhất một số thử nghiệm thực sự gọi API S3 và xác nhận rằng nó hoạt động từ đầu đến cuối.

  2. Bạn chắc chắn cũng cần phải thực hiện kiểm tra bổ sung mà không thực sự gọi API, vì vậy bạn có thể kiểm tra phần mềm của riêng mình một cách đầy đủ mà không cần phải gọi API mọi lúc.

Câu hỏi còn lại là: bạn có cần phải giả lập API không?

Và tôi nghĩ điều đó phụ thuộc vào mức độ bạn làm với nó. Nếu bạn chỉ thực hiện một hoặc hai hành động đơn giản, tôi không nghĩ bạn cần phải giải quyết tất cả những rắc rối của một bản nhái. Tôi sẽ hài lòng với việc chỉ kiểm tra việc sử dụng các chức năng của mình và thực hiện một số thử nghiệm trực tiếp.

Tuy nhiên, nếu việc sử dụng của bạn phức tạp hơn, với các kịch bản khác nhau và các biến khác nhau có thể ảnh hưởng đến kết quả, có lẽ bạn cần phải mô phỏng nó để kiểm tra kỹ lưỡng hơn.


1

Thêm vào các câu trả lời trước, câu hỏi chính là liệu bạn có muốn giả lập API S3 cho các bài kiểm tra của mình hay không.

Thay vì tự chế nhạo các phản hồi S3 riêng lẻ, bạn có thể tận dụng một số khung mô phỏng hiện có rất tinh vi. Chẳng hạn, moto cung cấp chức năng rất giống với API S3 thực tế.

Bạn cũng có thể xem LocalStack , một khung kết hợp các công cụ hiện có và cung cấp một môi trường đám mây cục bộ đầy đủ chức năng (bao gồm S3) tạo điều kiện cho thử nghiệm tích hợp.

Mặc dù một số trong các công cụ này được viết bằng các ngôn ngữ khác (Python), nhưng thật dễ dàng để tạo ra môi trường kiểm tra trong một quy trình bên ngoài từ các bài kiểm tra của bạn, giả sử, Java / JUnit.

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.