2010-04-10 33 views
14

Tôi là người mới đối với Ruby, và tôi đã cố gắng học Rake, RSpec và Cucumber. Tôi tìm thấy một số mã sẽ giúp tôi kiểm tra tác vụ Rake của mình, nhưng tôi đang gặp sự cố khi làm việc. Tôi đã được thông báo ở đây: http://blog.codahale.com/2007/12/20/rake-vs-rspec-fight/ để thả điều này:Thử nghiệm một công việc cào trong rspec (và dưa chuột)

def describe_rake_task(task_name, filename, &block) 
    require "rake" 

    describe "Rake task #{task_name}" do 
    attr_reader :task 

    before(:all) do 
     @rake = Rake::Application.new 
     Rake.application = @rake 
     load filename 
     @task = Rake::Task[task_name] 
    end 

    after(:all) do 
     Rake.application = nil 
    end 

    def invoke! 
     for action in task.instance_eval { @actions } 
     instance_eval(&action) 
     end 
    end 

    instance_eval(&block) 
    end 
end 

vào tệp spec_helper.rb của tôi.

tôi đã quản lý để lấy mã này ra và chạy nó trong bước dưa chuột của tôi như thế này:

When /^I run the update_installers task$/ do 
@rake = Rake::Application.new 
Rake.application = @rake 
load "lib/tasks/rakefile.rb" 
@task = Rake::Task["update_installers"] 

for action in @task.instance_eval { @actions } 
    instance_eval(&action) 
end 

instance_eval(&block) 

Rake.application = nil 
end 

nhưng khi tôi cố gắng để có được những điều làm việc trong rspec, tôi nhận được lỗi sau.

ArgumentError trong 'Rake nhiệm vụ install_grapevine nên cài đặt vào thư mục mygrapevine'

sai số đối số (1 trong 2) /spec/spec_helper.rb: 21: trong instance_eval' /spec/spec_helper.rb: 21:in khối trong invoke! ' /spec/spec_helper.rb: 20: trong số each' /spec/spec_helper.rb: 20:in gọi! ' /spec/tasks/rakefile_spec.rb:12:in 'khối (2 cấp) trong '

Thật không may, tôi đã có chỉ dưới một tuần ruby ​​dưới của vành đai, vì vậy các công cụ lập trình meta đã qua đầu của tôi. Ai có thể chỉ cho tôi đi đúng hướng?

+0

tương tự không có RSpec: http://stackoverflow.com/questions/3530/how-do-i-rake-tasks-within-a-ruby-script –

Trả lời

19

này làm việc cho tôi: (Rails3/Ruby 1.9.2)

When /^the system does it's automated tasks$/ do  
    require "rake" 
    @rake = Rake::Application.new 
    Rake.application = @rake 
    Rake.application.rake_require "tasks/cron" 
    Rake::Task.define_task(:environment) 
    @rake['cron'].invoke 
end 

Thay tên nhiệm vụ cào của bạn ở đây và cũng lưu ý rằng bạn cần có thể là "lib/nhiệm vụ/cron" nếu bạn không có thư mục lib trong đường dẫn tải của bạn.

Tôi đồng ý rằng bạn chỉ nên thực hiện công việc tối thiểu trong tác vụ Rake và đẩy phần còn lại vào các mô hình để dễ kiểm tra. Điều đó được nói rằng tôi nghĩ rằng điều quan trọng là phải đảm bảo rằng mã thực sự chạy trong nhiệm vụ cron của tôi trong các bài kiểm tra tích hợp của tôi vì vậy tôi nghĩ rằng kiểm tra rất nhẹ của các nhiệm vụ rake là hợp lý.

+3

Tôi có xu hướng sử dụng "thực thi" thay vì gọi trong khi kiểm tra của tôi . Đặc biệt nếu nhiều bước phụ thuộc vào việc kiểm tra tác vụ cào, điều này tránh chỉ có thể chạy tác vụ cào một lần. Tham khảo: http://stackoverflow.com/questions/2532427/why-is-rake-not-able-to-invoke-multiple-tasks-consecutively –

16

Vì thử nghiệm cào chỉ là quá nhiều đối với tôi, tôi có xu hướng di chuyển vấn đề này xung quanh. Bất cứ khi nào tôi tìm thấy bản thân mình với một nhiệm vụ cào dài mà tôi muốn thử nghiệm, tôi tạo ra một mô-đun/lớp học trong lib/ và di chuyển tất cả các mã từ nhiệm vụ đó. Điều này để lại nhiệm vụ cho một dòng mã Ruby, ủy nhiệm cho một cái gì đó dễ kiểm thử hơn (lớp, mô-đun, bạn đặt tên nó). Điều duy nhất vẫn chưa được kiểm tra là liệu tác vụ rake có gọi đúng dòng mã (và chuyển đúng các tham số) hay không, nhưng tôi nghĩ điều đó là OK.

