LoginSignup
15
9

More than 5 years have passed since last update.

rails test ではまった話。テスト環境のデータベース構築について

Posted at

railsでの開発も、さて一段落。というか、いろいろな所に落ちているコードの組合せだけではなく、自分でロジックを作って行く必要がぼちぼちとでてきました。

そこで、必要になるのがテストコード。いつもの様に、チュートリアルを読んでコピペをして「実行」をしたところ偉いことが起きてしまいました。

ActiveRecord::StatementInvalid: PG::UndefinedTable が。。。

testの作り方 in Rails 5.2

modelとかcontrollerとかを rails generate で作っていたら。。という前提ですが。。

  1. testフォルダ以下に生成されている model/**_test.rbを開く
  2. ActiveSupport::TestCase を継承している **Testクラスにテストメソッドを記載する (test "check my hat" do とか。これは def test_check_my_hat doと同値でマクロで定義されているらしい。。)
  3. コンソール上で、実行したいテストを含むrbファイルを実行する
    • rails test test/model/**_test.rb

以上。3のテストメソッドの中に assert ** と色々と評価する式を書いてあげるとそのtrue/falseが結果として集計されます

今回書いたテストはこちら

    test "check my hat" do
        assert true
    end

ただ、「成功」を返すだけのものです

で起きたエラーは以下

Error:
HatTest#test_check_my_hat:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "adresses" does not exist
LINE 8:                WHERE a.attrelid = '"adresses"'::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
                     c.collname, col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a
                LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                LEFT JOIN pg_type t ON a.atttypid = t.oid
                LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
               WHERE a.attrelid = '"adresses"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum

さて今更テストの環境を確認してみる

どこのデータベースが利用されるのか?

テーブルがないとかrelationがないとか言われているので、データベースが壊れているのかなと推測したわけです。

testでは RAILS_ENV=testが利用される

config/environments/以下の test.rb
config/database.yml の記載を確認

手抜きをしたいがために、developmentとtestのデータベースを同じにしていたのがいけないのか?
でも、ちょっと動かしただけで盛大にエラーが出るのはなぜ?

dbconsoleにつないでみる

`rails dbconsole -e test' を実行
Passwordを聞かれたので、「上手く値がdatabase.ymlから取得出来ない?」とか思ったけど、これは正常の動作ですね。。。

vagrant@vagrant:/var/www/html/skillconnect$ rails dbconsole -e test
/home/vagrant/.rbenv/versions/2.4.4/bin/ruby: warning: shebang line ends with \r may cause a problem
Password:
psql (10.4 (Ubuntu 10.4-2.pgdg16.04+1))
Type "help" for help.

skillconnect=>

postgresのコンソールが動きました。
これは上手く動いています。
久々だったので、終了方法を忘れていましたが、\qで終了です

よくわからないのでテスト環境のデータベースを作って見る

問題の切り分けをするために、「推奨されたやり方」を試みて見ました。

すなわち、テスト用のデータベースを作成して見ます。

意外とやり方がまとまったページが見つからなかったのですが、手順は以下の通り

  1. データベース上(今回の場合はpostgresql)にユーザー(ロール)を作成する
  2. スキーマを作成する (ユーザーに管理者権限があるならば、rails db:create RAILS_ENV=test により、database.ymlに基づいたスキーマが作成される
  3. rails db:reset RAILS_ENV=test により、db:migrateとdb:seedをまとめて行う。個々に行う場合は rails db:migrate RAILS_ENV=test rails db:seed RAILS_ENV=test で行う (resetは実際にはスキーマのdropとcreateが行われるので、実はdb:createもいらないかも。。)

それでも、エラーは解消されない・・・

原因は

エラーメッセージをよく見ると relation "adress" does not existとなっていた。
こいつは、昔作ったものの、綴りが間違えているので、モデルを作り直したことを思い出す。
当然、現在は adressというrelationは存在しない。

fixtures/adress.yml でした。。

rails generate modelでは test/model以下の _test.rbの他に、fixtures/.ymlも自動生成されていたのでした。
モデルを作り直したとき、app/model/adress.rb はファイル名を直接書き換えてしまったのですが、実は悪さしていたのはそのadress.yml。

rails testの本体?である、test/test_helper.rbを見ると(多分デフォルトの状態)

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
end

とfixturesが自動で読み込まれるとのこと。
このfixturesはモデルに対してテストデータを作成するファイルですね。

adress.ymlファイルが存在して、デフォルトのテストデータも残っていたため、丁寧にもそのデータを 'adresses'テーブルに突っ込むことを試みていたのでした。

それが、ActiveRecord::StatementInvalid: PG::UndefinedTable の正体でした。。

assert trueを返すだけでもいろいろなドラマがあるのですね。。。

15
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
9