Làm thế nào để tôi viết bài kiểm tra đối với một dịch vụ cuối cùng phù hợp?


17

Tôi đang xây dựng một dịch vụ trên đỉnh Kho dữ liệu ứng dụng của Google, đây là kho lưu trữ dữ liệu nhất quán. Đối với ứng dụng của tôi, điều này là tốt.

Tuy nhiên, tôi đang phát triển các thử nghiệm thực hiện những việc như đối tượng PUT, sau đó NHẬN đối tượng và kiểm tra các thuộc tính trên đối tượng được trả về. Thật không may, vì kho dữ liệu cuối cùng phù hợp, các thử nghiệm đơn giản này không thể lặp lại.

Làm thế nào để bạn kiểm tra một dịch vụ cuối cùng phù hợp?


2
Tại sao bạn thử nghiệm mong đợi khả năng tái sản xuất đối với một dịch vụ bên ngoài ở nơi đầu tiên?

... Và những gì bạn đang thực sự cố gắng để kiểm tra? ma cua ban? hay của Google?

5
Tôi đang thử nghiệm toàn bộ hệ thống. Tức là, họ là các bài kiểm tra tích hợp, không phải bài kiểm tra đơn vị.
Doug Richardson

3
How can I reproducibly test an eventually consistent service? - Bạn không thể. Bạn phải loại bỏ từ "tái sản xuất" hoặc từ "cuối cùng;" bạn không thể có cả hai.
Robert Harvey

1
Nếu cuối cùng nó phù hợp, cho dù có thể tái sản xuất hay không, bất kỳ kết quả nào cũng sẽ là một kết quả thành công. Bạn đã nói rằng nó tốt cho ứng dụng của bạn, vậy bạn thực sự đang thử nghiệm cái gì? Sự thật? Việc tích hợp với GAE? Ma cua ban?
Laiv

Câu trả lời:


16

Xem xét các yêu cầu phi chức năng khi thiết kế các kiểm tra chức năng của bạn - nếu dịch vụ của bạn có yêu cầu phi chức năng là "Phù hợp trong x (giây / phút / v.v."), chỉ cần chạy các yêu cầu PUT, đợi x, sau đó chạy các yêu cầu GET.

Tại thời điểm đó, nếu dữ liệu chưa 'đến', bạn có thể coi yêu cầu PUT là không phù hợp với yêu cầu của bạn.


7

Bạn thực sự muốn các bài kiểm tra của bạn được nhanh chóng và nhất quán. Nếu bạn bắt đầu tạo các thử nghiệm đôi khi có thể thất bại do tính nhất quán cuối cùng, bạn sẽ bỏ qua thử nghiệm khi thất bại, và sau đó sử dụng nó là gì?

Tạo một dịch vụ giả mạo xử lý các yêu cầu PUT và GET, nhưng có một hoạt động bổ sung để làm cho nó phù hợp. Bài kiểm tra của bạn là:

datastore.do_put(myobj);
datastore.make_consistent();
validate(datastore.do_get(), myobj);

Điều này cho phép bạn kiểm tra hành vi của phần mềm khi GET truy xuất thành công đối tượng PUT. Nó cũng cho phép bạn kiểm tra hành vi của phần mềm khi GET không tìm thấy đối tượng (hoặc đối tượng chính xác) do dịch vụ chưa nhất quán. Chỉ cần bỏ cuộc gọi đến make_consistent().

Vẫn đáng để thử nghiệm tương tác với dịch vụ thực, nhưng chúng nên chạy bên ngoài quy trình phát triển bình thường của bạn, vì chúng sẽ không bao giờ đáng tin cậy 100% (ví dụ: nếu dịch vụ ngừng hoạt động). Những xét nghiệm này nên được sử dụng để:

  1. cung cấp số liệu về thời gian trung bình và trường hợp xấu nhất giữa PUT và GET sau đó trở nên nhất quán; và
  2. xác minh rằng dịch vụ giả của bạn hoạt động tương tự như dịch vụ thật. Xem https://codewithoutrules.com/2016/07/31/verified-fakes/

6

Được, vậy "Bạn đang kiểm tra cái gì" là câu hỏi chính.

  • Tôi đang kiểm tra logic bên trong của mình về những gì xảy ra giả sử công cụ google hoạt động

Trong trường hợp này, bạn nên chế giễu các dịch vụ của google và luôn trả lại phản hồi.

  • Tôi đang kiểm tra logic của mình có thể đối phó với các lỗi thoáng qua mà tôi biết google sẽ tạo ra

