Làm cách nào để áp dụng TDD cho các chức năng đọc / ghi?


10

Có vẻ như một vấn đề gà và trứng.

Bạn có thể thực hiện chức năng ghi ghi vào một số lưu trữ dữ liệu, nhưng không bao giờ biết bạn đã lưu nó đúng cách mà không có chức năng đọc được kiểm tra.

Bạn có thể thực hiện chức năng đọc từ kho lưu trữ dữ liệu, nhưng làm thế nào để bạn đặt nội dung vào kho lưu trữ dữ liệu đó, để đọc mà không có chức năng ghi đã kiểm tra?

BIÊN TẬP:

Tôi đang kết nối và thực hiện các giao dịch với cơ sở dữ liệu SQL để lưu và tải các đối tượng để sử dụng. Không có điểm nào kiểm tra các chức năng truy cập mà DB cung cấp, nhưng tôi bọc các hàm DB đó để tuần tự hóa / giải tuần tự hóa các đối tượng. Tôi muốn chắc chắn rằng tôi đang viết và đọc đúng nội dung đến và từ DB.

Nó không giống như thêm / xóa, như @snowman đề cập. Tôi muốn biết rằng nội dung tôi đã viết là chính xác, nhưng điều đó đòi hỏi phải có chức năng đọc được kiểm tra tốt. Khi tôi đọc, tôi muốn chắc chắn rằng việc đọc của tôi đã tạo chính xác một đối tượng bằng với những gì đã được viết; nhưng điều đó đòi hỏi một chức năng ghi được kiểm tra tốt.


Bạn đang viết lưu trữ dữ liệu của riêng bạn, hoặc sử dụng một kho lưu trữ hiện có? Nếu bạn đang sử dụng một cái hiện có, giả sử rằng nó đã hoạt động. Nếu bạn đang tự viết, điều này hoạt động tương tự như viết bất kỳ phần mềm nào khác bằng TDD.
Robert Harvey


1
Mặc dù liên quan chặt chẽ, tôi không nghĩ rằng đây là một bản sao của câu hỏi cụ thể đó. Mục tiêu dupe đang nói về add / xóa, cái này là đọc / ghi. Sự khác biệt là sự phụ thuộc đọc / ghi có thể phụ thuộc vào nội dung của các đối tượng được đọc / ghi, trong khi thử nghiệm thêm / xóa đơn giản có thể sẽ đơn giản hơn nhiều: đối tượng có tồn tại hay không.

2
Bạn có thể tạo cơ sở dữ liệu với dữ liệu và hoàn toàn không có chức năng ghi để kiểm tra chức năng đọc.
JeffO

Câu trả lời:


7

Bắt đầu với chức năng Đọc.

  • Trong thiết lập thử nghiệm : tạo cơ sở dữ liệu và thêm dữ liệu thử nghiệm. hoặc thông qua các tập lệnh di chuyển hoặc từ một bản sao lưu. Vì đây không phải là mã của bạn, nên nó không yêu cầu kiểm tra trong TDD

  • Trong thử nghiệm : kích hoạt kho lưu trữ của bạn, chỉ vào db thử nghiệm của bạn và gọi phương thức Đọc. Kiểm tra xem dữ liệu kiểm tra được trả về.

Bây giờ bạn đã có chức năng đọc được kiểm tra đầy đủ, bạn có thể chuyển sang chức năng Ghi, có thể sử dụng chức năng Đọc hiện có để xác minh kết quả của chính nó


Tôi đoán bạn có thể tạo một DB trong bộ nhớ để tăng tốc mọi thứ, nhưng điều đó có thể quá phức tạp. Tại sao không sử dụng giả thay vì trong các bài kiểm tra đơn vị?
BЈовић

1
Một chút của Advocate của Devil ở đây, nhưng làm thế nào để bạn kiểm tra rằng cơ sở dữ liệu đã được tạo chính xác? Như OP đã nêu, gà và trứng.
dùng949300

