2011-10-06 25 views
11

Tôi có một kiểm tra điều khiển đơn giản, có chứa a.o. đoạn mã sau:Tăng tốc kiểm tra bộ điều khiển rspec: sử dụng trước khi tất cả không thành công?

context "POST :create" do 
    before (:each) do 
    post :create, :user_id => @user.id, 
     :account => { .. some data ... } 
    end 
    it { response.status.should == 201 } 
    it { response.location.should be_present } 
end 

Bây giờ tôi nghĩ ra một cách rất đơn giản để tăng tốc độ thử nghiệm này, và sử dụng một before(:all) thay vì một before(:each). Trong trường hợp đó, bài đăng chỉ được thực hiện một lần.

Vì vậy, tôi đã viết:

context "POST :create" do 
    before (:all) do 
    post :create, :user_id => @user.id, 
     :account => { .. some data ... } 
    end 
    it { response.status.should == 201 } 
    it { response.location.should be_present } 
end 

Nhưng sau đó tôi nhận được các lỗi sau đây:

RuntimeError: 
    @routes is nil: make sure you set it in your test's setup method. 

Đây có phải là do thiết kế? Có cách nào để vượt qua nó?

+1

Bạn đã tìm thấy giải pháp cho điều này chưa? Tôi đã chạy vào cùng một vấn đề. – ktusznio

Trả lời

12

Tôi hỏi câu hỏi này trên mailing list rspec, và nhận được trả lời sau từ chính @dchelimsky:

Có. rspec-rails kết thúc tốt đẹp khung kiểm tra của các đường ray mà không có một khái niệm trước (: tất cả) trong đó, vì vậy tất cả các dữ liệu được đặt lại trước mỗi ví dụ. Ngay cả khi chúng tôi muốn hỗ trợ điều này trong rspec-ray (mà tôi không) nó sẽ yêu cầu thay đổi để đường ray đầu tiên.

Vì vậy, thực hiện cuộc gọi điều khiển là không thể trong một before(:all), nó chỉ có thể được sử dụng để thiết lập DB hoặc các biến mẫu của bạn.

2

Tôi không chắc chắn nếu điều này là một ý tưởng tốt, nhưng thiết lập một biến lớp học với ||= trong khối before(:each) dường như làm việc:

describe PagesController do 
    describe "GET 'index'" do 
    before(:each) do 
     @@response ||= begin 
     get :index 
     response 
     end 
    end 
    it { @@response.should redirect_to(root_path) } 
    it { @@response.status.should == 301 } 
    it { @@response.location.should be_present } 
    end 
end 
+0

Bạn đã thử cái này chưa? Khi tôi thử nghiệm POST này thậm chí không làm việc, bởi vì bạn chưa có trong bất kỳ bối cảnh điều khiển nào. – nathanvda

+0

Rất tiếc, điều đó có nghĩa là để nói _haven't_ đã thử điều này. Cập nhật câu trả lời bằng một kỹ thuật khác. – Zubin

+0

Bây giờ bạn làm một 'trước (: mỗi)' một lần nữa, đó là chính xác những gì tôi muốn tránh, và sau đó có nhiều cách dễ dàng hơn/có thể đọc được để viết nó. Nếu bạn thực hiện 'before: each', bạn có thể viết' get: index' và sử dụng 'response'. – nathanvda

3

Nếu bạn muốn sử dụng biến toàn cục bẩn và hưởng lợi từ việc tăng tốc, bạn có thể sử dụng điều này nhưng cảnh báo. Logic lộn xộn này thực hiện công việc nhưng đánh bại mục đích của việc lái xe với các xét nghiệm rõ ràng có thể đọc được tinh thể. Tái cấu trúc trong một helper với năng suất là nhiều hơn đề nghị.

describe PagesController do 
    describe "GET 'index'" do 
    before(:each) do 
     GLOBAL ||= {} 
     @response = GLOBAL[Time.now.to_f] || begin 
     get :index 
     response 
     end 
    end 
    it { @response.should redirect_to(root_path) } 
    it { @response.status.should == 301 } 
    it { @response.location.should be_present } 
    end 
end 

Các cấu trúc lại bạn có thể đặt vào một tập tin bạn đã chọn trong spec/hỗ trợ đi như sau

RSPEC_GLOBAL = {} 

def remember_through_each_test_of_current_scope(variable_name) 
    self.instance_variable_set("@#{variable_name}", RSPEC_GLOBAL[variable_name] || begin 
    yield 
    end) 
    RSPEC_GLOBAL[variable_name] ||= self.instance_variable_get("@#{variable_name}") 
end 

Do đó, các mã trong tập tin thử nghiệm trở thành:

describe PagesController do 
    describe "GET 'index'" do 
    before(:each) do 
     remember_through_each_test_of_current_scope('memoized_response') do 
     get :index 
     response 
     end 
    end 
    it { @memoized_response.should redirect_to(root_path) } 
    it { @memoized_response.status.should == 301 } 
    it { @memoized_response.location.should be_present } 
    end 
end 

Hy vọng nó và một lần nữa, hãy sử dụng cẩn thận

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