Làm thế nào để TDD mà kết quả chính xác được trả về


12

Tôi đang bắt đầu một dự án mới và đang rất cố gắng sử dụng TDD để thúc đẩy thiết kế. Tôi đã nỗ lực trong nhiều năm và cuối cùng đã được chấp thuận dành thêm thời gian cho dự án này để sử dụng nó trong khi tôi học cách làm nó đúng cách.

Đây là một mô-đun mới, để gắn vào một hệ thống hiện có. Hiện tại, tất cả các truy cập dữ liệu xảy ra thông qua các dịch vụ web, phần lớn chỉ là một trình bao bọc mỏng cho các thủ tục lưu trữ cơ sở dữ liệu.

Một yêu cầu là đối với một cửa hàng nhất định, tôi trả lại tất cả các Đơn đặt hàng được coi là hợp lệ cho ứng dụng này. Một PO được coi là hợp lệ nếu ngày giao hàng rơi vào một phạm vi nhất định kể từ ngày mở cửa hàng (đây là cho các cửa hàng mới).

Bây giờ, tôi không thể đưa logic này vào mã ứng dụng, vì tôi sẽ không mang lại một triệu PO chỉ để có hàng tá áp dụng có thể áp dụng cho cửa hàng này với các ràng buộc ở trên.

Tôi đã suy nghĩ, tôi có thể chuyển phạm vi ngày cho một Proc GetValidPO và sử dụng các giá trị đó để trả về các PO hợp lệ. Nhưng, điều gì sẽ xảy ra nếu chúng ta thêm một yêu cầu khác vào thứ được coi là PO hợp lệ?

Và làm thế nào để tôi kiểm tra điều này và xác minh nó tiếp tục hoạt động? Chúng tôi không sử dụng ORM và điều đó khó có thể xảy ra. Và tôi không thể gọi DB trong bài kiểm tra của mình.

Tôi bị kẹt.

Suy nghĩ khác của tôi, có một số giả lập trả về dữ liệu hợp lệ, một số khác trả về một số dữ liệu xấu và kho lưu trữ cục bộ sẽ ném ngoại lệ nếu dữ liệu xấu xảy ra và kiểm tra xem ngoại lệ đó có bị ném nếu dữ liệu không hợp lệ được trả về bởi ProcValidPOs (hoặc giả được sử dụng trong thử nghiệm).

Điều này có nghĩa không? đây có phải là cách tốt hơn không?

CẬP NHẬT: Tôi có thể sử dụng EF có vẻ như. Bây giờ tôi chỉ cần tìm ra cách sử dụng nó, và làm cho nó có thể kiểm tra được, trong khi vẫn có thể dựa vào các thủ tục được lưu trữ và khó khăn trong việc có dữ liệu nằm rải rác trên một số cơ sở dữ liệu.


Vì tò mò, tại sao bạn không thể chọn chỉ các PO hợp lệ với câu lệnh SQL đơn giản? (Câu hỏi này hoặc câu trả lời không ngụ ý một giải pháp.)
Scarfridge

Câu trả lời:


7

Đây là một nhược điểm lớn của các thủ tục được lưu trữ trong thời đại TDD. Họ có một số mặt tích cực thực sự, ngay cả bây giờ, nhưng theo định nghĩa, bất kỳ bài kiểm tra nào thực hiện một Proc được lưu trữ không phải là một bài kiểm tra đơn vị; đó là một bài kiểm tra tích hợp tốt nhất.

Giải pháp thông thường, giả sử kiến ​​trúc không thể thay đổi để sử dụng ORM thay vào đó, là không đặt các thử nghiệm này trong bộ thử nghiệm đơn vị; thay vào đó, đặt các bài kiểm tra trong một bộ tích hợp. Bạn vẫn có thể chạy thử nghiệm bất cứ khi nào bạn muốn xác minh nó hoạt động, nhưng vì chi phí vốn có khi thiết lập thử nghiệm (khởi tạo DB với dữ liệu thử nghiệm phù hợp) rất cao và nó chạm vào tài nguyên mà tác nhân kiểm tra đơn vị của bot xây dựng của bạn có thể không có quyền truy cập, nó không nên có trong bộ thử nghiệm đơn vị.

