Có phải là một ý tưởng tốt để có các phương pháp thử nghiệm riêng biệt cho mỗi bước?


10

Tôi đang thử nghiệm một api REST. Hãy nói rằng nó trả về một cấu trúc JSON. Cách tiếp cận tốt nhất để kiểm tra máy chủ là gì? Mỗi bước kiểm tra chỉ có thể thành công nếu tất cả các lần trước đều thành công.

Cấu trúc A: kiểm tra mọi thứ cùng một lúc

- Test method 1:
    - make server request
    - assert http response code was 200
    - assert returned file is not empty
    - assert returned file has valid JSON syntax
    - assert returned JSON contains key X

Đây dường như là giải pháp tốt nhất.

Ưu điểm:

  • Chỉ một yêu cầu máy chủ
  • Tôi đang kiểm tra toàn bộ hành vi "Máy chủ có trả lại JSON bằng khóa X không?"

Cấu trúc B: dần dần thêm các xác nhận vào mỗi thử nghiệm

 - Test method 1:
     - make server request
     - assert http response code was 200
 - Test method 2:
     - make server request
     - assert returned file is not empty
 - Test method 3:
     - make server request
     - assert returned file has valid JSON syntax
 - Test method 4:
     - make server request
     - assert returned JSON contains key X

Đây là cách tôi bắt đầu thực hiện nó và tôi đã bị thuyết phục rằng đây sẽ là cách để đi bởi vì mọi phương pháp chỉ kiểm tra một điều duy nhất và điều này tạo ra sự tách biệt tốt hơn. Nhưng bây giờ tôi nghĩ rằng, vì đây không phải là các bài kiểm tra đơn vị nên sự tách biệt của tôi là không phù hợp và tôi nên kiểm tra toàn bộ hành vi.

Cấu trúc C: thực hiện yêu cầu một lần và chạy các phương thức thử nghiệm riêng biệt trên phản hồi được lưu trữ

- make server request and cache it (allow read-only access)

 - Test method 1:
     - assert http response code was 200 on cached server request
 - Test method 2:
     - assert returned file is not empty on cached server request
 - Test method 3:
     - assert returned file has valid JSON syntax on cached server request
 - Test method 4:
     - assert returned JSON contains key X on cached server request

Ưu điểm:

  • Không yêu cầu máy chủ lặp lại (đắt tiền)
  • Vẫn có các phương pháp kiểm tra khẳng định đơn

Đó là cấu trúc thử nghiệm hợp lý nhất để sử dụng?


Vui lòng ngừng thay đổi câu hỏi của bạn sau đó theo cách vô hiệu hóa các câu trả lời hiện có! Cảm ơn.
Doc Brown

Xin lỗi vì đã gây ra sự bất tiện cho bạn nhưng bạn có đề xuất làm khác không?
mrplow

Đầu tiên, hãy suy nghĩ kỹ nếu bạn thực sự cần thay đổi câu hỏi của mình theo cách như vậy. Nếu bạn thực sự nghĩ rằng bạn phải thêm một cái gì đó làm mất hiệu lực một số câu trả lời, bạn có thể thông báo cho tất cả các tác giả về những câu trả lời đó bằng cách để lại một bình luận bên dưới câu trả lời của họ hỏi họ có muốn thay đổi hoặc thêm một cái gì đó trong văn bản của họ không.
Doc Brown

2
Tôi thực sự cho rằng các tác giả của câu trả lời được thông báo nếu câu hỏi được thay đổi. Đây là lý do tại sao tôi không muốn spam bình luận với các tuyên bố chủ đề. Tôi sẽ thông báo cho các tác giả trong tương lai. Và cảm ơn bạn đã cung cấp một câu trả lời cho câu hỏi của tôi.
mrplow

Câu trả lời:


3

Thực hành tốt nhất luôn có một mục đích, một lý do đằng sau chúng. Luôn luôn là một ý tưởng tốt để xem xét những lý do này trong thiết kế của bạn - đặc biệt là khi bạn đang cố gắng quyết định cách thức và mức độ khó để làm theo các thực tiễn tốt nhất này.

Trong trường hợp này, lý do chính đằng sau việc thực hiện mọi bài kiểm tra là một điều duy nhất là nếu điều thứ nhất thất bại, thì điều thứ hai sẽ không được kiểm tra. Vì có quá nhiều người đưa ra ý kiến ​​dường như tìm thấy công đức trong việc phá vỡ mọi thứ thành các bit nhỏ nhất có thể và gói mọi bit vào càng nhiều càng tốt, điều này đã sinh ra ý tưởng rằng mọi bài kiểm tra nên chứa một khẳng định duy nhất.

Đừng làm theo điều này một cách mù quáng. Ngay cả khi mọi bài kiểm tra nên kiểm tra một điều, bạn vẫn nên suy nghĩ quyết định xem mỗi "điều" đó lớn hay nhỏ như thế nào, và để làm như vậy, bạn phải ghi nhớ lý do tại sao bạn muốn mọi bài kiểm tra kiểm tra một điều - để đảm bảo một lỗi trong điều đầu tiên là không để điều thứ hai chưa được kiểm tra.

