2015-08-10 16 views
13

Tôi đã phát triển trong RoR hơn một năm nay, nhưng tôi mới bắt đầu sử dụng các bài kiểm tra, sử dụng RSpec.Làm cách nào để cấu trúc thư mục, tệp và cơ sở dữ liệu kiểm tra RSpec của tôi?

Đối với thử nghiệm mô hình/bộ điều khiển chuẩn, tôi thường không gặp vấn đề gì, nhưng vấn đề là tôi muốn thử nghiệm một số quy trình chức năng phức tạp và không biết cách cấu trúc thư mục/tệp/cơ sở dữ liệu thử nghiệm của mình .

Dưới đây là một cấu trúc cơ bản cho ứng dụng của tôi:

class Customer 
    has_one :wallet 
    has_many :orders  
    has_many :invoices, through: :orders 
    has_many :invoice_summaries 
end 

class Wallet 
    belongs_to :customer 
end 

class Order 
    has_one :invoice 
    belongs_to :customer 
end 

class Invoice 
    belongs_to :order 
    belongs_to :invoice_summary 
end 

class InvoiceSummary 
    belongs_to :customer 
    has_many :invoices 
end 

Vấn đề chính là tôi muốn để mô phỏng vòng đời của đối tượng của tôi, có nghĩa là:

  • Instantiating khách hàng và ví đó sẽ được sử dụng cho tất cả các thử nghiệm (không cần khởi tạo lại)

  • Mô phỏng luồng thời gian, tạo và cập nhật nhiều đơn đặt hàng/đối tượng hóa đơn và một số i nvoice_summaries.

Đối với việc tạo ra và cập nhật các đơn đặt hàng/hóa đơn/invoice_summaries, tôi muốn có phương pháp như

def create_order_1 
    # code specific to create my first order, return the created order 
end 

def create_order_2 
    # code specific to create my second order, return the created order 
end 
. 
. 
. 
def create_order_n 
    # code specific to create my n-th order, return the created order 
end 

def bill_order(order_to_bill) 
    # generic code to do the billing of the order passed as parameter 
end 

def cancel_order(order_to_cancel) 
    # generic code to cancel the order passed as parameter 
end 

Tôi đã tìm thấy viên ngọc Timecop cho mô phỏng dòng chảy thời gian. Do đó, tôi muốn có một bài kiểm tra cuối cùng dễ hiểu giống như

# Code for the initialization of customers and wallets object 

describe "Wallet should be equal to 0 after first day" do 
    Timecop.freeze(Time.new(2015,7,1)) 
    first_request = create_request_1 
    first_request.customer.wallet.value.should? == 0 
end 

describe "Wallet should be equal to -30 after second day" do 
    Timecop.freeze(Time.new(2015,7,2)) 
    bill_order(first_request) 
    second_order = create_order_2 
    first_request.customer.wallet.value.should? == -30 
end 

describe "Wallet should be equal to -20 after third day" do 
    Timecop.freeze(Time.new(2015,7,3)) 
    bill_order(second_request) 
    cancel_order(first_request) 
    first_request.customer.wallet.value.should? == -20 
end 

describe "Three first day invoice_summary should have 3 invoices" do 
    Timecop.freeze(Time.new(2015,7,4)) 
    invoice_summary = InvoiceSummary.create(
     begin_date: Date.new(2015,7,1), 
     end_date: Date.new(2015, 7,3) 
) # real InvoiceSummary method 
    invoice_summary.invoices.count.should? == 3 
end 

Có ai đã có các bài kiểm tra như vậy không? Có thực hành tốt cho cấu trúc của các nhà máy đối tượng, kiểm tra văn bản và như vậy?

Ví dụ, tôi đã được cho biết rằng một ý tưởng hay là đặt công cụ tạo khách hàng/Wallet trong tệp db/seed.rb, nhưng tôi thực sự không biết phải làm gì với nó sau đó.

+0

@HunterStevens Tôi tin rằng chỉnh sửa của bạn sai, bởi vì bạn đã xóa một số logic về các đơn đặt hàng. 'def create_order_n; end' IS khác với 'def create_order_1; end' 'def create_order_2; end' vì @vincent muốn thể hiện sự cần thiết phải làm 2 điều hoàn toàn khác biệt. Bạn nên cẩn thận trước khi chỉnh sửa như thế này ... – Erowlin

+0

@Erowlin vui lòng quay lại bản chỉnh sửa của tôi sau đó. Tôi đã cố gắng để làm sạch một bài rất dài. Lấy làm tiếc. – onebree

+0

NP, hãy cẩn thận lần sau;). BTW, cảm ơn bạn đã chỉnh sửa, nó bắt đầu từ một ý định tốt! – Erowlin

Trả lời

5

Trả lời đầy đủ câu hỏi của bạn có thể lấp đầy và đã điền sách, vì vậy tôi chỉ có thể phác thảo câu trả lời ở đây.

