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

気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

書籍「Railsによるアジャイル Webアプリケーション開発」7章

Rails Ruby

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


7.2 イテレーションB2 : モデルのユニットテスト


ユニットテストの書き方

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章完了。次は商品カタログを作成する。
商品リストの見た目を更にパワーアップさせる。