Vì vậy, bạn cần phải tự hỏi - "tôi có thực sự cần sự đảm bảo này ở đây không?"

Giả sử có một lỗi trong trường hợp thử nghiệm đầu tiên - mã phản hồi HTTP thì không 200. Vì vậy, bạn bắt đầu hack mã, tìm hiểu lý do tại sao bạn không nhận được mã phản hồi bạn nên có và khắc phục sự cố. Còn bây giờ thì sao?

  • Nếu bạn tự chạy lại bài kiểm tra, để xác minh rằng bản sửa lỗi của bạn đã giải quyết được vấn đề, bạn nên gặp phải bất kỳ vấn đề nào khác được ẩn bởi lỗi đầu tiên.
  • Nếu bạn không chạy thủ công (có thể vì mất quá nhiều thời gian?) Và chỉ cần sửa lỗi chờ máy chủ kiểm tra tự động chạy mọi thứ, thì bạn có thể muốn đưa các xác nhận khác nhau vào các thử nghiệm khác nhau. Các chu kỳ trong trường hợp này rất dài, do đó, đáng để nỗ lực khám phá càng nhiều lỗi trong mỗi chu kỳ.

Có một vài điều nữa để xem xét:

Khẳng định phụ thuộc

Tôi biết các bài kiểm tra bạn mô tả chỉ là một ví dụ và các bài kiểm tra thực tế của bạn có thể phức tạp hơn - vì vậy những gì tôi sẽ nói có thể không hợp lệ với nhiều sức mạnh trong các bài kiểm tra thực tế, nhưng nó vẫn có thể hiệu quả phần nào vì vậy bạn có thể muốn xem xét nó.

Nếu bạn có một dịch vụ REST (hoặc bất kỳ giao thức HTTP nào khác) trả về các phản hồi ở định dạng JSON, bạn thường viết một lớp máy khách đơn giản cho phép bạn sử dụng các phương thức REST như các phương thức thông thường trả về các đối tượng thông thường. Giả sử rằng khách hàng có các thử nghiệm riêng biệt để đảm bảo nó hoạt động, tôi sẽ bỏ 3 xác nhận đầu tiên và chỉ giữ lại 4!

Tại sao?

  • Khẳng định đầu tiên là dự phòng - lớp máy khách sẽ đưa ra một ngoại lệ nếu mã phản hồi HTTP không phải là 200.
  • Khẳng định thứ hai là không cần thiết - nếu phản hồi trống, đối tượng kết quả sẽ là null hoặc một số đại diện khác của một đối tượng trống và bạn sẽ không có nơi nào để đặt khóa X.
  • Khẳng định thứ ba là không cần thiết - nếu JSON không hợp lệ, bạn sẽ gặp ngoại lệ khi bạn cố phân tích cú pháp.

Vì vậy, bạn không cần phải chạy tất cả các thử nghiệm này - chỉ cần chạy thử nghiệm thứ tư và nếu có bất kỳ lỗi nào trong ba lần thử đầu tiên phát hiện thì thử nghiệm sẽ thất bại với một ngoại lệ thích hợp trước khi bạn nhận được xác nhận thực tế.

Bạn muốn nhận báo cáo như thế nào?

Giả sử bạn không nhận được email từ máy chủ thử nghiệm, nhưng thay vào đó, bộ phận QA sẽ chạy thử nghiệm và thông báo cho bạn về các thử nghiệm thất bại.

Jack từ QA gõ cửa nhà bạn. Ông nói rằng phương thức thử nghiệm đầu tiên đã thất bại và phương thức REST trả về mã phản hồi xấu. Bạn cảm ơn anh ấy, và bắt đầu tìm kiếm nguyên nhân gốc rễ.

Sau đó, Jen đến từ QA và nói rằng phương thức thử nghiệm thứ ba đã thất bại - phương thức REST không trả về JSON hợp lệ trong phần thân phản hồi. Bạn nói với cô ấy rằng bạn đã xem phương thức đó và bạn tin rằng điều tương tự khiến nó trả về mã thoát xấu cũng khiến nó trả về một thứ không phải là JSON hợp lệ và trông giống như dấu vết ngăn xếp ngoại lệ.

Bạn quay lại làm việc, nhưng sau đó Jim từ QA đến, nói rằng phương pháp thử nghiệm thứ tư đã thất bại và không có phím X trong phản hồi ...

Bạn thậm chí không thể tìm lý do vì thật khó để xem mã khi bạn không có màn hình máy tính. Nếu Jim đủ nhanh, anh có thể tránh kịp ...

Email từ máy chủ thử nghiệm dễ dàng bị loại bỏ hơn, nhưng vẫn vậy - bạn có muốn thông báo cho ONCE rằng có gì đó không đúng với phương pháp kiểm tra và tự mình xem nhật ký kiểm tra có liên quan không?


3

Nếu bạn có thể giả định một cách an toàn rằng việc thực hiện một yêu cầu máy chủ có cùng tham số sẽ hoạt động giống nhau, thì phương thức B gần như vô nghĩa - tại sao bạn phải gọi bốn lần cùng một phương thức để có cùng một dữ liệu phản hồi bốn lần khi một cuộc gọi là đủ?