1
@Ewan - Tôi hoàn toàn đồng ý rằng bạn không nên kiểm tra mã DB của họ. Nhưng làm thế nào để bạn biết rằng mã thiết lập DB của bạn đã không quên INSERT ở đâu đó hoặc đặt một giá trị sai trong một cột?
dùng949300

1
từ một cách tiếp cận TDD thuần túy, bài kiểm tra IS là yêu cầu. Vì vậy, nó không thể sai. obvs trong thế giới thực bạn phải cầu mắt
Ewan

1
Quis custodiet ipsos custode? Hoặc, "Ai kiểm tra các bài kiểm tra?" :-) Tôi đồng ý với bạn rằng trong một thế giới TDD thuần túy, đây sẽ là cách tẻ nhạt và dễ bị lỗi khủng khiếp (đặc biệt nếu đó là một cấu trúc nhiều bảng phức tạp với 8 THAM GIA) để thực hiện. Nâng cao.
dùng949300

6

Tôi thường chỉ viết một bài tiếp theo là đọc. ví dụ (mã giả)

Foo foo1 = setup some object to write
File tempfile = create a tempfile, possibly in memory 
writeFoo(foo1, tempfile) 
Foo foo2 = readFoo(tempfile) 
assertEquals(foo1, foo2); 
clean-up goes here

Đã thêm sau

Ngoài giải pháp này là "prgamatic" và "đủ tốt", người ta có thể lập luận rằng các giải pháp khác kiểm tra điều sai . Kiểm tra xem các chuỗi hoặc các câu lệnh SQL có khớp không phải là một ý tưởng tồi tệ hay không, tôi đã tự mình thực hiện nó, nhưng nó đang thử nghiệm một tác dụng phụ và rất mong manh. Điều gì xảy ra nếu bạn thay đổi viết hoa, thêm trường hoặc cập nhật số phiên bản trong dữ liệu của mình? Điều gì xảy ra nếu trình điều khiển SQL của bạn chuyển đổi thứ tự các cuộc gọi để đạt hiệu quả hoặc trình tuần tự XML được cập nhật của bạn thêm một không gian bổ sung hoặc thay đổi phiên bản lược đồ?

Bây giờ, nếu bạn phải tuân thủ rất nghiêm ngặt một số thông số chính thức, thì tôi đồng ý rằng kiểm tra các chi tiết tốt là phù hợp.


1
Bởi vì nó là 90% mã giả thực sự dày đặc? Không chắc. Có thể làm nổi bật văn bản và làm cho mã ít ồn ào?
RubberDuck

1
Vâng @Ewan. Người nhiệt tâm sẽ cau mày vì điều này, tuy nhiên lập trình viên thực dụng sẽ nói "đủ tốt" và tiếp tục.
RubberDuck

1
Tôi có thể đọc câu hỏi như .. "giả sử tôi theo TDD như một người nhiệt tâm ..."
Ewan

1
giải thích của tôi về OP và TDD là bài kiểm tra của bạn nên được viết trước và không sử dụng cả đọc và viết trừ khi bài kiểm tra đó cũng được kiểm tra ở nơi khác.
Ewan

2
bạn đang kiểm tra, 'đọc sẽ trả về những gì tôi viết' nhưng các yêu cầu là 'đọc sẽ trả về dữ liệu từ db' và 'ghi nên ghi dữ liệu vào db'
Ewan

4

Đừng. Không kiểm tra đơn vị I / O. Nó là một sự lãng phí thời gian.

Logic kiểm tra đơn vị. Nếu có rất nhiều logic mà bạn muốn kiểm tra trong mã I / O, bạn nên cấu trúc lại mã của mình để tách logic của cách bạn thực hiện I / O và những gì tôi / O thực hiện với công việc thực hiện I / O thực tế (không thể kiểm tra được).

Để giải thích một chút, nếu bạn muốn kiểm tra máy chủ HTTP, bạn nên thực hiện thông qua hai loại kiểm tra: kiểm tra tích hợp và kiểm tra đơn vị. Các bài kiểm tra đơn vị không nên tương tác với I / O. Điều đó chậm và đưa ra nhiều điều kiện lỗi không liên quan đến tính chính xác của mã của bạn. Các bài kiểm tra đơn vị không nên tuân theo trạng thái của mạng của bạn!

