7.1 イテレーションB1 : 検証!
以下について実施
・検証およびエラー通知の実行
・ユニットテスト
productテーブルの項目に対するチェックを書く
class Product < ActiveRecord::Base #各項目の必須チェック validates :title, :description, :image_url, presence: true #数値かつ指定数値以上かをチェック validates :price, numericality: {greater_than_or_equal_to: 0.01} #他の商品名と重複しない名称かをチェック validates :title, uniqueness: true #適切な画像のURLかをチェック validates :image_url, allow_blank: true, format: { with: %r{.(gif|jpg|png)$}i, message: 'はGIF, JPG, PNG画像のURLでなければなりません' } end
と、そこでエラー発生
\n(改行)を用いた場合、その後は^$が有効にならないらしい。
この場合^→\A $→\z と変更すべきらしい。
rails4の場合。
http://jumperson.hatenablog.com/entry/2013/06/27/062237
いつのまにか以前導入したrails4で動作させていたみたい。
rails4で動作させていきます。
ここでテストを実行
depot> rake test 1) Failure: ProductsControllerTest#test_should_create_product 2) Failure: ProductsControllerTest#test_should_update_product
二つのエラー発生、scaffoldが自動作成してくれたテストクラスを修正していく。
入力チェックを挿入したことにより、チェックに通るデータを設定する必要がでてきた様子。
class ProductsControllerTest < ActionController::TestCase setup do @product = products(:one) #入力チェックに通るデータを設定(ハッシュのみの場合の簡略記法で記述) @update = { title: 'Lorem Ipusum', description: 'Wibbles are fun!', image_url: 'lorem.jpg', price: 19.95 } end ・・・ test "should create product" do assert_difference('Product.count') do post :create, product:@update end assert_redirected_to product_path(assigns(:product)) end ・・・ test "should update product" do patch :update, id: @product, product: @update assert_redirected_to product_path(assigns(:product)) end
ユニットテストの書き方
require 'test_helper' class ArticleTest < ActiveSupport::TestCase test テスト名 do テストコード end
モデルにおけるテストを書くと以下
class ProductTest < ActiveSupport::TestCase test "product attribute must not be empty" do product = Product.new # productモデルが妥当でないかをチェック assert product.invalid? # ハッシュで指定した項目のエラー有無チェック assert product.errors[:title].any? assert product.errors[:description].any? assert product.errors[:price].any? assert product.errors[:image_url].any? end end
ユニットテストのみの実行
depot> rake test:units
railsのテストは他にファンクションテスト、インテグレーションテストなどが
存在する。
・ファンクションテスト:モデル、ビュー、コントローラーまでの一連のアクションごとのテスト
・インテグレーションテスト:アクションをまたぐテスト
参照URL:http://railsdoc.com/test
3.価格のテストを追加する
test "product price must be positive" do product = Product.new(title: "My Book Title", description: "yyy", image_url: "zzz.jpg") # 価格が-1の場合,エラー product.price = -1; assert product.invalid? # joinはエラーが複数存在した場合、引数の区切り文字で結合するメソッド assert_equal "must be greater than or equal to 0.01", product.errors[:price].join('; ') # 価格が1の場合,正常 product.price = 1; assert product.valid? end
・priceのアクセス修飾子
publicなんですね。javaだとコンストラクタ以外の設定方法としてはsetterメソッドで値を設定したりしますが。記述としては短くかけるので結局書き換えるならば、この方が自然ということなんでしょうか。
・productモデルクラスのエラー情報
invalid,validなどのメソッド、errorsオブジェクトなどエラーに関する情報もモデルクラスに実装されている。この辺りの実装の必要がないところは楽です。
4.テストフィクスチャ
テスト対象モデルの初期データを指定するもの
test/fixtures以下のファイルで指定。
depot/test/fixtures/products.yml
one: title: MyString description: MyText image_url: MyString price: 9.99 ・・・
Productモデル作成時に上記のファイルが自動生成される。便利。。
このテストデータをrailsにアップロードさせる設定を記述する。
class ProductTest < ActiveSupport::TestCase fixtures :products ・・・
上記の設定を行うと、ProductTestのテストメソッドを実行する前に
productsテーブル内のデータを全削除し、テストデータを読み込むという処理を行う。
5.RailsのDB環境
database.ymlに以下の設定が存在する
db/development.sqlite3 :開発環境用
db/test.sqlite3 :テスト環境用
db/production.sqlite3 :本番環境用
下記コマンドでDBにおけるデータ設定が行われている。
rake test→テストDB初期化後に、フィクスチャを読み込む
rake db:test:prepare →rake testの個別ファイル実行版
6.フィクスチャデータの使用
class ProductTest < ActiveSupport::TestCase fixtures :products ・・・ test "product is not valid without a uniq title" do #products(:ruby)においてフィクスチャにアクセス product = Product.new(title: products(:ruby).title, description: "yyy", price : 1, image_url: "fred.jpg") assert !product.save assert_equal I18n.translate{'activerecord.errors.messages.taken'}, product.errors[:title].join('; ') end end
7章完了。次は商品カタログを作成する。
商品リストの見た目を更にパワーアップさせる。