2010-04-10 15 views
14

मैं रूबी के लिए नया हूं, और मैं रेक, आरएसपीसी, और ककड़ी सीखने की कोशिश कर रहा हूं। मुझे कुछ कोड मिला जो मुझे मेरे रेक कार्यों का परीक्षण करने में मदद करेगा, लेकिन मुझे इसे काम करने में परेशानी हो रही है। मेरी spec_helper.rb फ़ाइल मेंrspec (और ककड़ी) में एक रेक कार्य का परीक्षण

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 

: मैं यहाँ बताया गया था: http://blog.codahale.com/2007/12/20/rake-vs-rspec-fight/ इस ड्रॉप करने।

मैं इस कोड बाहर ले जाना और इस तरह मेरी ककड़ी चरणों में इसे चलाने के लिए प्रबंधित किया है:

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 

लेकिन जब मैं rspec में काम कर बातें प्राप्त करने की कोशिश, मैं निम्नलिखित मिल त्रुटि। आह्वान में instance_eval' /spec/spec_helper.rb: 21:in ब्लॉक में: में

ArgumentError /spec/spec_helper.rb (2 के लिए 1)

तर्कों की

गलत नंबर 'रैक कार्य install_grapevine mygrapevine निर्देशिका के लिए स्थापित करना चाहिए': 21! ' /spec/spec_helper.rb: 20: each' /spec/spec_helper.rb: 20:in में शामिल हों! ' `ब्लॉक /spec/tasks/rakefile_spec.rb:12:in (2 स्तर) में '

दुर्भाग्य से, मैं सिर्फ बेल्ट से नीचे गहरे लाल रंग का के एक सप्ताह के तहत मिल गया है, तो metaprogramming सामान खत्म हो गया है मेरा सिर। क्या कोई मुझे सही दिशा में रास्ता दिखा सकता है?

+0

आरएसपीईसी के बिना समान: http://stackoverflow.com/questions/3530/how-do-i-rake-tasks-within-a-ruby-script –

उत्तर

19