Mã của bạn nên tách biệt:

  • Logic xác định thông tin cần gửi
  • Logic xác định byte nào sẽ gửi để gửi một bit thông tin cụ thể (làm cách nào để mã hóa phản hồi, v.v. thành byte thô) và
  • Cơ chế thực sự ghi các byte đó vào một socket.

Hai cái đầu liên quan đến logic và quyết định và cần kiểm tra đơn vị. Việc cuối cùng không liên quan đến việc đưa ra nhiều quyết định nếu có bất kỳ quyết định nào và có thể được kiểm tra tuyệt vời bằng cách sử dụng thử nghiệm tích hợp.

Đây chỉ là thiết kế tốt nói chung, nhưng một trong những lý do cho điều đó là nó làm cho nó dễ dàng hơn để kiểm tra.


Dưới đây là một số ví dụ:

  • Nếu bạn đang viết mã nhận dữ liệu từ cơ sở dữ liệu quan hệ, bạn có thể kiểm tra đơn vị cách bạn ánh xạ dữ liệu được trả về từ các truy vấn quan hệ đến mô hình ứng dụng của bạn.
  • Nếu bạn đang viết mã ghi dữ liệu vào cơ sở dữ liệu quan hệ, bạn có thể kiểm tra đơn vị phần dữ liệu nào bạn muốn ghi vào cơ sở dữ liệu mà không thực sự kiểm tra các truy vấn SQL cụ thể mà bạn sử dụng. Ví dụ: bạn có thể giữ hai bản sao trạng thái ứng dụng của mình trong bộ nhớ: một bản sao thể hiện cơ sở dữ liệu trông như thế nào và bản sao hoạt động. Khi bạn muốn đồng bộ hóa với cơ sở dữ liệu, bạn cần phải tìm khác biệt và ghi sự khác biệt vào cơ sở dữ liệu. Bạn có thể dễ dàng kiểm tra đơn vị mã đó.
  • Nếu bạn đang viết mã đọc một cái gì đó từ tệp cấu hình, bạn muốn kiểm tra trình phân tích định dạng tệp cấu hình của mình, nhưng với các chuỗi từ tệp nguồn thử nghiệm của bạn thay vì các chuỗi bạn nhận được từ đĩa.

2

Tôi không biết đây có phải là một tiêu chuẩn thực hành hay không nhưng nó hoạt động tốt với tôi.

Trong cơ sở dữ liệu không đọc cơ sở dữ liệu của tôi, tôi sử dụng các phương thức toString()và kiểu cụ thể của riêng tôi fromString()làm chi tiết triển khai.

Đây có thể dễ dàng được kiểm tra trong sự cô lập:

 assertEquals("<xml><car type='porsche'>....", new Car("porsche").toString());

Đối với các phương pháp đọc thực tế, tôi có một bài kiểm tra tích hợp đọc và viết một cách vật lý trong một bài kiểm tra

Nhân tiện: Có điều gì sai khi có một bài kiểm tra kiểm tra đọc / ghi cùng nhau?


Nó có thể không cảm thấy tốt hoặc "tinh khiết", nhưng đây là giải pháp thực dụng.
RubberDuck

Tôi cũng thích ý tưởng kiểm tra đọc và viết cùng nhau. ToString () của bạn là một sự thỏa hiệp thực dụng tốt đẹp.
dùng949300

1

Dữ liệu đã biết phải được định dạng theo cách đã biết. Cách dễ nhất để thực hiện điều này là sử dụng một chuỗi không đổi và so sánh kết quả, như @ k3b mô tả.

Bạn không giới hạn các hằng số mặc dù. Có thể có một số thuộc tính của dữ liệu bằng văn bản mà bạn có thể trích xuất bằng cách sử dụng một loại trình phân tích cú pháp khác, chẳng hạn như biểu thức thông thường hoặc thậm chí các đầu dò ad hoc đang tìm kiếm các tính năng của dữ liệu.

