2012-05-18 21 views
16

Trong khi thực hiện Hướng dẫn Ruby On Rails của Michael Hartl, trong phần tác giả viết bài kiểm tra tích hợp để xác thực trang đăng ký của mình, ông đã sử dụng mã spinet dưới đây. Tôi đã nhận được những gì các mã nào nhưng không thể có được đầu của tôi xung quanh phần 'như thế nào' tức là không thể hiểu được trật tự thực hiện.Làm thế nào để RSpec mong đợi làm việc trong ROR

expect { click_button "Create my account" }.not_to change(User, :count) 

Ai đó có thể giải thích ngữ nghĩa của chuỗi phương pháp trên và cách chúng khớp với nhau không?

+3

Đây không phải là Capybara, đó là RSpec. –

+0

@RyanBigg Cảm ơn, chỉ cần sửa chữa nó. – Bedasso

Trả lời

45

Bạn muốn sử dụng expect ... change để xác minh rằng một đặc biệt thay đổi phương pháp gọi - hoặc không thay đổi - một số giá trị khác. Trong trường hợp này:

expect { click_button "Create my account" }.not_to change(User, :count) 

sẽ gây rspec phải làm như sau:

  1. Run User.count và lưu ý các giá trị trả về. (Điều này có thể được chỉ định làm người nhận và tên phương thức, chẳng hạn như (User, :count) trong ví dụ của bạn hoặc dưới dạng một khối mã tùy ý, như { User.count }.
  2. Chạy click_button "Create my account" là phương pháp Capybara mô phỏng nhấp chuột vào một liên kết.
  3. ..
  4. Run User.count lại
  5. Hãy so sánh các kết quả của # 1 và # 3 Nếu chúng khác nhau, ví dụ thất bại Nếu họ giống nhau, nó đi

các cách khác để sử dụng expect ... change:..

expect { thing.destroy }.to change(Thing, :count).from(1).to(0) 
expect { thing.tax = 5 }.to change { thing.total_price }.by(5) 
expect { thing.save! }.to raise_error 
expect { thing.symbolize_name }.to change { thing.name }.from(String).to(Symbol) 

Một số tài liệu là here.

Làm thế nào nó thực hiện điều này là một chút phức tạp và không cần thiết phải hiểu cách hoạt động của nó để sử dụng nó. Một cuộc gọi đến expect là xác định cấu trúc cho rspec thực thi, sử dụng DSL tùy chỉnh của riêng rspec và hệ thống "đối sánh". Gary Bernhardt có screencast khá gọn gàng, trong đó ông cho rằng bí ẩn của rspec thực sự rơi ra một cách tự nhiên từ một ngôn ngữ năng động như ruby.Nó không phải là một giới thiệu tốt để sử dụng rspec, nhưng nếu bạn tò mò về cách tất cả hoạt động, bạn có thể thấy nó thú vị.

CẬP NHẬT

Sau khi nhìn thấy bình luận của bạn về câu trả lời khác, tôi sẽ thêm một chút thông tin về thứ tự của các hoạt động. Bí quyết không trực quan là nó là matcher (change trong trường hợp này) thực thi tất cả các khối. expect có một lambda, not_to là bí danh cho should_not có công việc là chuyển lambda vào trình ghép. Trình phù hợp trong trường hợp này là change mà biết để thực hiện đối số riêng của nó một lần, sau đó thực thi lambda mà nó đã được chuyển (một từ expect), sau đó chạy lại đối số của chính nó để xem mọi thứ có thay đổi không. Đó là khó khăn bởi vì dòng có vẻ như nó nên thực hiện trái sang phải, nhưng vì hầu hết các mảnh chỉ là đi qua các khối mã, họ có thể và trộn chúng vào bất cứ thứ tự nào có ý nghĩa nhất với matcher.

Tôi không phải là chuyên gia về nội dung rspec, nhưng đó là sự hiểu biết của tôi về ý tưởng cơ bản.

+0

Câu trả lời chi tiết và hữu ích nhất mà tôi từng đọc trên SO. Tôi sẽ upvote này 100x nếu tôi có thể. Cảm ơn! –

4

Dưới đây là một đoạn trích từ từ Ryan Bates Railscast on Request Specs and Capybara

require 'spec_helper' 

describe "Tasks" do 
    describe "GET /tasks" do 
    it "displays tasks" do 
     Task.create!(:name => "paint fence") 
     visit tasks_path 
     page.should have_content("paint fence") 
    end 
    end 

    describe "POST /tasks" do 
    it "creates a task" do 
     visit tasks_path 
     fill_in "Name", :with => "mow lawn" 
     click_button "Add" 
     page.should have_content("Successfully added task.") 
     page.should have_content("mow lawn") 
    end 
    end 
end 

Và đây là một đoạn trích từ the docs on RSPec Expectations

describe Counter, "#increment" do 
    it "should increment the count" do 
    expect{Counter.increment}.to change{Counter.count}.from(0).to(1) 
    end 

    # deliberate failure 
    it "should increment the count by 2" do 
    expect{Counter.increment}.to change{Counter.count}.by(2) 
    end 
end 

Vì vậy, về cơ bản, các

expect { click_button "Create my account" }.not_to change(User, :count) 

là một phần RSpec:

expect {...}.not_to change(User, :count) 

và phần Capybara

click_button "Create my account" 

(Dưới đây là a link to the Capyabara DSL - bạn có thể tìm kiếm click_button)

Có vẻ như bạn đang tìm kiếm một ví dụ tổng thể với họ cả. Đây không phải là một ví dụ hoàn hảo, nhưng nó có thể trông giống như thế này:

describe "Tasks" do 
    describe "GET /tasks" do 
    it "displays tasks" do 
     expect { click_button "Create my account" }.not_to change(User, :count) 
    end 
    end 
end 
+0

Tnx cho các ví dụ hay. Tôi đã được nhiều hơn quan tâm để biết ngữ nghĩa của biểu thức như thế nào liều 'thay đổi (..)' được thực hiện hai lần và thứ tự tổng thể thực hiện. – Bedasso

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