Rspec入門。テストコードを書く意義とインストールの仕方
突然ですがみなさんテストコード書いておりますでしょうか?
残念ながら、まだまだテストコードのない現場というのが多くあるのですが、これからプログラミングを始める人にはぜひとも身につけて欲しいスキルです。
とはいえ、最初プログラミングを始める時点では優先度高くなく、最初のうちはガンガンプロダクトのコードを書くのでよいです。晴れてエンジニアとして就職したり、ある程度独学で力が付いてきた時などにぜひとも身につけておいて欲しいスキルになります。
テストコードを書く習慣が付いてくると自分のコードを見直す時間ができたり、コードのインターフェースを意識して、モジュールを小さく保つコードをかけるようになるのでぜひとも初級者から中級者に上がるために是非とも身につけたいスキルです。
なぜテストコードを書くのか?
- プロダクトのコードの品質を保証するため
- きれいなコードを保つため
- 短期間での「実装」「振り返り」「改善」を可能にするため
テストコードを書くまず一番の理由は品質の担保のためです。これはすでにわかりきっていることではあるのですがプロダクトのコードのカバレッジ(テストコードの網羅率です)が一定割合(80%程度)以上であれば、変数やメソッドが定義されていないことで起きるバグがデプロイされることを防げる可能性が高いです。
複雑なロジックをテストする意味でテストコードを書くのも十分有効ではありますが、デプロイ前にテストを回して、自動デプロイを行う運用が主流になっている最近の開発現場ではundefined methodの様な軽微なミスによるエラーを防ぐという部分の効果がでかいです。
次に、テストコードを書くことによってコードがきれいに保たれます。先にテストコードを書くと決めることによってテストしやすいコードを書くことになり、コードがきれいに保たれます。テストコードを書いたことがない人、書く習慣がない人などだと不要に長いメソッドを定義してしまいがちです。一メソッドの長さが50 ~ 100行あるような長いメソッドを定義してしまうとどうしても単体テストがやりづらくなって品質の担保ができません。
一方、あらかじめテストコードを書く習慣ができている人だとこのような長いメソッドも適切に分割して単体テストを書きやすいコードを書くことができます。メソッドを適切に分割していると一メソッドで一つのことしかしていないので理解しやすい単位でメソッドが切り出されるので読みやすく綺麗なコードができあがります。
三つ目は、通常の業務ではコードを書いて納品(デプロイ)してというサイクルがありますが、実装とデプロイの間にテストコードを書く時間が生まれることで、一通り機能を実装したあとに自分の実装を見直す時間ができます。この「コードを見直す時間」が個人的にあまり言われていないテストコードを書くメリットになると思っているのですが、テストコードを書くことで「実装」「見直し」のサイクルが短期間で回すことができます。
テストコードを書かないでいると数ヶ月あとにどういう気持ちで書いたかも忘れたあとに同じ箇所の改修かバグ修正で自分のコードにぶち当たり反省するということも多いです。実装を終えた後すぐに見返す時間を作ることで、次の実装では反省を生かした実装ができます。
テストを書かない場合はこの「実装」「振り返り」「反省を生かした実装」のスパンが数ヶ月に及んでしまいますが、テストコードを書けばこれが数週間以内に収められます。
Rspecのインストール
話は変わりますが、多くのRailsプロジェクトで利用されているテストフレームワークのRspecを導入していきます。インストールの流れは以下になります。
- bundlerでrspecのgemをインストール
- テストコードを配置するディレクトリを作成
- テストコードを実際に作成。実行。
rspecのgemインストール
gem install rspec
テストコードを配置するディレクトリを作成
テストコード用のディレクトリは、rspecのコマンドで作成することができます。rspec --init
テストコードを実際に作成
インストールが終わったので実際にモデルのテストコードを書いていきます。モデルは以下のようなBlogモデルを使用し、Blogモデルのtruncated_contentというblogのcontentを指定した文字数で切り捨てて返すメソッドをテストしていきます。app/models/blog.rb
class Blog < ApplicationRecord
belongs_to :category
has_many :reviews
has_many :review_items, through: :reviews
has_many :review_item_masters, through: :review_items
validates :content, length: { maximum: 140 }
def truncated_content(length: 30, omission: '...')
content.truncate(length, omission: omission)
end
end
テストコードはspec/models/blog_spec.rbに書いていきます。
app/models/blog.rb
require 'rails_helper'
RSpec.describe Blog, type: :model do
describe '#truncated_content' do
let(:dummy_content) { <<-'EOF'
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。
EOF
}
let(:blog) { described_class.create(title: 'test', content: dummy_content.strip) }
subject { blog.truncated_content }
context 'with no arguments' do
it '30文字で切り捨てられること' do
expect(subject.length).to eq(30)
end
end
context 'with length arguments' do
let(:length) { 10 }
subject { blog.truncated_content(length: length) }
it '10文字で切り捨てられること' do
expect(subject.length).to eq(length)
end
end
context 'with omission arguments' do
let(:omission) { '・・・'}
subject { blog.truncated_content(omission: omission) }
it '末尾が指定された文字で終わること' do
expect(subject[-3..-1]).to eq(omission)
end
end
end
end
今回細かいコードの説明はしませんが、describeというブロックでテストするメソッドを囲って、それぞれのテストケースはitというメソッドで囲った部分になります。
実際にテストする場合は,下記の様にrspecでファイルを指定して実行します。(全てのファイルを実行したい場合はファイルを指定しません。)
rspec spec/models/blog_spec.rb
...
Finished in 0.44559 seconds (files took 2.16 seconds to load)
3 examples, 0 failures
結果 3examples, 0 failuresとなっていますので無事テストを通過しています。
まとめ
今回テストコードを書くメリットとrspecのインストールから実行までをやりましたが、こういったテストの技術は未経験から転職するのに必須の技術となるほどではないですが、個人で開発したプログラムできっちりテストコードが書けていると結構面談で評価されると思います。(面談先があらかじめてテストコードを書いている現場か確認は必要ですが)
転職に必須の技術というわけではないですが、エンジニアには転職して終わりではなくそこからさらにレベルアップする必要があります。効率的なチーム開発の方法やコードの品質の担保の仕方を学ぶ上でテストコードの書き方や書く意義を知っていることは非常に大切なのでちょっとずつで良いのでテストコードにトライしてみましょう。