railsでの開発も、さて一段落。というか、いろいろな所に落ちているコードの組合せだけではなく、自分でロジックを作って行く必要がぼちぼちとでてきました。
そこで、必要になるのがテストコード。いつもの様に、チュートリアルを読んでコピペをして「実行」をしたところ偉いことが起きてしまいました。
ActiveRecord::StatementInvalid: PG::UndefinedTable が。。。
testの作り方 in Rails 5.2
modelとかcontrollerとかを rails generate
で作っていたら。。という前提ですが。。
- testフォルダ以下に生成されている model/**_test.rbを開く
- ActiveSupport::TestCase を継承している **Testクラスにテストメソッドを記載する (test "check my hat" do とか。これは def test_check_my_hat doと同値でマクロで定義されているらしい。。)
- コンソール上で、実行したいテストを含む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
で終了です
よくわからないのでテスト環境のデータベースを作って見る
問題の切り分けをするために、「推奨されたやり方」を試みて見ました。
すなわち、テスト用のデータベースを作成して見ます。
意外とやり方がまとまったページが見つからなかったのですが、手順は以下の通り
- データベース上(今回の場合はpostgresql)にユーザー(ロール)を作成する
- スキーマを作成する (ユーザーに管理者権限があるならば、
rails db:create RAILS_ENV=test
により、database.ymlに基づいたスキーマが作成される -
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を返すだけでもいろいろなドラマがあるのですね。。。