Trong trường hợp này, bạn nên mô phỏng các dịch vụ của google và luôn trả lại lỗi thoáng qua trước khi phản hồi chính xác

  • Tôi đang thử nghiệm rằng sản phẩm của tôi sẽ thực sự hoạt động với dịch vụ google thực

Bạn nên tiêm các dịch vụ google thực và chạy thử nghiệm. Nhưng! Mã mà bạn đang kiểm tra phải được xử lý Lỗi tạm thời (thử lại). VÌ bạn nên nhận được một phản ứng nhất quán. (trừ khi google cư xử rất tệ)


+1 cho đề xuất Mock - Tôi sẽ đưa ra nhiều phiếu bầu hơn cho các tùy chọn bổ sung nếu tôi có thể.
đánh bại

6

Sử dụng một trong những điều sau đây:

  • Sau khi PUT, thử lại NHẬN N lần cho đến khi thành công. Thất bại nếu không thành công sau khi N cố gắng.
  • Ngủ giữa PUT và GET

Thật không may, bạn phải chọn các giá trị ma thuật (N hoặc thời gian ngủ) cho cả hai kỹ thuật này.


1
Bạn có thể làm rõ: là những lựa chọn thay thế, hoặc bổ sung? Tôi nghĩ bạn muốn nói rằng chúng là những lựa chọn thay thế - và đó là cách tôi nghĩ về chúng. Nhưng có lẽ tôi đã sai.
Robin Green

1
Chính xác, tôi có nghĩa là chúng là lựa chọn thay thế.
Doug Richardson

2

Theo tôi hiểu, kho dữ liệu Google Cloud cho phép cả truy vấn nhất quán và cuối cùng nhất quán .

Sự đánh đổi là các truy vấn nhất quán mạnh mẽ bị giới hạn tỷ lệ khá nghiêm trọng (điều mà bạn có thể sống trong quá trình thử nghiệm).

Một khả năng có thể là đặt các truy vấn của bạn vào kho dữ liệu trong một trình bao bọc có thể cho phép tính nhất quán mạnh mẽ cho mục đích thử nghiệm.

Ví dụ, bạn có thể có các phương thức được gọi start_debug_strong_consistency()end_debug_strong_consistency().

Phương thức start sẽ tạo một khóa có thể được sử dụng làm khóa tổ tiên cho tất cả các truy vấn tiếp theo và phương thức kết thúc sẽ xóa khóa.

Thay đổi duy nhất đối với các truy vấn thực tế mà bạn đang kiểm tra sẽ là gọi setAncestor(your_debug_key)nếu khóa đó tồn tại.


1

Một cách tiếp cận, đó là tốt đẹp về mặt lý thuyết nhưng có thể không phải luôn luôn thực tế, là làm cho tất cả các hoạt động ghi trong hệ thống được kiểm tra idempotent . Điều đó có nghĩa là, giả sử mã kiểm tra của bạn kiểm tra mọi thứ theo thứ tự tuần tự cố định, bạn có thể thử lại tất cả các lần đọc tất cả ghi riêng lẻ cho đến khi bạn nhận được kết quả mà bạn mong đợi, thử lại cho đến khi hết thời gian mà bạn xác định trong mã kiểm tra bị vượt quá. Đó là, làm điều A1, thử lại nếu cần cho đến khi kết quả là B1, sau đó làm điều A2, thử lại nếu cần cho đến khi kết quả là B2, v.v.

Sau đó, bạn không cần phải kiểm tra các điều kiện tiên quyết của các thao tác ghi, bởi vì các thao tác ghi sẽ kiểm tra chúng cho bạn và bạn chỉ cần thử lại cho đến khi chúng thành công!

Sử dụng cùng thời gian chờ "mặc định" càng nhiều càng tốt, có thể tăng lên nếu toàn bộ hệ thống chậm hơn và ghi đè mặc định riêng lẻ khi thử lại các hoạt động đặc biệt chậm.


1

Một dịch vụ như Google App Engine Datastore dựa trên sự sao chép dữ liệu trên một số điểm hiện diện trên toàn cầu (POP). Bất kỳ thử nghiệm tích hợp nào cho một dịch vụ phù hợp cuối cùng thực sự là một thử nghiệm về tốc độ sao chép của dịch vụ đó trên tập hợp các POP của nó. Tốc độ lan truyền nội dung tới mọi POP trong một dịch vụ nhất định sẽ không giống với mọi POP trong dịch vụ tùy thuộc vào một số yếu tố, như phương pháp sao chép và các vấn đề truyền tải Internet khác nhau - đây là hai ví dụ chiếm phần lớn các báo cáo trong bất kỳ dịch vụ kho dữ liệu nhất quán nào (ít nhất đó là kinh nghiệm của tôi khi tôi đang làm việc cho một CDN lớn).

