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