Bạn vẫn có thể kiểm tra mã đơn vị yêu cầu dữ liệu, bằng cách trừu tượng hóa mọi thứ bạn không thể kiểm tra đơn vị (các lớp ADO.NET) thành một lớp DAO mà sau đó bạn có thể giả định. Sau đó, bạn có thể xác minh rằng các cuộc gọi dự kiến ​​được thực hiện bằng cách sử dụng mã và tái tạo hành vi trong thế giới thực (chẳng hạn như không tìm thấy kết quả) cho phép thử nghiệm các trường hợp sử dụng khác nhau. Tuy nhiên, việc thiết lập thực tế của SqlCommand để gọi Proc được lưu trữ gần như là điều cuối cùng bạn có thể kiểm tra đơn vị, bằng cách cắt đứt việc tạo lệnh từ thực thi lệnh và chế nhạo người thực thi lệnh. Nếu điều này nghe có vẻ như rất nhiều mối quan tâm, nó có thể được; hãy nhớ rằng, "không có vấn đề nào không thể giải quyết bằng một lớp gián tiếp khác, ngoại trừ việc có quá nhiều lớp không xác định". Tại một số điểm bạn phải nói "đủ rồi, tôi không thể kiểm tra đơn vị này, chúng tôi '

Sự lựa chọn khác:

  • Kiểm tra Proc được lưu trữ bằng cách sử dụng một cá thể DBMS "tồn tại ngắn" như SQLite. Việc thực hiện điều này thường dễ dàng hơn khi sử dụng ORM, nhưng sau đó thử nghiệm có thể được thực hiện "trong bộ nhớ" (hoặc với tệp cơ sở dữ liệu được cài đặt sẵn đi kèm với bộ kiểm tra). Vẫn không phải là thử nghiệm đơn vị, nhưng nó có thể được chạy với mức độ cô lập cao (DBMS là một phần của quy trình đang chạy và không phải là thứ bạn kết nối từ xa có thể ở giữa bộ thử nghiệm xung đột của người khác). Nhược điểm là các thay đổi đối với Proc được lưu trữ có thể xảy ra trong sản xuất mà không có thử nghiệm phản ánh sự thay đổi, do đó bạn phải bị kỷ luật về việc đảm bảo thay đổi được thực hiện trước tiên trong môi trường thử nghiệm.

  • Xem xét nâng cấp lên ORM. Một ORM với nhà cung cấp Linq (hầu như tất cả những người sử dụng chung đều có một) sẽ cho phép bạn xác định truy vấn dưới dạng câu lệnh Linq; câu lệnh đó sau đó có thể được trao cho Kho lưu trữ giả, có bộ sưu tập dữ liệu kiểm tra trong bộ nhớ để áp dụng. Do đó, bạn có thể xác minh truy vấn là chính xác mà không cần chạm vào DB (bạn vẫn nên chạy truy vấn trong môi trường tích hợp, để kiểm tra xem nhà cung cấp Linq có thể tiêu hóa chính xác truy vấn không).


2
-1 vì TDD! = Kiểm tra đơn vị. Hoàn toàn tốt để bao gồm các bài kiểm tra cấp độ tích hợp khi làm TDD.
Steven A. Lowe

Kiểm thử đơn vị là một tập hợp con của phát triển theo hướng kiểm tra. Trong một phát triển theo hướng thử nghiệm, bạn sẽ tạo ra một bộ xương đi bộ của hệ thống của mình và sau đó chạy đơn vị, tích hợp và kiểm tra chức năng trên hệ thống đó. Các bài kiểm tra tích hợp, đơn vị hoặc chấp nhận của bạn không thành công, sau đó bạn làm cho chúng vượt qua và viết các bài kiểm tra tiếp theo.
CodeART

