RSpec
WEB+DB PRESS vol.61 の特集記事を見つつ色々ヤッてみます。とりあえず環境の確認から。
$ ruby -v ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux] $ gem -v 1.8.8 $ rails -v Rails 3.0.9 $
とりあえず sqlite3 を入れます。
$ sudo apt-get install sqlite3
で、rails のアプリを作るのか。
以下らしい。
$ rails new webpress61_blog -T
出力多いですな。ちなみに -T は Test::Unit なナニを組込まないオプションとのこと。次に Gemfile に以下を追加とのこと。
group :development, :test do gem "rspec", "2.4.0" gem "rspec-rails", "2.4.1" end
で、bundle install すれば良いらしい。便利な世の中になったものです。
$ bundle install Fetching source index for http://rubygems.org/ Using rake (0.9.2) Using abstract (1.0.0) Using activesupport (3.0.9) Using builder (2.1.2) Using i18n (0.5.0) Using activemodel (3.0.9) Using erubis (2.6.6) Using rack (1.2.3) Using rack-mount (0.6.14) Using rack-test (0.5.7) Using tzinfo (0.3.29) Using actionpack (3.0.9) Using mime-types (1.16) Using polyglot (0.3.2) Using treetop (1.4.10) Using mail (2.2.19) Using actionmailer (3.0.9) Using arel (2.0.10) Using activerecord (3.0.9) Using activeresource (3.0.9) Using bundler (1.0.15) Installing diff-lcs (1.1.3) Installing rdoc (3.9.4) Using thor (0.14.6) Using railties (3.0.9) Using rails (3.0.9) Installing rspec-core (2.4.0) Installing rspec-expectations (2.4.0) Installing rspec-mocks (2.4.0) Installing rspec (2.4.0) Installing rspec-rails (2.4.1) Using sqlite3 (1.3.4) Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed. $
で、以下なおまじないを最初の一発めに、ということらしい。
$ rails generate rspec:install create .rspec create spec create spec/spec_helper.rb $
とりあえず RSpec の第一歩の手前まできたのか。
モデルのテストを書いてみよう
まず、モデルを作成する模様。
$ rails generate model article title:string body:text invoke active_record create db/migrate/20110902125048_create_articles.rb create app/models/article.rb invoke rspec create spec/models/article_spec.rb $ || む、spec 配下も自動生成な模様。で、db を作るのか。あまり何も考えてなかったのですが、config/database.yml は以下らしい。 >|| # SQLite version 3.x # gem install sqlite3 development: adapter: sqlite3 database: db/development.sqlite3 pool: 5 timeout: 5000 # 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: adapter: sqlite3 database: db/test.sqlite3 pool: 5 timeout: 5000 production: adapter: sqlite3 database: db/production.sqlite3 pool: 5 timeout: 5000
自動か。凄いな。とりあえず rake db:migrate せよ、との記述あり。
$ rake db:migrate == CreateArticles: migrating ================================================= -- create_table(:articles) -> 0.0028s == CreateArticles: migrated (0.0029s) ======================================== $
なんだか数年前の良い思い出がよみがえってくるようだ。とりあえず spec/models/articles_spec.rb を以下にせよ、とのこと。
ちょっと見栄を張って英語にしてたりして。
require 'spec_helper' describe Article do context "case of specifying a title and body" do before do @article = Article.new(:title => "first blog", :body => "This is first post." ) end it "Must be set title" do @article.title.should == "first blog" end it "Must be set body" do @article.body.should == "This is first post." end end end
で、試験実行してみたら通らん。
$ bundle exec rspec spec/models/article_spec.rb FF Failures: 1) Article case of specifying a title and body Must be set title Failure/Error: @article = Article.new(:title => "first blog", ActiveRecord::StatementInvalid: Could not find table 'articles' # ./spec/models/article_spec.rb:6:in `new' # ./spec/models/article_spec.rb:6:in `block (3 levels) in <top (required)>' 2) Article case of specifying a title and body Must be set body Failure/Error: @article = Article.new(:title => "first blog", ActiveRecord::StatementInvalid: Could not find table 'articles' # ./spec/models/article_spec.rb:6:in `new' # ./spec/models/article_spec.rb:6:in `block (3 levels) in <top (required)>' Finished in 0.09132 seconds 2 examples, 2 failures $
テーブル無いし、とか出力されてるし。db/development.sqlite3 の中を見たら
sqlite> .schema CREATE TABLE "articles" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar(255), "body" text, "created_at" datetime, "updated_at" datetime); CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL); CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version"); sqlite>
とのこと。これって RAILS_ENV だったかが微妙なのかな。しかも git で云々してないことに今更気づいておりますorz
で、色々探して以下を発見。
$ find |xargs grep RAILS_ENV ./spec/spec_helper.rb:ENV["RAILS_ENV"] ||= 'test' $
変えましょうね。で、リトライ。
$ bundle exec rspec spec/models/article_spec.rb .. Finished in 0.19687 seconds 2 examples, 0 failures $
やれやれ。あるいは出力が以下で変わるらしい。
$ bundle exec rspec spec/models/article_spec.rb -f d Article case of specifying a title and body Must be set title Must be set body Finished in 0.35993 seconds 2 examples, 0 failures $
次、validation の試験を書くらしい。title 属性が必須項目である試験は以下とのこと。
context "case of not specifying a title" do before do @article = Article.new end it { @article.should_not be_valid } end
これは失敗しますな。
$ bundle exec rspec spec/models/article_spec.rb -f d Article case of specifying a title and body Must be set title Must be set body case of not specifying a title should not be valid (FAILED - 1) Failures: 1) Article case of not specifying a title Failure/Error: it { @article.should_not be_valid } expected valid? to return false, got true # ./spec/models/article_spec.rb:21:in `block (3 levels) in <top (required)>' Finished in 0.28405 seconds 3 examples, 1 failure $
あるいは必須項目な確認の記述があります。こうしたら title 属性が必須になるらしい。app/models/article.rb です。
class Article < ActiveRecord::Base validates_presence_of :title end
これで再度試験をしてみます。
$ bundle exec rspec spec/models/article_spec.rb -f d Article case of specifying a title and body Must be set title Must be set body case of not specifying a title should not be valid Finished in 0.29035 seconds 3 examples, 0 failures $
をー、通りましたな。
で、最後の正常系の試験を追加するらしい。
context "case of specifying a title" do before do @article = Article.new(:title => "first blog") end it { @article.should be_valid } end
なんか格好良いですね。試験実行。
$ bundle exec rspec spec/models/article_spec.rb -f d Article case of specifying a title and body Must be set title Must be set body case of not specifying a title should not be valid case of specifying a title should be valid Finished in 0.14967 seconds 4 examples, 0 failures $
試験ドリブン大好きです。英語は間違ってるはずですが気持ち良い。
続きは明日の朝にします。