ちょっぴりテスト突入

今日の作業

明日のRuby研修の下準備
ユーザ削除、ログアウト
テストについて

今日の作業でわかったこと&わからなかったこと

今日からテストについてのタスクに入りました。
これまではdepotディレクトリのappディレクトリやdbディレクトリ内を主に触っていたので
testディレクトリ内にファイルができているのを知らなかったので驚いた。
今日の所はテストを作っていくにあたっての準備的な所で終わってしまったけど、
テスト用DBにスキーマ情報をロードする方法やテストフィクスチャについてなどを
知ることができました。
また明日からはRuby研修に塩見さんのサポート役として参加します。
サポート役ですがいろいろ知らないことの方が多いと思うので、
できるだけ多くの知識を吸収していきたい。

明日やること

モデルのテスト
Ruby研修

調べたことのまとめ

ユーザ削除機能

ユーザが全て削除されてしまうとDBを直接操作してデータを格納するまでログインできなくなるので
そうならないようにする。
それを実現するためにUserモデル内にdont_destroy_dave()というフックメソッドを定義し、
destroyされる前にこのメソッドが呼び出されるようにする。
ここでもコールバックを使うのか〜
コールバックを定義する前回と違う方法は次のようにクラスレベルの宣言を使って、
実際に処理をするインスタンスメソッドを参照する方法。
User.rbモデルに

  before_destroy :dont_destroy_dave
  def dont_destroy_dave
    raise if name == 'aaa'
  end

raiseメソッドは例外を発生させるメソッド。
例外を処理するには次のようにコードをbeginとendで囲みrescue節を記述する。
login_controller.rb

  def delete_user
    id = params[:id]
    if id && user = User.find(id)
      begin
         user.destroy
         flash[:notice] = "ユーザ #{user.name}が削除されました"
      rescue
         flash[:notice] = "このユーザは削除できない"
      end
    end
    redirect_to(:action => :list_users)
  end
Railsによるテストのサポート

このアプリケーションの最上位ディレクトリを見てみると既にその直下にtestと言うサブディレクトリが存在している。
その中には四つのディレクトリと一つのヘルパーファイルがある。

test$ ls
fixtures  functional  integration  mocks  test_helper.rb  unit

Railsでは規約により、モデルを対象とするテストはユニットテスト(unit test)、
コントローラを対象とするテストは機能テスト(functional test)と呼ばれる。
それぞれのディレクトリ内は

/test$ ls functional/
admin_controller_test.rb  login_controller_test.rb  store_controller_test.rb
/test$ ls unit/
add_shipped_at_test.rb  line_item_test.rb  product_test.rb
cart_test.rb            order_test.rb      user_test.rb

とモデルとコントローラに対応するユニットテストと機能テストを記述するためのファイルが、
既に作成されている。

まずはモデルのテストから始める。

その前にこのアプリを作る際3つのDBを作成した。
Railsユニットテストでは自動的にテスト用DBが使用される。
しかしこのDBには商品データはおろかテーブルさえ作成されていない。
でもRailsには開発用DB構造をテスト用DBに複製する機能がある。

/depot$ rake clone_structure_to_test

これでテスト用DBにスキーマをロードできたが商品データは何も格納されていない。
insertで入力することもできるが手間がかかる。
また、今後DBのデータを変更するテストを実行した場合、その後同じ条件でテストを再開するために、
なんらかの方法で初期データをリロードしないといけなくなる。
この問題の対処法としてテストフィクスチャがある。


テストフィクスチャ

テストフィクスチャとはモデルの初期データの内容を指定したもの。
ユニットテストを実行する際、常にテーブルに正しい内容のデータが格納された状態で開始したい場合は、
そのデータの内容をフィクスチャで指定するだけ。
フィクスチャデータはtest/fixturesディレクトリのファイルで指定。
YAMLフォーマットのフィクスチャファイルに1つのモデルのデータだけ記述。
YAMLについて

http://jp.rubyist.net/magazine/?0009-YAML


test/fixtures/products.yml

version_control_book:
  id: 1
  title: Pragmatic Version Control
  description: バージョン管理の使用法
  price: 730
  date_available: 2005-01-26 00:00:00
autmation_book:
  id: 2
  title: Pragmatic Project Automation
  description: プロジェクトを自動化する方法
  price: 2300
  date_available: 2004-01-1 00:00:00

次はユニットテスト実行時に、このテストデータがRailsによってProductsテーブルに
ロードされるようにする。
product_test.rb内に

  fixtures :products

fixtures()メソッドは、このテストケースの各テストメソッドの開始時に指定されたモデル名に
対応するフィクスチャを自動的にロードする。
また規約によりモデルのシンボル名を使用することが決められている。