2011-06-21 63 views
4

我一直試圖申請Square's method of including Resque in their integration tests沒有太多的運氣。我不知道如果Resque和/或黃瓜自2010年8月你如何整合Resque在黃瓜功能?

改變了很多下面你找到我採取的方法,也許你可以:

  1. 告訴我我哪裏錯了,我怎麼能解決這個問題
  2. 推薦整合Resque到黃瓜功能

我沒有安裝它

什麼的一種全新的方式

廣場的博客文章並沒有對如何安裝它明確的步驟,所以這是我做過什麼:

  1. 下載their gistfeatures/support/cucumber_external_resque_worker.rb
  2. 創建一個Rails初始化在config/initializers/cucumber_external_resque.rb是做了以下內容:
    1. require 'features/support/cucumber_external_resque_worker'
    2. CucumberExternalResqueWorker.install_hooks_on_startup
  3. cucumber_external_resque_worker.rb,我將Rails.env.cucumber?的實例更改爲Rails.env.test?,因爲Cucumber正在運行test環境中的功能(我確實在cucumber_external_resque_worker.rb中執行了一些puts Rails.env
  4. 我運行這些功能。此時,我卡住了,因爲我收到了錯誤uninitialized constant WorkerBase (NameError)。也許Resque改變了它命名的方式。

在此先感謝!

+1

WorkerBase是Bluth的一部分(https://github.com/delano/bluth)..建立在Redis上的簡單排隊系統..也許Square使用它。 –

+0

任何人都有其他選擇嗎? – Trip

回答

6

呦ü可以只通過設置

Resque.inline = true 

運行Resque工作同步添加此行我config/initializers/resque.rb

Resque.inline = Rails.env.test? 

這比在後建議的其他方法更簡潔。因爲它是同步的,所以會慢一點。

+1

謝謝是的!我相信這是一個半最近的補充。我一直在使用它,它的工作原理很棒! –

+0

您是否也使用'WorkerBase'類? – Trip

+0

@旅行不,我沒有使用'WorkerBase' – etagwerker

0

我想在這裏介紹的方法:

Cucumber and Resque Jobs

其同步執行resque處理。在我的情況下,我對測試Resque沒有興趣,我只想測試我的應用程序中的功能。

+0

謝謝。我知道這一點,現在就用它代替上述方法。但畢竟我想要進行集成測試 - 這意味着整個堆棧。 –

3

我今天花了一段時間玩這個,我想我有一個解決方案。

這是更新的Gist,它刪除了對WorkerBase的需求。

它還包含必要的配置更改以使事情正常工作(與您發現的更改相同)。


# This is adapted from this gist: https://gist.github.com/0 by Square 
# The main difference is that it doesn't require Bluth for WorkerBase 
# It also calls prune_dead_workers on start so it doesn't hang on every other run 
# It does not do anything special to avoid connecting to your main redis instance; you should be 
# doing that elsewhere 

class CucumberExternalResqueWorker 
    DEFAULT_STARTUP_TIMEOUT = 1.minute 
    COUNTER_KEY = "cucumber:counter" 

    class << self 
    attr_accessor :pid, :startup_timeout 

    def start 
     # Call from a Cucumber support file so it is run on startup 
     return unless Rails.env.test? 
     if self.pid = fork 
     start_parent 
     wait_for_worker_to_start 
     else 
     start_child 
     end 
    end 

    def install_hooks_on_startup 
     # Call from a Rails initializer 
     return unless Rails.env.test? 
     # Because otherwise crashed workers cause a fork and we pause the actual worker forever 
     Resque::Worker.all.each { |worker| worker.prune_dead_workers } 
     install_pause_on_start_hook 
     install_worker_base_counter_patch 
    end 

    def process_all 
     # Call from a Cucumber step 
     unpause 
     sleep 1 until done? 
     pause 
    end 

    def incr 
     Resque.redis.incr(COUNTER_KEY) 
    end 

    def decr 
     Resque.redis.decr(COUNTER_KEY) 
    end 

    def reset_counter 
     Resque.redis.set(COUNTER_KEY, 0) 
    end 

    private 

    def done? 
     Resque.redis.get(CucumberExternalResqueWorker::COUNTER_KEY).to_i.zero? 
    end 

    def pause(pid = self.pid) 
     return unless Rails.env.test? 
     Process.kill("USR2", pid) 
    end 

    def unpause 
     return unless Rails.env.test? 
     Process.kill("CONT", pid) 
    end 

    def start_parent 
     at_exit do 
     #reset_counter 
     Process.kill("KILL", pid) if pid 
     end 
    end 

    def start_child 
     # Array form of exec() is required here, otherwise the worker is not a direct child process of cucumber. 
     # If it's not the direct child process then the PID returned from fork() is wrong, which means we can't 
     # communicate with the worker. 
     exec('rake', 'resque:work', "QUEUE=*", "RAILS_ENV=test", "VVERBOSE=1") 
    end 

    def wait_for_worker_to_start 
     self.startup_timeout ||= DEFAULT_STARTUP_TIMEOUT 
     start = Time.now.to_i 
     while (Time.now.to_i - start) < startup_timeout 
     return if worker_started? 
     sleep 1 
     end 

     raise "Timeout while waiting for the worker to start. Waited #{startup_timeout} seconds." 
    end 

    def worker_started? 
     Resque.info[:workers].to_i > 0 
    end 

    def install_pause_on_start_hook 
     Resque.before_first_fork do 
     #reset_counter 
     pause(Process.pid) 
     end 
    end 

    def install_worker_base_counter_patch 
     Resque.class_eval do 
     class << self 
      def enqueue_with_counters(*args, &block) 
      CucumberExternalResqueWorker.incr 
      enqueue_without_counters(*args, &block) 
      end 
      alias_method_chain :enqueue, :counters 
     end 
     end 
     Resque::Job.class_eval do 
     def perform_with_counters(*args, &block) 
      perform_without_counters(*args, &block) 
     ensure 
      CucumberExternalResqueWorker.decr 
     end 
     alias_method_chain :perform, :counters 
     end 
    end 
    end 
end 

在黃瓜環境文件features/support/env.rb

後:

require 'cucumber/rails' 

地址:

require 'lib/cucumber_external_resque_worker' 
CucumberExternalResqueWorker.start 

變化:

DatabaseCleaner.strategy = :transaction 

到:

DatabaseCleaner.strategy = :truncation 

此外,創建一個文件:config/initializers/cucumber_external_resque.rb

require 'lib/cucumber_external_resque_worker' 
CucumberExternalResqueWorker.install_hooks_on_startup 
# In my controller, I have: 
    def start 
    if params[:job] then 
     Resque.enqueue(DemoJob, j.id) 
    end 
    redirect_to :action => :index 
    end 
# DemoJob: 
class DemoJob 
    def self.queue 
    :demojob 
    end 
    def perform(job_id) 
    j = Job.find(job_id) 
    j.value = "done" 
    j.save 
    end 
# In your actual Cucumber step file, for instance: 
When /I click the start button for "([^"]*)"/ do |jobname| 
    CucumberExternalResqueWorker.reset_counter 
    Resque.remove_queue(DemoJob.queue) 
    click_button(jobname) 
end 
When /all open jobs are processed/ do 
    CucumberExternalResqueWorker.process_all 
end 

# And you cucumber feature file looks like: 
# Scenario: Starting a job 
# When I click the start button for "Test Job 1" 
#  And all open jobs are processed 
# Then I am on the job index page 
#  And I should see an entry for "Test Job 1" with a value of "done". 
+0

爲什麼在創建初始化程序時,只需將該加載內容放入env.rb中? – Trip

+0

這適用於我,但只是間歇性的。大多數情況下,process_all方法只是掛起:( – Dakuan