TDD với mẫu kho lưu trữ


10

Trong dự án mới của tôi, tôi quyết định thử với TDD. Và ngay từ đầu tôi đã gặp phải một vấn đề. Điều đầu tiên tôi muốn làm trong ứng dụng của mình là cung cấp khả năng đọc dữ liệu từ nguồn dữ liệu. Đối với mục đích này, tôi muốn sử dụng mô hình kho lưu trữ. Và bây giờ:

  • Nếu kiểm tra là để thực hiện giao diện kho lưu trữ thực sự, tôi sẽ kiểm tra lớp có quyền truy cập vào cơ sở dữ liệu và tôi biết rằng tôi nên tránh điều đó.
  • Nếu kiểm tra không thực hiện đúng mẫu kho lưu trữ, tôi sẽ kiểm tra tốt ... chỉ là giả. Sẽ không có bất kỳ đoạn mã sản xuất nào được thử nghiệm trong các thử nghiệm đơn vị đó.

Tôi đang suy nghĩ về điều này từ hai ngày và vẫn không thể đưa ra bất kỳ giải pháp hợp lý nào. Tôi nên làm gì?

Câu trả lời:


11

Những gì một kho lưu trữ làm là dịch từ miền của bạn sang khung DAL của bạn, chẳng hạn như NHibernate hoặc Doctrine hoặc các lớp thực thi SQL của bạn. Điều này có nghĩa là kho lưu trữ của bạn sẽ gọi các phương thức trên khung đã nói để thực hiện các nhiệm vụ của nó: kho lưu trữ của bạn xây dựng các truy vấn cần thiết để tìm nạp dữ liệu. Nếu bạn không sử dụng khung ORM (tôi hy vọng bạn là ...), kho lưu trữ sẽ là nơi xây dựng các câu lệnh SQL thô.

Cơ bản nhất của các phương thức này là lưu: trong hầu hết các trường hợp, điều này chỉ đơn giản là chuyển đối tượng từ kho lưu trữ vào đơn vị công việc (hoặc phiên).

public void Save(Car car)
{
    session.Save(car);
}

Nhưng hãy xem xét một ví dụ khác, ví dụ lấy xe bằng ID của nó. Nó có thể trông giống như

public function GetCarWithId(String id)
{
    return Session.QueryOver<Car>()
                    .Where(x => x.Id == id)
                    .SingleOrDefault();
}

Vẫn không quá phức tạp, nhưng bạn có thể tưởng tượng với nhiều điều kiện (lấy cho tôi tất cả những chiếc xe được sản xuất sau năm 2010 cho tất cả các thương hiệu trong nhóm 'Volkswagen') điều này trở nên khó khăn. Vì vậy, trong thời trang TDD thực sự, bạn cần phải kiểm tra điều này. Có nhiều hướng khác nhau để làm điều đó.

Tùy chọn 1: Giả định các cuộc gọi được thực hiện cho khung ORM

Chắc chắn, bạn có thể giả định đối tượng Phiên và chỉ cần xác nhận rằng các cuộc gọi đúng được thực hiện. Trong khi điều này kiểm tra kho, nó không phải là thực sự Test- điều khiển bởi vì bạn đang chỉ là thử nghiệm mà các kho nội bộ giống theo cách bạn muốn nó. Bài kiểm tra về cơ bản nói rằng 'mã sẽ trông như thế này'. Tuy nhiên, đây là một cách tiếp cận hợp lệ nhưng có cảm giác như loại thử nghiệm này có rất ít giá trị.

Tùy chọn 2: (Re) xây dựng cơ sở dữ liệu từ các thử nghiệm

Một số khung DAL cung cấp cho bạn khả năng xây dựng cấu trúc hoàn chỉnh của cơ sở dữ liệu dựa trên các tệp ánh xạ bạn tạo để ánh xạ tên miền lên các bảng. Đối với các khung công tác này, cách để kiểm tra kho thường là tạo cơ sở dữ liệu với cơ sở dữ liệu trong bộ nhớ trong bước đầu tiên của kiểm tra và thêm các đối tượng sử dụng khung DAL vào cơ sở dữ liệu trong bộ nhớ. Sau này, bạn có thể sử dụng kho lưu trữ trên cơ sở dữ liệu trong bộ nhớ để kiểm tra xem các phương thức có hoạt động không. Những bài kiểm tra này chậm hơn, nhưng rất hợp lệ và thúc đẩy bài kiểm tra của bạn. Nó đòi hỏi một số hợp tác từ khung DAL của bạn.