यह मेरे लिए काम करता है: (Rails3/रूबी 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 

यहाँ रेक कार्य नाम स्थानापन्न और यह भी ध्यान दें कि आपकी आवश्यकता हो सकता है "lib/कार्य/क्रॉन" यदि आप नहीं अपने लोड पथ में lib फ़ोल्डर है।

मैं मानता हूं कि आपको केवल रेक कार्य में न्यूनतम कार्य करना चाहिए और शेष को परीक्षण की आसानी के लिए मॉडल पर धक्का देना चाहिए। ऐसा कहा जा रहा है कि मुझे लगता है कि यह सुनिश्चित करना महत्वपूर्ण है कि कोड मेरे एकीकरण परीक्षणों के दौरान वास्तव में मेरे क्रॉन कार्यों में चलाया जाता है, इसलिए मुझे लगता है कि रेक कार्यों का बहुत हल्का परीक्षण उचित है।

+3

मैं अपने परीक्षणों के दौरान आह्वान के बजाय "निष्पादित" का उपयोग करता हूं । विशेष रूप से यदि कई कदम रेक कार्य का परीक्षण करने पर निर्भर करते हैं, तो यह केवल एक बार रेक कार्य को चलाने में सक्षम होता है। रेफरी: http://stackoverflow.com/questions/2532427/why-is-rake-not-able-to-invoke-multiple-tasks-consecutively –

16

चूंकि परीक्षण रेक मेरे लिए बहुत अधिक है, इसलिए मैं इस समस्या को चारों ओर स्थानांतरित करता हूं। जब भी मैं खुद को एक लंबे रेक कार्य के साथ ढूंढता हूं जिसे मैं परीक्षण करना चाहता हूं, तो मैं lib/ में मॉड्यूल/कक्षा बना देता हूं और वहां से सभी कोड को वहां से ले जाता हूं। यह कार्य को रूबी कोड की एक पंक्ति में छोड़ देता है, जो कुछ और टेस्टेबल (वर्ग, मॉड्यूल, आप इसे नाम देते हैं) को प्रतिनिधि करता है। एकमात्र चीज जो अनचाहे बनी हुई है वह यह है कि रेक कार्य कोड की सही रेखा को आमंत्रित करता है (और सही पैरामीटर पास करता है), लेकिन मुझे लगता है कि यह ठीक है।

यह हमें बताने में उपयोगी हो सकता है कि आपके spec_helper.rb की 21 वीं पंक्ति कौन सा है। लेकिन यह देखते हुए कि आपके द्वारा पोस्ट किया गया दृष्टिकोण रेक में गहराई से खोदता है (इसके आवृत्ति चर का जिक्र करता है), मैं पिछले पैराग्राफ में जो सुझाव दिया था, उसके लिए मैं पूरी तरह से इसे छोड़ दूंगा।

5

मैंने रेक कार्य चलाने के लिए ककड़ी प्राप्त करने में थोड़ी देर बिताई है, इसलिए मैंने सोचा कि मैं अपना दृष्टिकोण साझा करूंगा। नोट: यह रूबी 2.0.0 और रेक 10.0.4 का उपयोग कर रहा है, लेकिन मुझे नहीं लगता कि व्यवहार पिछले संस्करणों के बाद बदल गया है।

इसमें दो भाग हैं। पहला आसान है: Rake::Application के ठीक से सेट अप उदाहरण के साथ हम #[] (उदाहरण के लिए rake['data:import']) पर कॉल करके कार्यों को एक्सेस कर सकते हैं।एक बार जब हम एक काम है हम #invoke बुला और बहस में गुजर (द्वारा चला सकते हैं जैसे rake['data:import'].invoke('path/to/my/file.csv')

दूसरे भाग अधिक परेशान करने वाला है:।। ठीक से साथ काम करने के Rake::Application का एक उदाहरण स्थापित करने एक बार जब हम require 'rake' किया है हम Rake मॉड्यूल तक पहुंच है। इसमें पहले से ही एक एप्लीकेशन इंस्टेंस है, जो Rake.application से उपलब्ध है, लेकिन यह अभी तक स्थापित नहीं है - यह हमारे किसी भी रेक कार्यों के बारे में नहीं जानता है। हालांकि, यह पता है कि हमारे रेकफाइल को कहां मिलना है, मानते हैं हम मानक फ़ाइल नामों में से एक का उपयोग किया है:। rakefile, Rakefile, rakefile.rb या Rakefile.rb

सिर्फ nee rakefile हम लोड करने के लिए आवेदन पर #load_rakefile पर कॉल करने के लिए, लेकिन इससे पहले कि हम ऐसा कर सकें, हमें #handle_options पर कॉल करने की आवश्यकता है। #handle_options पर कॉल डिफ़ॉल्ट मान के साथ options.rakelib पर आती है। यदि options.rakelib सेट नहीं है तो #load_rakefile विधि उड़ाएगी, क्योंकि यह options.rakelib को अनुमानित होने की अपेक्षा करता है।

यहाँ सहायक मैं के साथ समाप्त हो गया है या नहीं: features/support/ में एक फ़ाइल में

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) 

पॉप कि कोड और फिर बस अपने चरणों में run_rake_task उपयोग करते हैं, उदाहरण के लिए:

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

व्यवहार हो सकता है सही उत्तर पोस्ट होने के बाद से बदल गया है। मुझे एक ही रेक कार्य को चलाने के लिए आवश्यक दो परिदृश्यों को निष्पादित करने में समस्याएं आ रही थीं (.invoke के बजाय .execute का उपयोग करने के बावजूद केवल एक को निष्पादित किया जा रहा था)। मैंने इस मुद्दे को हल करने के लिए अपना दृष्टिकोण साझा करना सोचा (रेल 4.2.5 और रूबी 2.3.0)।

मैंने उन सभी परिदृश्यों को टैग किया जिन्हें @rake के साथ रेक की आवश्यकता है और मैंने केवल एक बार रेक बनाने के लिए एक हुक परिभाषित किया है।

# 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 

(एक वैश्विक चर का उपयोग करना यहाँ का सुझाव दिया है: https://github.com/cucumber/cucumber/wiki/Hooks#running-a-before-hook-only-once)

कदम परिभाषा में मैं बस $rake

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

कहा जाता है किसी भी प्रतिक्रिया का स्वागत है।

+0

हां, यह बिल्कुल ठीक था जिसकी हमें आवश्यकता थी - धन्यवाद! –

संबंधित मुद्दे