Về tạo các đối tượng để kiểm tra,

  • db/seeds.rb không phải dành cho dữ liệu kiểm tra, nhưng đối với dữ liệu tĩnh, không thay đổi bởi người sử dụng, đó là cần thiết cho các ứng dụng để chạy, cho dù trong phát triển hoặc thử nghiệm hoặc sản xuất. Các ví dụ phổ biến về loại dữ liệu này bao gồm mã quốc gia và vai trò người dùng.

  • Có hai phương pháp chung để tạo dữ liệu thử nghiệm, đồ đạc và nhà máy.

    • Đồ đạc là phương pháp Rails ngoài hộp. Chúng được tạo ra một lần khi cơ sở dữ liệu thử nghiệm được tạo ra. Chúng nhanh chóng khi bạn có nhiều bài kiểm tra, vì chúng chỉ được tạo một lần ở đầu bộ thử nghiệm. Tuy nhiên, họ kiểm tra dọc bởi vì họ khuyến khích viết bài kiểm tra xung quanh đồ đạc hiện có, vì vậy tôi khuyên bạn nên chống lại chúng.
    • Nhà máy là các tiện ích tạo đối tượng. Bạn tạo các đối tượng bạn cần trong mỗi bài kiểm tra và xóa hoặc cuộn chúng lại ở cuối. Hầu hết các dự án Rails sử dụng các nhà máy sử dụng FactoryGirl. Đó là những gì tôi đề nghị.

    Cả hai phương pháp đều đặt mã tạo đối tượng vào các tệp riêng trong một thư mục khác với thông số kỹ thuật của bạn. Nếu bạn tìm kiếm SO cho "đồ đạc hoặc nhà máy", bạn sẽ tìm thấy nhiều cuộc thảo luận nhiều hơn về cả hai.

Thông số kỹ thuật của bạn sẽ dễ hiểu hơn nếu bạn đặt tất cả các giá trị quan trọng, trong đó trường hợp có thể nhìn thấy và so sánh với kết quả bạn đang khẳng định . (Nếu không, bạn cần phải ghi nhớ ngày tháng và số tiền trong các đối tượng thử nghiệm của bạn để hiểu các thông số kỹ thuật.) Bạn có thể đưa ra các phương thức tạo đối tượng trong các tham số dateamount thử nghiệm của mình. Bạn có thể cần ít phương pháp hơn. Nếu bạn đã sử dụng FactoryGirl, nó có thể chỉ là một câu hỏi xác định các thuộc tính created_atamount của mỗi đối tượng. Cũng lưu ý rằng Rails có các phương thức như 1.day.from_now; nếu bạn tạo các đối tượng có ngày được xác định theo cách đó, bạn có thể không cần timecop.

Về cách bố trí RSpec thông số kỹ thuật trong hệ thống tập tin, ở cấp cao nhất, chỉ cần thực hiện bố trí giống hệt như của ứng dụng Rails của bạn:

app/ 
    controllers/ 
    bars_controller.rb 
    foos_controller.rb 
    models/ 
    bar.rb 
    foo.rb 
    ... 
    ... 

spec/ 
    controllers/ 
    bars_controller_spec.rb 
    foos_controller_spec.rb 
    ... 
    models/ 
    bar_spec.rb 
    foo_spec.rb 
    ... 
    ... 

Nếu thông số kỹ thuật của bạn cho một lớp duy nhất nhận được quá lớn, đó là một dấu hiệu cho thấy lớp học quá lớn. Tìm một số mẫu để phá vỡ nó và kiểm tra từng phần riêng lẻ. Nếu bạn thực sự không thể phá vỡ lớp học (một tình huống hiếm hoi), hãy chuyển tệp thông số của lớp thành một thư mục các tệp spec, như tôi đã mô tả trong How to break down super long specs in RSpec?.

+0

Thêm chi tiết về [cấu trúc thư mục được đề xuất RSpec tại đây] (https://relishapp.com/rspec/rspec-rails/docs/directory-structure). –

0

Bạn nên sử dụng FactoryGirl cho công việc của mình. Cấu hình nó như được mô tả trong tài liệu, và sau đó chỉ cần sử dụng nó như thế này:

# factories.rb 
factory :order do 
end 

# your spec 
first_order = create(:order, ...) # configure parameters of order in-place 

Hoặc có nhà máy cụ thể xử lý các loại yêu cầu khác nhau:

# factories.rb 
factory :expensive_order, class: Order do 
    amount 999 # have 'amount' field of Order be equal to 999 
end 

# your spec 
first_order = create(:expensive_order) 

Bạn có thể có FactoryGirl xử lý các hiệp hội một cách tự động:

factory :order do 
    association :user # automatically create User association 
end 

Bạn đang mô tả sự cố chính xác mà nhà phát triển của FactoryGirl đang hướng đến để giải quyết.

Các vấn đề liên quan