Và nếu bạn không thể giả định điều này một cách an toàn và muốn biến nó thành một phần của bài kiểm tra, bạn có thể tốt hơn để chạy thử nghiệm A nhiều lần.

Tình huống giả định duy nhất tôi thấy ở đâu B có thể có lợi ích là khi khung kiểm tra của bạn chỉ cho phép bật và tắt các phương pháp kiểm tra rõ ràng và bạn mong muốn phải thực hiện điều này cho từng bước kiểm tra của mình.

Giải pháp thay thế C dường như kết hợp A với một lợi ích mà tôi đã đề cập ở trên cho B. Nếu khung thử nghiệm của bạn cho phép mã của bạn được cấu trúc dễ dàng như thế, mà không cần nhiều chi phí trên B, đây là một cách tiếp cận khả thi. Tuy nhiên, điều này làm tăng thêm độ phức tạp cho A, vì vậy tôi sẽ chỉ sử dụng nó nếu tôi muốn bật và tắt các thử nghiệm riêng lẻ, nếu không thì áp dụng nguyên tắc YAGNI và tuân theo giải pháp đơn giản nhất (A).

TLDR: bắt đầu bằng A nếu bạn chắc chắn rằng bạn luôn muốn tất cả các xác nhận được chạy trong một thử nghiệm, tái cấu trúc thành C nếu bạn nhận thấy bạn cần kiểm soát dễ dàng hơn từ bên ngoài về các xác nhận riêng lẻ.


0

Giống như bất kỳ mã nào, tránh tối ưu hóa sớm. Đầu tiên viết bài kiểm tra của bạn để chúng đơn giản để đọc và đơn giản để duy trì. Khi các bài kiểm tra bắt đầu trở nên quá chậm thì hãy tối ưu hóa chúng. Trong ví dụ khá đơn giản của bạn, cả A và B đều dễ đọc và duy trì, vì vậy hãy chọn bất cứ thứ gì bạn muốn cho đến khi mọi thứ trở nên quá chậm (cấu trúc B) hoặc quá phức tạp (cấu trúc A).

Nếu máy chủ của bạn không trạng thái thì bạn có thể tối ưu hóa bằng cách so sánh phản hồi thực tế với phản hồi dự kiến ​​để kiểm tra toàn bộ tin nhắn trong một lần. Rõ ràng đó sẽ là chi phí của khả năng đọc.

Nếu máy chủ của bạn hoạt động tốt và bạn cần thực hiện nhiều cuộc gọi api chậm để đưa máy chủ về trạng thái kiểm tra thì bạn phải thực hiện một cách tiếp cận khác hoặc các thử nghiệm của bạn có thể mất vài phút để chạy. Ví dụ: bạn có thể chạy cập nhật cơ sở dữ liệu để đưa dữ liệu vào cơ sở dữ liệu kiểm tra để bạn có thể nhanh chóng nhận được một đối tượng ở trạng thái thích hợp để kiểm tra. Bài kiểm tra nhanh và dễ đọc nhưng khó bảo trì hơn. Ngoài ra, bạn có thể viết một mặt tiền phía trước api để nhiều cuộc gọi api trở thành một cuộc gọi api duy nhất phù hợp hơn với quy trình kinh doanh mà bạn đang thử nghiệm.


0

Các bài kiểm tra không nên chia sẻ mọi thứ - bắt đầu từ đầu bạn tránh ảnh hưởng của bài kiểm tra này đến bài kiểm tra khác. Điều này cũng làm cho bạn có thể chạy thử nghiệm theo thứ tự ngẫu nhiên.
Vì vậy, cách C không nên được chấp nhận.


Khi viết bất kỳ mã nào (hoặc thậm chí có thể tạo ra bất cứ điều gì khác), hãy luôn tự hỏi: "tại sao lại có thực hành như vậy?"
Tại sao chúng ta nói rằng nên có các thử nghiệm khác nhau cho tất cả mọi thứ?

Có hai trường hợp khi bạn cần điều này:

  1. khi bạn không thể dựa vào "mỗi bước kiểm tra chỉ có thể thành công nếu tất cả các bước trước đều thành công"
  2. khi bài kiểm tra của bạn không có thông điệp khẳng định mô tả

Có hai lý do tại sao bạn phải đối mặt với những trường hợp này:

  1. "mỗi bước kiểm tra chỉ có thể thành công nếu tất cả các lần trước đều thành công" thực sự không thể áp dụng cho tính năng sản phẩm của bạn
  2. bạn không có đủ kiến ​​thức về sản phẩm vì thiếu kinh nghiệm hoặc thời gian hoặc độ phức tạp của sản phẩm quá cao

Nếu bạn vì một lý do nào đó, bạn không thể tuyên bố ít nhất một trong những lý do này chỉ cần lấy cấu trúc B một cách mù quáng .


Nếu không (Tôi hy vọng bạn sẽ có được ở đây), bạn chọn một .


Ngoài ra, bạn có thể đặt câu hỏi này trên trang web Stackexchange Kiểm tra và Đảm bảo Chất lượng Phần mề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.