Có thể hữu ích khi cho chúng tôi biết đó là dòng thứ 21 của số spec_helper.rb của bạn. Nhưng cho rằng cách tiếp cận mà bạn đăng tải đào sâu trong cào (đề cập đến các biến cá thể của nó), tôi hoàn toàn sẽ từ bỏ nó cho những gì tôi đã đề xuất trong đoạn trước.

5

Tôi đã dành một chút thời gian để dưa chuột để chạy một công việc cào nên tôi nghĩ tôi sẽ chia sẻ cách tiếp cận của mình. Lưu ý: Đây là sử dụng Ruby 2.0.0 và Rake 10.0.4, nhưng tôi không nghĩ rằng hành vi đã thay đổi kể từ phiên bản trước.

Có hai phần cho điều này. Việc đầu tiên là dễ dàng: với một trường hợp thiết lập đúng của Rake::Application sau đó chúng tôi có thể truy cập các nhiệm vụ trên nó bằng cách gọi #[] (ví dụ: rake['data:import']).Một khi chúng ta có một nhiệm vụ chúng ta có thể chạy nó bằng cách gọi #invoke và đi qua trong các đối số (ví dụ rake['data:import'].invoke('path/to/my/file.csv')

Phần thứ hai là lúng túng hơn:.. Đúng cách thiết lập một thể hiện của Rake::Application để làm việc với một khi chúng ta đã làm require 'rake' chúng tôi Có quyền truy cập vào mô-đun Rake.Nó đã có một phiên bản ứng dụng, có sẵn từ Rake.application, nhưng nó chưa được thiết lập - nó không biết về bất kỳ nhiệm vụ cào nào của chúng tôi, tuy nhiên, biết nơi tìm Rakefile của chúng tôi, giả sử chúng tôi đã sử dụng một trong các tên tệp chuẩn: rakefile, Rakefile, rakefile.rb hoặc Rakefile.rb.

Để tải tệp rake chúng tôi chỉ cần d gọi #load_rakefile trên đơn đăng ký, nhưng trước khi chúng tôi có thể thực hiện điều đó, chúng tôi cần gọi số #handle_options. Cuộc gọi tới số #handle_options được điền options.rakelib với giá trị mặc định. Nếu options.rakelib không được đặt thì phương pháp #load_rakefile sẽ phát nổ, vì dự kiến ​​options.rakelib sẽ được liệt kê.

Đây là helper tôi đã kết thúc với:

module RakeHelper 
    def run_rake_task(task_name, *args) 
    rake_application[task_name].invoke(*args) 
    end 

    def rake_application 
    require 'rake' 
    @rake_application ||= Rake.application.tap do |app| 
     app.handle_options 
     app.load_rakefile 
    end 
    end 
end 

World(RakeHelper) 

Pop rằng mã vào một tập tin trong features/support/ và sau đó chỉ cần sử dụng run_rake_task trong các bước của bạn, ví dụ:

When /^I import data from a CSV$/ do 
    run_rake_task 'data:import', 'path/to/my/file.csv' 
end 
3

Các hành vi sức mạnh đã thay đổi kể từ khi câu trả lời chính xác được đăng. Tôi đã gặp sự cố khi thực hiện hai tình huống cần thiết để chạy cùng một tác vụ rake (chỉ có một kịch bản được thực hiện mặc dù tôi sử dụng .execute thay vì .invoke). Tôi nghĩ rằng để chia sẻ cách tiếp cận của tôi để giải quyết vấn đề (Rails 4.2.5 và Ruby 2.3.0).

Tôi đã gắn thẻ tất cả các trường hợp yêu cầu rake với @rake và tôi đã xác định một móc để thiết lập cào chỉ một lần.

# hooks.rb 
Before('@rake') do |scenario| 
    unless $rake 
    require 'rake' 
    Rake.application.rake_require "tasks/daily_digest" 
    # and require other tasks 
    Rake::Task.define_task(:environment) 
    $rake = Rake::Task 
    end 
end 

(Sử dụng một biến toàn cầu được gợi ý ở đây: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)

Trong định nghĩa bước tôi chỉ đơn giản gọi là $rake

# step definition 
Then(/^the daily digest task is run$/) do 
    $rake['collector:daily_digest'].execute 
end 

Bất kỳ thông tin phản hồi được chào đón.

+0

vâng, đó chính xác là bản sửa lỗi chúng tôi cần - cảm ơn! –

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