Để kiểm tra hiệu quả sao chép của một đối tượng trên một nền tảng nhất định, bạn cần đặt thử nghiệm để yêu cầu cùng một đối tượng được đặt gần đây từ từng POP cụ thể của từng dịch vụ. Tôi đang đề nghị kiểm tra danh sách POP từ một đến năm lần hoặc cho đến khi tất cả các POP trong danh sách POP của bạn báo cáo có đối tượng. Đây là một tập hợp các khoảng thời gian để thực hiện kiểm tra mà bạn có thể tự do điều chỉnh: 1, 5, 60 phút, 12 giờ, 25 giờ sau khi đặt nó vào kho dữ liệu. Điều quan trọng là ghi nhật ký kết quả ở mỗi khoảng thời gian để xem xét và phân tích sau này để cảm nhận về khả năng sao chép toàn cầu của một dịch vụ nhất định. Thông thường các dịch vụ kho dữ liệu chỉ kéo một bản sao cục bộ sang POP một khi nó được yêu cầu cục bộ [việc định tuyến được thực hiện thông qua giao thức BGP, đó là lý do tại sao thử nghiệm của bạn phải yêu cầu đối tượng từ mỗi POP cụ thể để nó có hiệu lực toàn cầu cho một nền tảng nhất định] . Trong trường hợp Kho dữ liệu của Google, bạn sẽ xem xét việc thiết lập thử nghiệm của mình để truy vấn một đối tượng nhất định từ "hơn 70 điểm hiện diện trên 33 quốc gia"; bạn có thể phải lấy danh sách url địa chỉ cụ thể POP từ Bộ phận hỗ trợ của Google [ref:https://cloud.google.com/about/locations/ ] hoặc nếu Google đang sử dụng Nhanh chóng để nhân rộng, hãy hỗ trợ nhanh chóng [ https://www.fastly.com/resource ].

Một vài ưu điểm của phương pháp này: 1) Bạn sẽ cảm nhận được nền tảng nhân rộng của một dịch vụ nhất định, biết toàn bộ điểm yếu và điểm yếu của nó trên phạm vi toàn cầu [như trong quá trình thử nghiệm tích hợp]. 2) Đối với bất kỳ đối tượng nào bạn kiểm tra, bạn sẽ có một công cụ có sẵn để làm ấm nội dung [thực hiện yêu cầu đầu tiên tạo bản sao tại một POP cục bộ cụ thể] - do đó cung cấp cho bạn cách đảm bảo nội dung được lan truyền trên toàn cầu trước khi khách hàng của bạn yêu cầu bất cứ nơi nào trên trái đất.


0

Tôi có kinh nghiệm với Google App Engine Datastore. Chạy tại địa phương, đáng ngạc nhiên, nó thường là "cuối cùng" hơn là "nhất quán". Ví dụ đơn giản nhất: tạo một thực thể mới và sau đó lấy nó. Thường xuyên trong 5 năm qua, tôi đã thấy SDK chạy cục bộ không tìm thấy thực thể mới ngay lập tức, nhưng tìm thấy nó sau khoảng nửa giây.

Tuy nhiên, chạy với các máy chủ Google thực sự, tôi chưa thấy hành vi đó. Họ cố gắng làm cho máy khách Datastore của bạn luôn chạy trên cùng một máy chủ về phía họ, vì vậy thông thường mọi thay đổi sẽ được phản ánh ngay lập tức trong các truy vấn.

Lời khuyên của tôi cho các bài kiểm tra tích hợp là chạy chúng với các máy chủ thực, và sau đó có thể bạn sẽ không cần phải bỏ phiếu giả hoặc trì hoãn để nhận kết quả của mình.


Mặc dù điều đó thuận tiện, nhưng nó có thể gây ra sự phá vỡ tinh vi liên quan đến nhiều máy chủ ứng dụng mà không bị phát hiện trong các thử nghiệm tích hợp của bạn. Tôi đoán họ đã làm cho máy chủ cục bộ cuối cùng phù hợp vì một lý do tốt!
Robin Green
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.