Help us understand the problem. What is going on with this article?

【動画付き】「プロを目指す人のためのRuby入門」のテストコードをRSpecに書き換える・その1

More than 1 year has passed since last update.

はじめに

僕が執筆したRubyの入門書「プロを目指す人のためのRuby入門」では、Minitestを使って例題の実行結果をテストしています。
ですが、実際の現場ではMinitestではなく、RSpecを使っている場合も多いと思います。

そこで、この記事では「プロを目指す人のためのRuby入門」のテストコードを、筆者自らRSpecに書き換えてみます。

rubybook-mini.jpg

RSpecをまったく知らない方へ

RSpecの基本は詳しく説明しません。RSpecをまったく知らない、という方は、先に以下の記事を読んでからこの記事に戻ってきてください。

使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita
※ただし、「RSpecの高度な機能」の項で説明している知識は今回使いません。

本記事は3部構成になっています

ボリュームが大きいので、本記事は3部構成になっています。
この記事では第3章から第6章までのテストコードをRSpecに書き換えます。

動画とソースコード

この記事の内容は動画(スクリーンキャスト)形式で解説しています。
細かい説明は口頭で話しているので、ぜひ動画もチェックしてください。
(録音状況が悪いため、ときどき大きなノイズが入ります。ごめんなさい🙏)

「プロを目指す人のためのRuby入門」のテストコードをRSpecに書き換える・その1Screen Shot 2018-03-19 at 5.19.53.png

また、ソースコードはこちらにアップしています。

https://github.com/JunichiIto/ruby-book-codes/tree/rspec/ruby-book

対象バージョン

この記事は以下の環境で動作確認しています。

  • Ruby 2.4.1
  • RSpec 3.7.0

それでは以下が本編です。

セットアップ

gemコマンドを使ってRSpecをインストールします。

$ gem install rspec

テストコードを書きたいプロジェクトのルートディレクトリに移動し、rspec --initコマンドを実行すると、RSpecの実行に必要なファイルやディレクトリが作成されます。

$ rspec --init
create   .rspec
create   spec/spec_helper.rb

.rspecspec_helper.rbはRSpecを実行するための設定ファイルですが、今回はデフォルトのまま使うので説明は割愛します。

コンソールからrspecコマンドを実行し、以下のような結果になればセットアップ完了です。

$ rspec
No examples found.


Finished in 0.00038 seconds (files took 0.67611 seconds to load)
0 examples, 0 failures

セットアップ直後にはテストがありませんが、specディレクトリにテストコードがあれば、テストが実行されます。

第3章 FizzBuzzプログラム

Minitest版

test/fizz_buzz_test.rb
require 'minitest/autorun'
require './lib/fizz_buzz'

class FizzBuzzTest < Minitest::Test
  def test_fizz_buzz
    assert_equal '1', fizz_buzz(1)
    assert_equal '2', fizz_buzz(2)
    assert_equal 'Fizz', fizz_buzz(3)
    assert_equal '4', fizz_buzz(4)
    assert_equal 'Buzz', fizz_buzz(5)
    assert_equal 'Fizz', fizz_buzz(6)
    assert_equal 'Fizz Buzz', fizz_buzz(15)
  end
end

RSpec版

spec/fizz_buzz_spec.rb
require './spec/spec_helper'
require './lib/fizz_buzz'

RSpec.describe 'Fizz Buzz' do
  it 'returns valid string' do
    expect(fizz_buzz(1)).to eq '1'
    expect(fizz_buzz(2)).to eq '2'
    expect(fizz_buzz(3)).to eq 'Fizz'
    expect(fizz_buzz(4)).to eq '4'
    expect(fizz_buzz(5)).to eq 'Buzz'
    expect(fizz_buzz(6)).to eq 'Fizz'
    expect(fizz_buzz(15)).to eq 'Fizz Buzz'
  end
end

ポイント

  • 4行目のRSpec.describeでは、テスト対象のプログラムやクラスを記述します。
  • it 'returns valid string' doの部分では、プログラムの期待する振る舞いを記述しています。この場合は「(テスト対象のメソッドが)正しい文字列を返すこと」という内容になっています。
  • 英語が苦手な人はitに渡す文字列を日本語で書いても構いません(例:it '正しい文字列を返すこと' do)。
  • RSpecのexpect(A).to eq Bは、Minitestのassert_equal B, Aに対応します。

第4章 RGB変換プログラム

Minitest版

test/rgb_test.rb
require 'minitest/autorun'
require './lib/rgb'

class RgbTest < Minitest::Test
  def test_to_hex
    assert_equal '#000000', to_hex(0, 0, 0)
    assert_equal '#ffffff', to_hex(255, 255, 255)
    assert_equal '#043c78', to_hex(4, 60, 120)
  end

  def test_to_ints
    assert_equal [0, 0, 0], to_ints('#000000')
    assert_equal [255, 255, 255], to_ints('#ffffff')
    assert_equal [4, 60, 120], to_ints('#043c78')
  end
