読者です 読者をやめる 読者になる 読者になる

maeshimaの日記

メモ書きです

thinking_sphinx 利用時のテスト方法

transactional fixtures をオフにしないと search メソッドは値を返さないそうな。

cucumber

1.3.2 から、thinking_sphinx は cucumber と連携しやすくするためのヘルパーメソッドを用意した。

features/support/env.rb に下記の二行を足す。

require 'cucumber/thinking_sphinx/external_world'
Cucumber::ThinkingSphinx::ExternalWorld.new

あと transactinal fixture もオフにする。グローバルで設定するなら features/support/env.rb に下記を書く。

Cucumber::Rails::World.use_transactional_fixtures = false

フィーチャかシナリオ単位で使うだけなら @no-txn タグを使ってもいい

@no-txn
Feature: Searching for articles

なぜこうするのかというと、ActiveRecord は単一のトランザクション中で全ての操作をすることが出来るのだけれど、Sphinx はそれにアクセスできないので、Sphinxトランザクション中の変更をインデックスに含めることが不可能だから。

完成度を高めるために、シナリオ毎にデータをクリアする必要があるかもしれない。下記のようなコードをステップファイルのどこかに書くか、Database Cleaner を導入するかするといい。

Before do
  # Add your own models here instead.
  [Article, User].each do |model|
    model.delete_all
  end
end

一度設定すれば、フィーチャを実行したときにSphinxは自動的にインデックスを作ってデーモンを開始する。でも一番最初だけで、全てのシナリオでそうするわけではない。特定のシナリオでインデックスを作り直したいときには、下記のようなステップを追加するのがオススメ(モデルのデータの準備をした後、webratがブラウズする前のタイミングで)

Given 'the Sphinx indexes are updated' do
  # Update all indexes
  ThinkingSphinx::Test.index
  sleep(0.25) # Wait for Sphinx to catch up
end

Given 'the Sphinx indexes for articles are updated' do
  # Update specific indexes
  ThinkingSphinx::Test.index 'article_core', 'article_delta'
  sleep(0.25) # Wait for Sphinx to catch up
end

デフォルトの Delta indexes を使っている場合、インデックスは普通にアプリを使っているときのように自動でアップデートされる。

Rails Functional and Integration Tests

Cucumberとほぼ同じ感じで、ingegration test でも thinking_sphinx を使うことが出来る。test_helper.rb に下記のように書く。

require 'thinking_sphinx/test'
ThinkingSphinx::Test.init

テスト毎にtransactional fixture をオフに出来る。

class SearchControllerTest
  self.use_transactional_fixtures = false
  
  # ...
end

全てのテストで sphinx を走らせたければ、test_helper.rb で下記のようにするといい。

ThinkingSphinx::Test.start_with_autostop

一部で走らせたい場合は、下記のように start と stop を使う。

test "Searching for Articles" do
  ThinkingSphinx::Test.start
  
  get :index
  assert [@article], assigns[:articles]
  
  ThinkingSphinx::Test.stop
end

こんな風にも書ける。

test "Searching for Articles" do
  ThinkingSphinx::Test.run do
    get :index
    assert [@article], assigns[:articles]
  end
end

インデックス作成を手動でする必要があるときは、下記のようにする。

ThinkingSphinx::Test.index # 全部のインデックスを作る
ThinkingSphinx::Test.index 'article_core', 'article_delta' # 一部のインデックスを指定