【Ruby】miniテストのエラー
FJORD BOOT CAMP(フィヨルドブートキャンプ)の課題で実装しているボーリングスコア計算プログラムのテストでエラーが出たので原因をアウトプットしていきます。
エラー
- ボーリングスコア計算プログラムのテストを実行すると下記のエラーが出た
bowling_object.rb:68:in `pinfalls': undefined method `split' for nil:NilClass (NoMethodError)
「splitメソッドのクラスがnilのため見つかりません。」と解釈、しかしクラスは定義しているはず...なぜ?と思いつつ起点を調べる
- テストの起点は下記のコード
from bowling_object_test.rb:3:in `<main>'
- 上記のコードはrequire して
bowling_object.rb
を読み込む部分。このときにエラーが発生していることがわかる
require './bowling_object'
- ちなみに
bowling_object.rb
のファイルの中身は、こんな感じ
# frozen_string_literal: true class Game ... end class Frame ... end class Shot ... end puts Game.new(ARGV[0]).calculate_score
原因/改善
- 上記のコードでは、最後の
puts Game.new(ARGV[0]).calculate_score
がrequireしただけで実行されてしまう。つまりARGVが何もない状態で実行されてしまうため、最終的にエラーが発生してしまう。テストを書く際にrequireしたいことを考えると、puts Game.new(ARGV[0]).calculate_score
はこのファイル自体をrubyコマンドとして実行したときだけ走って欲しい。そんなときは以下のように書く
if __FILE__ == $PROGRAM_NAME puts Game.new(ARGV[0]).calculate_score end
__FILE__:現在のファイルの名前を含むマジック変数。rubyは__FILE__を使用して現在のソースファイル名を保持する
$PROGRAM_NAME:変数名の先頭に$を付けると、グローバル変数を示す。変数名には実行中のスクリプトの名前が含まれる。PROGRAM_NAMEは、プログラムの名前を文字列で返す定数
そもそもテストコードはクラスのメソッドをテストするだけなので、ファイルを分けるとエラーは起きないということも学んだ。クラスを使ってコードを書く時は、クラスごとにファイルを分けることが重要!