Tùy chọn 3: Kiểm tra trên cơ sở dữ liệu thực tế

Một cách tiếp cận khác là kiểm tra trên cơ sở dữ liệu thực tế và cách ly không đáng tin cậy nhất. Bạn có thể thực hiện việc này theo nhiều cách: bao quanh các thử nghiệm của mình bằng một giao dịch, dọn dẹp thủ công (sẽ không khuyến nghị rất khó bảo trì), xây dựng lại hoàn toàn cơ sở dữ liệu sau mỗi bước ... Tùy thuộc vào ứng dụng bạn đang xây dựng có thể hoặc có thể không khả thi Trong các ứng dụng của mình, tôi hoàn toàn có thể xây dựng cơ sở dữ liệu phát triển cục bộ từ kiểm soát nguồn và việc không lưu trữ của tôi trên các kho lưu trữ sử dụng các giao dịch để cách ly hoàn toàn các kiểm tra với nhau (giao dịch mở, chèn dữ liệu, kho lưu trữ kiểm tra, giao dịch rollback). Mỗi bản dựng trước tiên sẽ thiết lập cơ sở dữ liệu phát triển cục bộ và sau đó thực hiện các lệnh không phân tách giao dịch cho các kho lưu trữ trên cơ sở dữ liệu phát triển cục bộ đó. Nó '

Đừng kiểm tra DAL

Nếu bạn đang sử dụng khung DAL như NHibernate, hãy tránh kiểm tra khung đó. Bạn có thể kiểm tra các tệp ánh xạ của mình bằng cách lưu, truy xuất và sau đó so sánh một đối tượng miền để đảm bảo mọi thứ đều ổn (đảm bảo vô hiệu hóa bất kỳ loại bộ đệm nào) nhưng nó không được yêu cầu như nhiều bài kiểm tra khác mà bạn nên viết. Tôi có xu hướng làm điều này chủ yếu cho các bộ sưu tập về cha mẹ có điều kiện về trẻ em.

Khi kiểm tra sự trở lại của kho lưu trữ của bạn, bạn chỉ cần kiểm tra xem liệu một số thuộc tính xác định trên đối tượng miền của bạn có khớp hay không. Đây có thể là một id nhưng trong các thử nghiệm thường có lợi hơn khi kiểm tra một tài sản có thể đọc được của con người. Trong phần 'hãy cho tôi tất cả những chiếc xe được sản xuất sau năm 2010 ....' điều này có thể chỉ cần kiểm tra xem có năm chiếc xe được trả lại và biển số xe là 'danh sách chèn ở đây'. Thêm lợi ích là nó buộc bạn phải suy nghĩ về việc sắp xếp VÀ bài kiểm tra của bạn sẽ tự động buộc việc sắp xếp. Bạn sẽ ngạc nhiên về số lượng ứng dụng sắp xếp nhiều lần (trả về được sắp xếp từ cơ sở dữ liệu, sắp xếp trước khi tạo đối tượng xem và sau đó sắp xếp đối tượng xem, tất cả trên cùng một thuộc tính chỉ trong trường hợp ) hoặc mặc nhiên giả định sắp xếp kho lưu trữ và vô tình xóa rằng một số người đang trên đường đi, phá vỡ giao diện người dùng.

'Bài kiểm tra đơn vị' chỉ là một cái tên

