そろそろ試験書こう
色々自動で作成されてたりしますが。
とは言え
書き始め、は今が最適なのか。あと、Web API なナニの stab ってどうやって作るのかな。なんか WebMock などという便利系な Gem がある模様。あ、でも直接云々してる訳ではないから普通に stub で云々、で良いのかな。
ええと、RSpec でテストを作るのに役立つ「モック/スタブ」のシンプルな説明 によると
[Object].stub(:[Method]).and_return([戻り値])
て事なのか。とりあえず index なアクションのナニをでっち上げてみたので試験を書いてみましょう。微妙にハマッて scaffold を参考にしてみたところログインなソレは以下の記述で OK だったようです。
before do login_user end
その後
当分ハマッて夕方に至っております。とりあえず以下な index コントローラの試験を通す、を目標にもごもごしておりました。
class VmOperationController < ApplicationController before_filter :authenticate_user! def index ret = VirtualMachine.find_by_conn(current_user.conns) @virtual_machines = [] ret.each { |i| @virtual_machines.push(i[:virtual_machines]["listvirtualmachinesresponse"]) } respond_to do |format| format.html # index.html.erb format.json { render json: @virtual_machines } end end
ユーザが持ってる諸々の Cloud サービスなコネクション情報を元にそれぞれでアクティブになってるホスト情報の一覧を、という形なのかどうか。view の記述は略しますが単純にホスト名をテーブルで表示してるのみ、です。
また、model の記述が以下。修正必要ですが晒す。
def self.find_by_conn(conns) ret = [] conns.each { |conn| virtual_machines = Hash::new uri = URI.parse(conn.end_point) compute = Fog::Compute.new(:provider => conn.provider, :cloudstack_api_key => conn.access_key, :cloudstack_secret_access_key => conn.secret_access_key, :cloudstack_host => uri.host, :cloudstack_port => uri.port, :cloudstack_path => uri.path, :cloudstack_scheme => uri.scheme, ) virtual_machines[:conn] = conn virtual_machines[:virtual_machines] = compute.list_virtual_machines ret.push(virtual_machines) } ret end
で、パスしているであろう試験が以下。
context "When user is signed in" do before do login_user end it "returns http success" do Fog.mock! Fog::Mock.delay = 0 @mock_creds = { :provider => "CloudStack", :cloudstack_api_key => "xxx", :cloudstack_secret_access_key => "yyy", :cloudstack_host => "hostname", :cloudstack_port => "port", :cloudstack_path => "uri", :cloudstack_scheme => "scheme", } cloudstack = Fog::Compute.new(@mock_creds) Fog::Compute.stub(:new).and_return(cloudstack) cloudstack.stub(:list_virtual_machines).and_return({}) get 'index' response.should be_success end end
mock で云々できるのは非常に有難いです。当初は stub のみで云々とかしてたのですが、なかなか上手くいかずでした。一旦 mock なオブジェクトを作って、てのがポイントだった模様。
これを踏まえて晩メシ後ももごもごな方向です。
factories.rb
以下に修正してました。ので以下な記述で不具合が出ている模様。
FactoryGirl.define do factory :user do id 1 email "michael@example.com" password "foobarbaz" password_confirmation "foobarbaz" after(:create) do |user| create(:conn, user: user) end end factory :conn do id 1 access_key "xxx" end_point "http://demmy.example.com/" secret_access_key "yyy" provider "CloudStack" user_id 1 end end
scaffold で自動生成された試験が例えば以下なカンジになってて
context "When user is signed in" do before do login_user end it "destroys the requested item" do conn = FactoryGirls.create(:conn) expect { delete :destroy, {:id => conn.to_param} }.to change(Conn, :count).by(-1) end
conn に代入してる部分を無理くり以下にすると試験パスしてます。
conn = subject.current_user.conns[0]
現状、いくつかの試験が pending な状態。なんとか綺麗な状態にして、なんですがどうなるか。
追記
ええと、以下の記述はヘルパメソドに入れちゃって良いのかな。
Fog.mock! Fog::Mock.delay = 0 @mock_creds = { :provider => "CloudStack", :cloudstack_api_key => "xxx", :cloudstack_secret_access_key => "yyy", :cloudstack_host => "hostname", :cloudstack_port => "port", :cloudstack_path => "uri", :cloudstack_scheme => "scheme", } cloudstack = Fog::Compute.new(@mock_creds) Fog::Compute.stub(:new).and_return(cloudstack) cloudstack.stub(:list_virtual_machines).and_return({})
やってみましょう。ヘルパではなくて spec/support/controller_macros.rb に以下を追加。
def fog_mock_init Fog.mock! Fog::Mock.delay = 0 @mock_creds = { :provider => "CloudStack", :cloudstack_api_key => "xxx", :cloudstack_secret_access_key => "yyy", :cloudstack_host => "hostname", :cloudstack_port => "port", :cloudstack_path => "uri", :cloudstack_scheme => "scheme", } cloudstack = Fog::Compute.new(@mock_creds) Fog::Compute.stub(:new).and_return(cloudstack) cloudstack.stub(:list_virtual_machines).and_return({}) end
で、試験が以下なカンジに。
context "When user is signed in" do before do login_user end it "returns http success" do fog_mock_init get 'index' expect(response).to be_success end end
list_virtual_machines が空の Hash を戻してるのが良いのだろうか。とりあえずこれでスタート地点に立てた模様です。頑張ろう。
TODO 控え
ええと
- 以下な routing 追加して云々
resources :vm_operation do member do get :start, :stop end end
- create なアクション
- start/stop なアクション
ここは早めに実装マストなのでこれから検討。
新規に追加
どうも Rails 的には以下な作法らしい。
POST /conns(.:format) conns#create new_conn GET /conns/new(.:format) conns#new
new なアクションでフォームが出てきてそこから POST するのは create アクションなのか。
以下な設定を追加しつつ spec/routing な試験を確認してみる方向。
resources :vm_operations, only: [:new, :create, :index] do member do get :start, stop end end
member てのがアレですが (何
で、盛り込んで rake routs したら以下が出力されました。すばら。
start_vm_operation GET /vm_operations/:id/start(.:format) vm_operations#start stop_vm_operation GET /vm_operations/:id/stop(.:format) vm_operations#stop vm_operations GET /vm_operations(.:format) vm_operations#index POST /vm_operations(.:format) vm_operations#create new_vm_operation GET /vm_operations/new(.:format) vm_operations#new
一応これを踏まえて routing の試験も書いておくことに。
つうか、コントローラな class の名前を単数にしてたのも含め、ここでもハマるなど。週末はだらだらしてたのですが、なるべく朝練でこのあたりの実装をアレして某所に連絡を、と思いつつ (ry