/var/log/messages

debugging with sixth sense

Everyday Rails - Rspec による Rails テスト入門

昨晩、Ust にて勉強会が開催されてました。電子書籍も手元にあるしってことで中身を確認しつつ手も動かしてみる方向で考えてます。

ということで

諸々の件にてぶち切れ気味なのでヤケクソ半分で着手。とりあえず 01_untested な branch から branch 作成。

Gemfile に以下を追加しました。

group :development, :test do
  gem "rspec-rails", "~> 2.14.0"
  gem "factory_girls_rails", "~> 4.2.1"
end

group :test do
  gem "faker", "~> 1.1.2"
  gem "capybara", "~> 2.1.0"
  gem "database_cleaner", "~> 1.0.1"
  gem "launchy", "~> 2.3.0"
  gem "selenium-webdriver", "~> 2.39.0"
end

あとはテストな DB を云々、とありますね。中身を見てみるに sqlite3 でテキストにある通りの記述でした。スルーします。データベース作成しとけ、とありますね。つうかその前に以下。

$ bundle install

と思ったら ruby 2.0.0 が前提らしいな。

$ cat .ruby-version
2.0.0

あら、2.0.0 ですね。

$ ruby --version
ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]

今、出てるのは以下な不具合です。bundle instlal できない。

$ bundle install
rbenv: version `2.0.0' is not installed

rbenv global な出力が以下なので

$ rbenv global
2.0.0-p353

.ruby-version も同じ中身にしたら動きました。bundle install は済んだのでデータベースの準備ということで以下。

$ bundle exec rake db:create:all

つうか今って 3 系な Railstutorial で出てた不具合は問題なくなっているのかどうか。と思ったら以下なメセジが出てたので控えとこ。

Post-install message from capybara:
IMPORTANT! Some of the defaults have changed in Capybara 2.1. If you're experiencing failures,
please revert to the old behaviour by setting:

    Capybara.configure do |config|
      config.match = :one
      config.exact_options = true
      config.ignore_hidden_elements = true
      config.visible_text_only = true
    end

If you're migrating from Capybara 1.x, try:

    Capybara.configure do |config|
      config.match = :prefer_exact
      config.ignore_hidden_elements = false
    end

Details here: http://www.elabs.se/blog/60-introducing-capybara-2-1

Post-install message from twitter-bootstrap-rails:
Important: You may need to add a javascript runtime to your Gemfile in order for bootstrap's LESS files to compile to CSS. 

**********************************************

ExecJS supports these runtimes:

therubyracer - Google V8 embedded within Ruby

therubyrhino - Mozilla Rhino embedded within JRuby

Node.js

Apple JavaScriptCore - Included with Mac OS X

Microsoft Windows Script Host (JScript)

**********************************************

therubyracer が無いと云々、みたいな不具合だった記憶あり。とりあえずここではスルーします。

rake aborted!

rake aborted!
Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes.

出たので以下を有効にして bundle install したら db:create:all な rake は正常終了している模様。

# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

次。config/application.rb に不要な spec を作成しないおまじない。

module ContactsExample40
  class Application < Rails::Application
    config.generators do |g|
      g.test_framework :rspec,
        fixtures: true,
        view_specs: false,
        helper_specs: false,
        routing_specs: false,
        controller_specs: true,
        request_specs: false
      g.fixture_replacement :factory_girl, dir: "spec/factories"
    end
  end
end

あと、以下を忘れるな、とのこと。

$ bundle exec rake db:test:clone

db:migrate とかってした後に忘れがち、とのこと。これで試験が実行できる模様。

と思ったら

いっちゃん大事な準備をスルーしてました (滝汗

$ bundle exec rails generate rspec:install

これで以下か。

$ bundle exec rspec
No examples found.


Finished in 0.00008 seconds
0 examples, 0 failures

ここで一旦 commit 作っておく。

$ git add --all
$ git commit -m '2.setup'

3.モデルスペック

spec/models を掘って contact_spec.rb を新規に作って以下としてます。

require 'spec_helper'

describe Contact do
  it "is valid with a firstname, lastname and email"

  it "is invalid without a firstname"

  it "is invalid without a lastname"

  it "is invalid without an email address"

  it "is invalid with a duplicate email address"

  it "returns a contact's full name as a string"
end

実行してみます。

$ bundle exec rspec

あら、PendingMigrationError が出ましたね。

$ bundle exec rake db:migrate

して

$ bundle exec rake db:test:clone

してリトライ。

$ bundle exec rspec
******

Pending:
  Contact is invalid without an email address
    # Not yet implemented
    # ./spec/models/contact_spec.rb:10
  Contact is valid with a firstname, lastname and email
    # Not yet implemented
    # ./spec/models/contact_spec.rb:4
  Contact is invalid without a lastname
    # Not yet implemented
    # ./spec/models/contact_spec.rb:8
  Contact is invalid without a firstname
    # Not yet implemented
    # ./spec/models/contact_spec.rb:6
  Contact is invalid with a duplicate email address
    # Not yet implemented
    # ./spec/models/contact_spec.rb:12
  Contact returns a contact's full name as a string
    # Not yet implemented
    # ./spec/models/contact_spec.rb:14

Finished in 0.00196 seconds
6 examples, 0 failures, 6 pending

Randomized with seed 2578

expect を使いなさい、とあります。最初の試験が以下とのこと。

  it "is valid with a firstname, lastname and email" do
    contact = Contact.new(
      firstname: 'Aaron',
      lastname: 'Summer',
      email: 'tester@example.com')
    expect(contact).to be_valid
  end

実行してみると試験いっこパス。

$ bundle exec rspec
.*****

validation の試験は以下とのこと。

  it "is invalid without a firstname" do
    expect(Contact.new(firstname: nil)).to have(1).errors_on(:firstname)
  end

to の逆は to_not とのこと。同じ形で他の validation の試験も追加。つうか

it "returns a contact's full name as a string"

という状態で pending というのは良いですね。あとログはスルーしますが、phone なモデルの試験も面白い。以下自分メモを列挙。

  • 等値の expectation は == より eq 使う方が良い
  • 使った matcher は be_valid、eq および include
  • Github にある rspec-expectations リポジトリの README 見てみなさいとのこと

DRY 化

このあたり、昨晩の勉強会で云々してたあたりなのかどうか。まず、Contact.by_letter な試験を云々なのか。確かに Contact なインスタンス作るあたり、冗長。

属性に、というのも昨晩話してましたね。

  describe "filter last name by letter" do
    before :each do
      @smith = Contact.create(firstname: 'John', lastname: 'Smith',
                              email: 'jsmith@example.com')
      @jones = Contact.create(firstname: 'Tim', lastname: 'Jones',
                              email: 'tjones@example.com')
      @johnson = Contact.create(firstname: 'John', lastname: 'Johnson',
                                email: 'jjohnson@example.com')
    end

む、.rspec に以下を追加するのを忘れてました。

--format documentation

出力が以下。

$ bundle exec rspec

Contact
  is valid with a firstname, lastname and email
  is invalid with a duplicate email address
  is invalid without a firstname
  is invalid without an email address
  is invalid without a lastname
  returns a contact's full name as a string
  filter last name by letter
    matching letters
      returns a sorted array of results that match
    non-matching letters
      returns a sorted array of results that match

Phone
  does not allow duplicate phone numbers per contact
  allows two contacts to share a phone number

Finished in 0.40031 seconds
10 examples, 0 failures

Randomized with seed 30552

ええと Q&A にも describe とか context の話が出てますね。このあたり、昨晩の勉強会でもいくつか云々な話が出ていたと記憶しています。

色々参考になるので

こちらをがっと確認してみてから espresso 方面を、と思っていたり。他にもヤること満載なんですがもう少し集中できんかな。

Comments