Theo tôi, các bài kiểm tra đơn vị chủ yếu không nên đánh vào cơ sở dữ liệu. Bạn xây dựng một ứng dụng sao cho mọi đoạn mã cần dữ liệu từ một nguồn thực hiện điều này với một kho lưu trữ và kho lưu trữ đó được thêm vào như một phần phụ thuộc. Điều này cho phép dễ dàng chế giễu và tất cả lòng tốt TDD bạn muốn. Nhưng cuối cùng, bạn muốn chắc chắn rằng các kho lưu trữ của bạn thực hiện nhiệm vụ của mình và nếu cách dễ nhất để làm điều đó là đánh vào cơ sở dữ liệu, thì cũng vậy. Từ lâu tôi đã từ bỏ quan niệm rằng 'các bài kiểm tra đơn vị không nên chạm vào cơ sở dữ liệu' và học được rằng có những lý do rất thực tế để làm điều này. Nhưng chỉ khi bạn có thể làm điều này tự động và lặp đi lặp lại. Và thời tiết chúng tôi gọi một bài kiểm tra như vậy là 'bài kiểm tra đơn vị' hoặc 'bài kiểm tra tích hợp' là tranh luận.


3
Kiểm tra đơn vị và kiểm tra tích hợp có mục đích khác nhau. Tên của các thử nghiệm này không chỉ đơn thuần là trang trí; họ cũng được mô tả.
Robert Harvey

9
  1. Đừng kiểm tra các phương pháp lưu trữ tầm thường hoặc rõ ràng.

    Nếu các phương thức là các hoạt động CRUD tầm thường, tất cả những gì bạn thực sự kiểm tra là liệu các tham số có được ánh xạ chính xác hay không. Nếu bạn có các bài kiểm tra tích hợp, những lỗi như vậy sẽ trở nên rõ ràng ngay lập tức.

    Đây là cùng một nguyên tắc áp dụng cho các thuộc tính tầm thường, như thế này:

    public property SomeProperty
    {
        get { return _someProperty; }
        set { _someProperty = value; }
    }
    

    Bạn không kiểm tra nó, bởi vì không có gì để kiểm tra. Không có xác nhận hoặc logic khác trong tài sản cần phải được xác minh.

  2. Nếu bạn vẫn muốn thử nghiệm các phương pháp đó ...

    Mocks là cách để làm điều đó. Hãy nhớ rằng, đây là những bài kiểm tra đơn vị. Bạn không kiểm tra cơ sở dữ liệu bằng các bài kiểm tra đơn vị; đó là những gì Kiểm tra tích hợp dành cho.

Thêm thông tin
Toàn bộ, Phần 3: Xây dựng Kho lưu trữ bằng TDD (bắt đầu xem sau khoảng 16 phút).


3
Chắc chắn, tôi hiểu điều này. Tuy nhiên, nếu đó là cách tiếp cận TDD, tôi không nên viết bất kỳ mã nào nếu tôi không có thử nghiệm cho mã này trước, phải không?
Thaven

1
@Thaven - có một loạt các video trên youtube có tên "đã chết?". Xem họ. Họ giải quyết rất nhiều điểm thú vị, một trong số đó là khái niệm rằng áp dụng TDD ở mọi cấp độ ứng dụng của bạn không nhất thiết là ý tưởng tốt nhất. "Không có mã mà không có bài kiểm tra thất bại" là một vị trí quá cực đoan, là một trong những kết luận.
Jules

2
@Jules: tl; dw là gì?
Robert Harvey

1
@RobertHarvey Thật khó để tóm tắt, nhưng điểm quan trọng nhất là việc coi TDD như một tôn giáo luôn phải được quan sát là một sai lầm. Lựa chọn sử dụng nó là một phần của sự đánh đổi và bạn cần xem xét rằng (1) bạn có thể làm việc nhanh hơn mà không gặp phải một số vấn đề và (2) nó có thể đẩy bạn tới một giải pháp phức tạp hơn bạn cần, đặc biệt nếu bạn thấy mình sử dụng rất nhiều giả.
Jules

1
+1 cho điểm # 1. Các xét nghiệm có thể sai, chỉ là chúng thường tầm thường. Việc kiểm tra một chức năng có độ chính xác rõ ràng hơn kiểm tra là vô nghĩa. Không giống như việc bảo hiểm mã 100% giúp bạn tiến gần đến việc kiểm tra mọi thực thi chương trình có thể, vì vậy bạn cũng có thể thông minh về nơi bạn dành nỗ lực kiểm tra.
Doval
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.