1
Tôi hiểu tất cả những điều đó, cả hai bạn. Trường hợp tôi đã nói rằng nó phải là một bài kiểm tra tích hợp có nghĩa là bạn không thể TDD nó? Quan điểm của tôi là một thủ tục được lưu trữ không thể được kiểm tra một cách cô lập, đó là điều bạn muốn làm với càng nhiều codebase càng tốt. Thay vào đó, việc kiểm tra SP yêu cầu các thử nghiệm tích hợp dài hơn, phức tạp hơn; trong khi chúng vẫn tốt hơn so với thử nghiệm thủ công, một bộ thử nghiệm tích hợp nặng có thể mất hàng giờ để chạy và có thể có tác động bất lợi đến các nỗ lực của CI.
KeithS

Kiểm tra SP thường cũng yêu cầu một bộ dữ liệu cụ thể trong cơ sở dữ liệu kiểm tra; mã để có được cơ sở dữ liệu ở trạng thái thích hợp để đạt được kết quả mong đợi thường là LoC nhiều hơn và chạy lâu hơn nhiều lần so với mã bạn thực sự đang thực hiện. Điều này càng làm tăng thêm độ phức tạp thời gian của bộ kiểm tra và thường phải lặp lại thiết lập cho từng thử nghiệm riêng lẻ (và có lẽ nên có một vài cho mỗi SP, để kiểm tra rằng từng yêu cầu chức năng của truy vấn bên trong được đáp ứng).
KeithS

Thủ tục lưu trữ có thể được kiểm tra trong sự cô lập. Làm thế nào khác họ sẽ được xác nhận? Đối với SQL giao dịch, có tQueryt ( tsqlt.org )
kevin cline

4

Lời khuyên của tôi là chia rẽ và chinh phục . Hãy quên đi cơ sở dữ liệu và sự kiên trì trong thời gian này và tập trung vào việc kiểm tra các triển khai giả mạo của kho lưu trữ hoặc các đối tượng truy cập dữ liệu của bạn.

Bây giờ, tôi không thể đưa logic này vào mã ứng dụng, vì tôi sẽ không mang lại một triệu PO chỉ để có hàng tá áp dụng có thể áp dụng cho cửa hàng này với các ràng buộc ở trên.

Tôi sẽ chế nhạo kho lưu trữ trả về đơn đặt hàng. Tạo một giả với hai mươi đơn đặt hàng lẻ.

Tôi đã suy nghĩ, tôi có thể chuyển phạm vi ngày cho một Proc GetValidPO và sử dụng các giá trị đó để trả về các PO hợp lệ. Nhưng, điều gì sẽ xảy ra nếu chúng ta thêm một yêu cầu khác vào thứ được coi là PO hợp lệ?

Thực hiện một cuộc gọi đến GetValidPO để nó gọi giả của bạn, thay vì thủ tục cơ sở dữ liệu.

Và làm thế nào để tôi kiểm tra điều này và xác minh nó tiếp tục hoạt động? Chúng tôi không sử dụng ORM và điều đó khó có thể xảy ra. Và tôi không thể gọi DB trong bài kiểm tra của mình.

Bạn cần một bài kiểm tra đơn vị để đảm bảo dữ liệu chính xác được trả về từ một bản giả.

Bạn cũng cần một bài kiểm tra tích hợp để đảm bảo dữ liệu chính xác được trả về từ cơ sở dữ liệu. Kiểm tra tích hợp sẽ yêu cầu một số cấu hình và dọn dẹp. Ví dụ: trước khi chạy kiểm tra tích hợp, hãy khởi tạo cơ sở dữ liệu của bạn bằng cách chạy tập lệnh. Xác nhận rằng tập lệnh của bạn đã hoạt động. Truy vấn cơ sở dữ liệu bằng cách gọi các thủ tục lưu trữ của bạn. Xác nhận rằng kết quả của bạn là chính xác. Dọn dẹp cơ sở dữ liệu.

Suy nghĩ khác của tôi, có một số giả lập trả về dữ liệu hợp lệ, một số khác trả về một số dữ liệu xấu và kho lưu trữ cục bộ sẽ ném ngoại lệ nếu dữ liệu xấu xảy ra và kiểm tra xem ngoại lệ đó có bị ném nếu dữ liệu không hợp lệ được trả về bởi ProcValidPOs (hoặc giả được sử dụng trong thử nghiệm).

Như tôi đã nói, bạn cần một bản giả trả về ít nhất một số dữ liệu mà bạn có thể truy vấn.

Khi bạn truy vấn dữ liệu bạn muốn đảm bảo rằng hệ thống của bạn có thể xử lý các ngoại lệ một cách duyên dáng. Do đó, bạn chế giễu hành vi để nó ném ngoại lệ trong các tình huống nhất định. Sau đó, bạn viết các bài kiểm tra để đảm bảo rằng hệ thống của bạn có thể xử lý các ngoại lệ này một cách duyên dáng.


Đó là những gì tôi đang cố gắng làm. Chỉ gặp khó khăn khi viết một triển khai thực sự sẽ hoạt động giống như giả, vì quyền truy cập dữ liệu của chúng tôi không có lợi cho việc sử dụng ORM. Phần lớn dữ liệu tôi cần là trong một số hệ thống và được truy cập thông qua các dịch vụ web ... ngay cả khi cập nhật.
CaffGeek

0

Giống như kiểm tra đơn vị Java hoặc Javascript có nghĩa là viết các kiểm tra đơn vị bằng cách sử dụng ngôn ngữ Java cho java và kiểm tra đơn vị các chức năng Javascript bằng Javascript, viết các kiểm tra tự động để thúc đẩy bạn viết các thủ tục được lưu trữ có nghĩa là thư viện kiểm tra đơn vị bạn đang tìm kiếm được dựa trên lưu trữ thủ tục.

Nói cách khác, sử dụng các thủ tục được lưu trữ để kiểm tra các thủ tục được lưu trữ bởi vì:

  • vì bạn đang phát triển ngôn ngữ thủ tục, bạn nên có kỹ năng viết bài kiểm tra của mình bằng ngôn ngữ thủ tục
  • viết bài kiểm tra bằng ngôn ngữ thủ tục của bạn sẽ tăng kỹ năng của bạn bằng ngôn ngữ thủ tục, điều này sẽ giúp phát triển sản phẩm của bạn
  • bạn sẽ có quyền truy cập trực tiếp vào tất cả các công cụ mà DB của bạn cung cấp và bạn cũng có thể sử dụng các công cụ đó để giữ cho các bài kiểm tra đơn vị của bạn đơn giản nhất có thể
  • kiểm tra đơn vị được lưu trữ trong cùng DB với các quy trình mà họ đang kiểm tra sẽ nhanh chóng (điều gần nhất với kiểm tra đơn vị như tốc độ) vì bạn không vượt qua ranh giới hệ thống

Giống như TDD trong một ngôn ngữ OO, bạn muốn thử nghiệm đơn vị của mình chỉ thiết lập một hàng hoặc nhiều dữ liệu để kiểm tra những gì nó cần cho thủ tục (tối giản, chỉ có những gì các thử nghiệm đơn giản của bạn cần). Kết quả của việc này là bạn sẽ có một vài bài kiểm tra đơn vị đơn giản cho mỗi thủ tục được lưu trữ. Các thử nghiệm đơn giản này sẽ dễ bảo trì hơn so với các thử nghiệm phức tạp phụ thuộc vào bộ dữ liệu lớn không dễ dàng ánh xạ lại những gì thử nghiệm thực sự cầ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.