Đối với việc đọc hoặc ghi dữ liệu, có thể hữu ích khi có một hệ thống tệp trong bộ nhớ cho phép bạn chạy các bài kiểm tra của mình mà không có khả năng bị nhiễu từ các phần khác của hệ thống. Nếu bạn không có quyền truy cập vào hệ thống tệp trong bộ nhớ tốt, thì hãy sử dụng cây thư mục tạm thời.


1

Sử dụng tiêm phụ thuộc và chế nhạo.

Bạn không muốn kiểm tra trình điều khiển SQL của mình và bạn không muốn kiểm tra xem cơ sở dữ liệu SQL của bạn có trực tuyến và được thiết lập đúng không. Đó sẽ là một phần của kiểm tra tích hợp hoặc hệ thống. Bạn muốn kiểm tra xem mã của bạn có gửi các câu lệnh SQL mà nó được gửi không và nếu nó diễn giải các phản hồi theo cách nó được yêu cầu.

Vì vậy, khi bạn có một phương thức / lớp được cho là làm một cái gì đó với cơ sở dữ liệu, đừng để nó có kết nối cơ sở dữ liệu đó. Thay đổi nó để đối tượng đại diện cho kết nối cơ sở dữ liệu được truyền cho nó.

Trong mã sản xuất của bạn, vượt qua đối tượng cơ sở dữ liệu thực tế.

Trong các bài kiểm tra đơn vị của bạn, vượt qua một đối tượng giả giống như cơ sở dữ liệu thực tế không thực sự liên hệ với máy chủ cơ sở dữ liệu. Chỉ cần kiểm tra xem nó có nhận được các câu lệnh SQL không, nó sẽ nhận được và sau đó trả lời bằng các phản hồi được mã hóa cứng.

Bằng cách này, bạn có thể kiểm tra lớp trừu tượng cơ sở dữ liệu của mình mà không cần đến cơ sở dữ liệu thực tế.


Devil's Advocate: Làm thế nào để bạn biết câu lệnh SQL nào "đáng lẽ phải nhận"? Điều gì xảy ra nếu trình điều khiển DB tối ưu hóa thứ tự từ những gì xuất hiện trong mã?
dùng949300

@ user949300 Một đối tượng giả cơ sở dữ liệu thường thay thế trình điều khiển cơ sở dữ liệu.
Philipp

khi bạn đang kiểm tra một kho lưu trữ thì không có điểm nào khiến khách hàng cơ sở dữ liệu bị chế giễu. Bạn phải kiểm tra xem mã của bạn có chạy sql hoạt động trên cơ sở dữ liệu không. nếu không, bạn sẽ kết thúc việc kiểm tra bản giả của mình
Ewan

@Ewan Đó không phải là những gì đơn vị thử nghiệm là về. Một bài kiểm tra đơn vị kiểm tra một đơn vị mã, được phân lập từ phần còn lại của thế giới. Bạn không kiểm tra các tương tác giữa các thành phần, như mã của bạn và cơ sở dữ liệu. Đó là những gì kiểm thử tích hợp dành cho.
Philipp

Đúng. Tôi nói không có đơn vị điểm nào kiểm tra kho lưu trữ db. kiểm tra tích hợp là điều duy nhất đáng làm
Ewan

0

Nếu bạn đang sử dụng một trình ánh xạ quan hệ đối tượng, thường có một thư viện liên kết có thể được sử dụng để kiểm tra rằng ánh xạ của bạn hoạt động chính xác bằng cách tạo tổng hợp, duy trì và tải lại từ phiên mới, sau đó là xác minh trạng thái chống lại đối tượng ban đầu.

NHibernate cung cấp Kiểm tra Thông số kỹ thuật bền bỉ . Nó có thể được cấu hình để hoạt động đối với một cửa hàng trong bộ nhớ để kiểm tra đơn vị nhanh.

Nếu bạn làm theo phiên bản đơn giản nhất của các mẫu Kho lưu trữ và Đơn vị công việc và kiểm tra tất cả các ánh xạ của bạn, bạn có thể tin tưởng vào những thứ hoạt động khá nhiều.

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.