ユニットテストコードの実装
ここからは、「実際に動作するコードがあると想定して、そのコードが正しく利用できることを確認するためのコード」、すなわちテストコードを書いていきます。
ここでは、先ほど検討したUserとHitokotoの関連が実装できたと想定して、それぞれのクラスから、関連するクラスを取得するためのテストコードを書いてみましょう。
なお、今回実装する本番コードは、Ruby on Railsのアソシエーション機能を利用するだけのシンプルなものですので、テストコードを書くまでもないと感じられるかもしれません。しかし、本稿では実際のテストコード実装を含めた開発イテレーションを紹介するために、あえてテストコードを実装し、テスト実行の過程を追っていきます。
ユニットテストコードは[Railsエクスプローラー]のtsubuyakiプロジェクト以下、[テスト]−[ユニットテスト]以下に書いていきます。まずは、[ユニットテスト]以下のUserをダブルクリックし、編集エリアにuser_test.rbを表示します。user_test.rb には、以下のようなユニットテストコードを記述します。<
require 'test_helper' class UserTest < ActiveSupport::TestCase test "Userに属すHitokotoを取得できる" do u = User.find(1) assert u.hitokotos == Hitokoto.find_all_by_user_id(1) end end
ユニットテストコードは、ActiveSupport::TestCaseを継承したクラスへ記述します(テストコードはテストケースとも呼ばれます)。ActiveSupport::TestCaseでは、各テストを定義するためのクラスメソッドtestが定義されています。上記のテストコードは、指定したUserから関連するHitokotoインスタンスを取得するための検証コードです。
testメソッドの使用方法について、もう少し確認しておきましょう。testメソッドへの引数には任意の文字列を指定できます。この文字列はテスト実行時に、個々のテストの成功/失敗情報とともに表示されますので、テストの内容を端的に表現した文字列を指定するといいでしょう。ここでは、上記のとおり「Userに属すHitokotoを取得できる」と指定します。
続いて、メソッドへ渡すブロックの中身を見ていきましょう。「u = User.find(1)」の行では、フィクスチャで登録したid=1のユーザーを取得し、変数へ代入しています。
次の行で使用されているassertメソッドは、「引数として渡された式の評価結果がtrueであるかどうかを確認する」ためのメソッドです。ここでは、id=1のUserに属するHitokotoをu.hitokotosという名前で抽出し、これらがデータベースからuser_id=1の検索条件で抽出されるHitokotoインスタンスの配列と同等であることを確認しようとしています。
Userクラスのユニットテストが実装できたら、次はHitokotoクラスのユニットテストを実装していきます。先ほど同様、[Railsエクスプローラー]ビューの[ユニットテスト]以下、Hitokotoをダブルクリックし、hitokoto_test.rbを編集エリアに表示します。hitokoto_test.rbには、以下のテストコードを実装します。
require 'test_helper' class HitokotoTest < ActiveSupport::TestCase test "Hitokotoが属すUserを取得できる" do h = Hitokoto.find(1) assert h.user == User.find(1) end end
このテストコードは、ほとんどUserクラスのユニットテストと同じですが、こちらではHitokotoに関連するUserをh.userという名前で抽出しようとしています。つまり、先ほどとは逆の方向での関連が解決できるか、を確認するためのコードです。
テスト用データベースの準備
テストを実行する際は、開発用のデータベースとは別に、テストに使用するデータベースを準備し、ここまで実行したデータベーススキーマの更新(マイグレーション)を行っておく必要があります。
少し面倒にも思えるかもしれませんが、実際の作業は3rdRailのプロジェクトコマンダーでコマンドを実行するだけです。
3rdRailのメニューから[ウィンドウ]−[プロジェクトコマンダー]−[最後または新規のコマンダーを表示]の順にクリックし、ウィンドウ下のコンソールタブにプロジェクトコマンダーを起動します。プロジェクトコマンダーに以下のコマンドを入力し、テスト用データベースを準備しましょう。
> rake db:test:prepare
以上で、テスト用データベースの準備は完了です。
ユニットテストを実行してみよう
3rdRailはユニットテストの実行結果をビジュアルで表示するための[スクリプト・テスト]ビューを搭載しています。このビューを使用すると、テストの進行状況やエラー発生時のスタックトレース、テスト結果を分かりやすく確認できます。
[Railsエクスプローラー]ビューの[ユニットテスト]を右クリックし、[実行]−[Rubyテスト]をクリックしましょう。[スクリプト・テスト]ビューに切り替わり、作成したテストが実行されます。
上記のような表示になっているでしょうか。[スクリプトテスト]ビューの上部に表示されている進捗バーが赤で表示されていることが確認できると思います。このバーが赤表示となっているときは、何らかのテストに失敗したことを表しています。
現時点では、所期の関連を解決するためのコードを書いていませんので、テストは2件とも失敗するはずです。[スクリプト・テスト]ビューのUserTestを開き、「test_Userに属すHitokotoを取得できる」をクリックしてみましょう。障害トレースのログに、テストがどのように失敗したかというメッセージが表示されます。ここでは、以下のメッセージが表示されていることを確認してください。
undefined method `hitokotos' for #<User:0x20726a8> /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/attribute_methods.rb:260:in `method_missing' /Users/tmtysk/Documents/3rdRail/workspace/tsubuyaki/test/unit/user_test.rb:17:in `test_Userに属すHitokotoを取得できる' :(以下略)
どうやら、先ほどのテストコードで記述した以下の行、
assert u.hitokotos == Hitokoto.find_all_by_user_id(1)
のUser#hitokotosというメソッド名が解決できないためテストが失敗したようです。同様に、HitokotoTestでもHitokoto#userというメソッド名が解決できないというトレースが出ていることも確認しておきましょう。
さて、テストは失敗しましたが、これは想定どおりです。以降、このテストが成功するように本番コードを実装していけばよいということになります。
3/4 |
Index | |
「つぶやき」アプリを改修してみよう(前編) | |
Page1 追加するModel候補を洗い出してみよう 新しいModelクラスのアソシエーション(関連)を検討しよう Modelクラスの改修と追加作業の流れ |
|
Page2 複数ユーザーによる「ひとこと」を可能にする Modelのテストを実装しよう テスト用サンプル「フィクスチャ」の準備 |
|
Page3 ユニットテストコードの実装 テスト用データベースの準備 ユニットテストを実行してみよう |
|
Page4 Modelの本番コードを実装しよう ユニットテストの再実行 |
3rdRailによるRailsプログラミング入門 |
Ruby/Rails関連記事 |
プログラミングは人生だ まつもと ゆきひろのコーディング天国 ときにプログラミングはスポーツであり、ときにプログラミングは創造である。楽しいプログラミングは人生をより実りあるものにしてくれる |
|
生産性を向上させるRuby向け統合開発環境カタログ Ruby on Rails 2.0も強力サポート 生産性が高いと評判のプログラミング言語「Ruby」。統合開発環境を整えることで、さらに効率的なプログラミングが可能になる |
|
かんたんAjax開発をするためのRailsの基礎知識 Ruby on RailsのRJSでかんたんAjax開発(前編) 実はAjaxアプリケーション開発はあなたが思うよりも簡単です。まずはRuby on Railsの基礎知識から学びましょう |
|
Praggerとnetpbmで作る画像→AA変換ツール Rubyを使って何か面白いものを作ってみよう! 一般的な画像をアスキーアートに変換するツールを作ってみる。さらに出力にバリエーションを持たせてみよう |
|
コードリーディングを始めよう Railsコードリーディング〜scaffoldのその先へ〜(1) 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|