end

RSpec版

spec/rgb_spec.rb
require './spec/spec_helper'
require './lib/rgb'

RSpec.describe 'RGB' do
  describe '#to_hex' do
    it 'returns valid string' do
      expect(to_hex(0, 0, 0)).to eq '#000000'
      expect(to_hex(255, 255, 255)).to eq '#ffffff'
      expect(to_hex(4, 60, 120)).to eq '#043c78'
    end
  end

  describe '#to_ints' do
    it 'returns valid array' do
      expect(to_ints('#000000')).to eq [0, 0, 0]
      expect(to_ints('#ffffff')).to eq [255, 255, 255]
      expect(to_ints('#043c78')).to eq [4, 60, 120]
    end
  end
end

ポイント

  • describe '#to_hex' dodescribe '#to_ints' doは、それぞれテストのグループ化をしています。前者は「to_hexメソッドをテストするグループ」で、後者は「to_intsメソッドをテストするグループ」です。

第5章 長さの単位変換プログラム

Minitest版

test/convert_length_test.rb
require 'minitest/autorun'
require './lib/convert_length'

class ConvertLengthTest < Minitest::Test
  def test_convert_length
    assert_equal 39.37, convert_length(1, from: :m, to: :in)
    assert_equal 0.38, convert_length(15, from: :in, to: :m)
    assert_equal 10670.73, convert_length(35000, from: :ft, to: :m)
  end
end

RSpec版

spec/convert_length_spec.rb
require './spec/spec_helper'
require './lib/convert_length'

RSpec.describe 'Convert length' do
  it 'returns valid value' do
    expect(convert_length(1, from: :m, to: :in)).to eq 39.37
    expect(convert_length(15, from: :in, to: :m)).to eq 0.38
    expect(convert_length(35000, from: :ft, to: :m)).to eq 10670.73
  end
end

ポイント

(ここでは特に新しいトピックはありません。)

第6章 ハッシュ記法変換プログラム

Minitest版

test/convert_hash_syntax_test.rb
require 'minitest/autorun'
require './lib/convert_hash_syntax'

class ConvertHashSyntaxTest < Minitest::Test
  def test_convert_hash_syntax
    old_syntax = <<~TEXT
      {
        :name => 'Alice',
        :age=>20,
        :gender  =>  :female
      }
    TEXT
    expected = <<~TEXT
      {
        name: 'Alice',
        age: 20,
        gender: :female
      }
    TEXT
    assert_equal expected, convert_hash_syntax(old_syntax)
  end
end

RSpec版(letを使わない場合)

spec/convert_hash_syntax_spec.rb
require './spec/spec_helper'
require './lib/convert_hash_syntax'

RSpec.describe 'Convert hash syntax' do
  it 'converts old syntax to new syntax' do
    old_syntax = <<~TEXT
      {
        :name => 'Alice',
        :age=>20,
        :gender  =>  :female
      }
    TEXT
    expected = <<~TEXT
      {
        name: 'Alice',
        age: 20,
        gender: :female
      }
    TEXT
    expect(convert_hash_syntax(old_syntax)).to eq expected
  end
end

RSpec版(letを使う場合)

spec/convert_hash_syntax_spec.rb
require './spec/spec_helper'
require './lib/convert_hash_syntax'

RSpec.describe 'Convert hash syntax' do
  let(:old_syntax) do
    <<~TEXT
      {
        :name => 'Alice',
        :age=>20,
        :gender  =>  :female
      }
    TEXT
  end
  let(:expected) do
    <<~TEXT
      {
        name: 'Alice',
        age: 20,
        gender: :female
      }
    TEXT
  end
  it 'converts old syntax to new syntax' do
    expect(convert_hash_syntax(old_syntax)).to eq expected
  end
end

ポイント

  • RSpecではテストコード内に登場するローカル変数やインスタンス変数を、letと呼ばれるコードブロックに移動させることができます。
  • ここではit 'xxx' do ... endの中身をスッキリさせるために、letを使いました。
  • letについては前述の「使えるRSpec入門・その1」でも説明しているので、そちらの説明も参考にしてください。

まとめ

この記事では「プロを目指す人のためのRuby入門」の第2章から第6章までのテストコードをRSpecに書き換えました。
第7章以降のテストコードは第2回、および第3回の記事で書き換えていきます。

jnchito
SIer、社内SEを経て、ソニックガーデンに合流したプログラマ。 「プロを目指す人のためのRuby入門」の著者。 http://gihyo.jp/book/2017/978-4-7741-9397-7 および「Everyday Rails - RSpecによるRailsテスト入門」の翻訳者。 https://leanpub.com/everydayrailsrspec-jp
https://blog.jnito.com/
sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業
http://www.sonicgarden.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした