Railsチュートリアル3章のエラー解決×2
Ruby on Railsチュートリアル 3章でエラーが発生したため、その解決方法を書き残します。
該当箇所は3.3.2節、わざとテストを失敗させるところです。
環境
- ホストOS:Windows 10
- ゲストOS:CentOS 7
- VirtualBoxで動作
- VirtualBoxのフォルダ共有機能を使用
- Vagrantで環境管理
- Ruby on Railsチュートリアル Rails 5.1対応 (第4版)
- rails バージョン5.1.4
エラーメッセージ
長いですが全部貼ります。
このメッセージ、前半と後半でそれぞれ独立のエラーが発生しています。
[vagrant@localhost sample_app]$ rails test
Running via Spring preloader in process 16123
rails aborted!
ActiveRecord::Tasks::DatabaseAlreadyExists: ActiveRecord::Tasks::DatabaseAlreadyExists
/vagrant_data/sample_app/bin/rails:9:in `require'
/vagrant_data/sample_app/bin/rails:9:in `<top (required)>'
/vagrant_data/sample_app/bin/spring:15:in `require'
/vagrant_data/sample_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Caused by:
Errno::ETXTBSY: Text file busy @ apply2files - /vagrant_data/sample_app/db/test.sqlite3
/vagrant_data/sample_app/bin/rails:9:in `require'
/vagrant_data/sample_app/bin/rails:9:in `<top (required)>'
/vagrant_data/sample_app/bin/spring:15:in `require'
/vagrant_data/sample_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:test:load => db:test:purge
(See full trace by running task with --trace)
Run options: --seed 25191
# Running:
Run options: --seed 25191
# Running:
EE
Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x0000561eb6178d08>
test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'
Traceback (most recent call last):
27: from -e:1:in `<main>'
26: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
25: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
24: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application/boot.rb:19:in `<top (required)>'
23: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:135:in `run'
22: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:135:in `loop'
21: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:141:in `block in run'
20: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:171:in `serve'
19: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork'
18: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:63:in `block in autorun'
17: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:136:in `run'
16: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:159:in `__run'
15: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:159:in `map'
14: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:159:in `block in __run'
13: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/line_filtering.rb:9:in `run'
12: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:319:in `run'
11: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:347:in `with_info_handler'
10: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:360:in `on_signal'
9: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:320:in `block in run'
8: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:320:in `each'
7: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:321:in `block (2 levels) in run'
6: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:334:in `run_one_method'
5: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:802:in `record'
4: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:802:in `each'
3: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:803:in `block in record'
2: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/reporter.rb:23:in `record'
1: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/reporter.rb:70:in `format_rerun_snippet'
/home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/reporter.rb:70:in `method': undefined method `test_should_get_about' for class `Minitest::Result' (NameError)
原因1:VirtualBoxの共有フォルダ機能
まず前半のほうです。
ActiveRecord::Tasks::DatabaseAlreadyExists: ActiveRecord::Tasks::DatabaseAlreadyExists /vagrant_data/sample_app/bin/rails:9:in `require' /vagrant_data/sample_app/bin/rails:9:in `<top (required)>' /vagrant_data/sample_app/bin/spring:15:in `require' /vagrant_data/sample_app/bin/spring:15:in `<top (required)>' bin/rails:3:in `load' bin/rails:3:in `<main>' Caused by: Errno::ETXTBSY: Text file busy @ apply2files - /vagrant_data/sample_app/db/test.sqlite3 /vagrant_data/sample_app/bin/rails:9:in `require' /vagrant_data/sample_app/bin/rails:9:in `<top (required)>' /vagrant_data/sample_app/bin/spring:15:in `require' /vagrant_data/sample_app/bin/spring:15:in `<top (required)>' bin/rails:3:in `load' bin/rails:3:in `<main>'
test.sqlite3というファイルがビジーで操作できない、という内容のエラーです。
この問題については以下のページに情報があります。
ruby on rails - Errno::ETXTBSY: Text file busy @ unlink_internal - Stack Overflow
これはVirtualBoxの共有フォルダ内にrailsのプロジェクトを作ってしまった際に発生する問題のようです。
※Vagrantが関連しているかどうかは不明ですが、Vagrantは単にVirtualBoxの共有フォルダ機能を有効にしているだけなので、おそらく関連はないと思います。
問題となっているのはtest.sqlite3、これはデータベースファイルです。プロジェクト作成時のデータベース利用設定では、テスト用のデータベースはプロジェクトディレクトリ内にSQLiteのDBファイルを作るようになっています。これがうまくいっていないようです。
解決策としては、1つはプロジェクトを共有フォルダの外で作ってしまうことです。またはデータベース設定を変更して、共有フォルダの外にデータベースを作るようにしてもよいです。今回は後者の方法を採ります。
データベースの設定はconfig/database.ymlに記述されています。これを以下のように変更します。
# SQLite version 3.x # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default #ついでに変更 #database: db/development.sqlite3 database: /var/rails_db/development.sqlite3 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default #ここを変更 #database: db/test.sqlite3 database: /var/rails_db/test.sqlite3 production: <<: *default #ついでに変更 #database: db/production.sqlite3 database: /var/rails_db/production.sqlite3
場所は/tmp/とかでも良いのですが、/var/rails_db/というディレクトリを作ってそこに入れることにしました。
以下のコマンドでディレクトリを作り、オーナーを作業ユーザに変更します。ユーザ名とグループ名(vagrant:vagrant)はそれぞれの環境によって異なるのでご注意ください。
[vagrant@localhost sample_app]$ sudo mkdir /var/rails_db [vagrant@localhost sample_app]$ sudo chown vagrant:vagrant /var/rails_db
これで前半のエラーは出なくなるはずです。
原因2:minitestとrailsのバージョン相性
次に後半のエラーに対処していきます。
Traceback (most recent call last):
27: from -e:1:in `<main>'
26: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
25: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
24: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application/boot.rb:19:in `<top (required)>'
23: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:135:in `run'
22: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:135:in `loop'
21: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:141:in `block in run'
20: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:171:in `serve'
19: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/spring-2.0.2/lib/spring/application.rb:171:in `fork'
18: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:63:in `block in autorun'
17: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:136:in `run'
16: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:159:in `__run'
15: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:159:in `map'
14: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:159:in `block in __run'
13: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/line_filtering.rb:9:in `run'
12: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:319:in `run'
11: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:347:in `with_info_handler'
10: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:360:in `on_signal'
9: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:320:in `block in run'
8: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:320:in `each'
7: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:321:in `block (2 levels) in run'
6: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:334:in `run_one_method'
5: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:802:in `record'
4: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:802:in `each'
3: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/minitest-5.11.3/lib/minitest.rb:803:in `block in record'
2: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/reporter.rb:23:in `record'
1: from /home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/reporter.rb:70:in `format_rerun_snippet'
/home/vagrant/.anyenv/envs/rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/railties-5.1.4/lib/rails/test_unit/reporter.rb:70:in `method': undefined method `test_should_get_about' for class `Minitest::Result' (NameError)
Minitest::Resultというクラスが期待されているメソッドを持っていない、というエラーです。
この問題について、そのものズバリの記事を書いてくださっている方がいます。
Ruby on Rails チュートリアル3章のテストのバグとその対応メモ
今回railsのバージョン5.1.4を使っているが、テストに使っているgemのminitestは新しいバージョンが入るため、実装が合わずに上手く動いていないようです。
解決策は、Gemfileにminitestのバージョン指定を書き加えることです。
source 'https://rubygems.org' gem 'rails', '5.1.4' gem 'puma', '3.9.1' gem 'sass-rails', '5.0.6' gem 'uglifier', '3.2.0' gem 'coffee-rails', '4.2.2' gem 'jquery-rails', '4.3.1' gem 'turbolinks', '5.0.1' gem 'jbuilder', '2.7.0' group :development, :test do gem 'sqlite3', '1.3.13' gem 'byebug', '9.0.6', platform: :mri end group :development do gem 'web-console', '3.5.1' gem 'listen', '3.1.5' gem 'spring', '2.0.2' gem 'spring-watcher-listen', '2.0.1' end group :test do gem 'rails-controller-testing', '1.0.2' gem 'minitest-reporters', '1.1.14' gem 'guard', '2.13.0' gem 'guard-minitest', '2.4.4' gem 'minitest', '5.10.3' # ここを追加 end group :production do gem 'pg', '0.20.0' end
修正後、以下のコマンドを実行します。
[vagrant@localhost sample_app]$ bundle update [vagrant@localhost sample_app]$ bundle install
結果
以上2つのエラー対策により、正常に「テスト失敗」させることができました。
[vagrant@localhost sample_app]$ rails test
Running via Spring preloader in process 16455
/vagrant_data/sample_app/db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /vagrant_data/sample_app/config/application.rb to limit the frameworks that will be loaded.
Run options: --seed 46335
# Running:
Run options: --seed 46335
# Running:
EE
Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x0000561a90598ed0>
test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'
bin/rails test test/controllers/static_pages_controller_test.rb:14
....
Finished in 1.254642s, 2.3911 runs/s, 1.5941 assertions/s.
1) Error:
StaticPagesControllerTest#test_should_get_about:
NameError: undefined local variable or method `static_pages_about_url' for #<StaticPagesControllerTest:0x0000561a90598ed0>
test/controllers/static_pages_controller_test.rb:15:in `block in <class:StaticPagesControllerTest>'
3 runs, 2 assertions, 0 failures, 1 errors, 0 skips
Finished in 1.299065s, 2.3094 runs/s, 1.5396 assertions/s.
3 runs, 2 assertions, 0 failures, 1 errors, 0 skips