give IT a try

プログラミング、リモートワーク、田舎暮らし、音楽、etc.

Qiitaに「テストコードの期待値はDRYを捨ててベタ書きする」という記事を書きました

お知らせ

昨日、Qiitaに「テストコードの期待値はDRYを捨ててベタ書きする ~テストコードの重要な役割とは?~」という記事を書きました。

テスト初心者の人が読むと役に立つかもしれません。
よかったら読んでみてください。

追記:さらに続編も書きました

上の記事で説明したテストコードをMinitestで書いたバージョンと、RSpecらしく書いたバージョンを説明している、続編の記事です。

この記事を書いた理由、もしくは「DRYを捨てる」という表現について

この記事を書いた理由は、テストコード内で変数や実装コード側のロジックを多用するコードを最近何度か目にしたからです。
たとえばこんな感じです。

given(:user) { create :user, name: 'Alice' }
scenario 'ユーザー詳細ページを表示する' do
  visit user_path(user)
  expect(page).to have_content "#{user.name}さん"
end

別の例を出すとこんな感じ。

class User
  def upper_name
    name.upcase
  end
end

let(:user) { create :user, name: 'Alice' }
describe '名前を大文字にする' do
  upper_name = user.name.upcase
  expect(user.upper_name).to eq upper_name
end

上のようなテストコードは次のように期待値をベタ書きするが望ましいです。

given(:user) { create :user, name: 'Alice' }
scenario 'ユーザー詳細ページを表示する' do
  visit user_path(user)
  expect(page).to have_content "Aliceさん"
end
class User
  def upper_name
    name.upcase
  end
end

let(:user) { create :user, name: 'Alice' }
describe '名前を大文字にする' do
  expect(user.upper_name).to eq 'ALICE'
end

なぜベタ書きした方がいいのかはQiita記事を読んでみてください。

ただ、熟練プログラマの人がこれを見ると「これはDRYとは関係ないんじゃないか?」と感じられる方もいるようです。
たしかに、実装コード側でよく言われるDRY原則と、期待値を変数や実装コードとほぼ同じロジックで書くことは、別物かもしれません。

とはいえ、僕がその人たちのコードを見ていると、「テストコードも1箇所の変更だけで済むコードが良いコード」だと考えているんじゃないかな?と感じました。

たとえば、AliceをBobに変更する場合、変数を使っていると1箇所の変更で済みます。

given(:user) { create :user, name: 'Bob' } # 変更1
scenario 'ユーザー詳細ページを表示する' do
  visit user_path(user)
  expect(page).to have_content "#{user.name}さん"
end

しかし、ベタ書きしていると2箇所の変更が必要です。

given(:user) { create :user, name: 'Bob' } # 変更1
scenario 'ユーザー詳細ページを表示する' do
  visit user_path(user)
  expect(page).to have_content "Bobさん" # 変更2
end

この「省エネ精神(?)」を一言で表現したい、と思ったときに「DRY原則が一番近いかな」と僕は思いました。
なぜなら、DRY原則も「コードの重複がなければ変更は1箇所だけで済む」という結果になるからです。

本当は「DRY」以外の言葉で表現すべきなのかもしれませんが、簡潔に表現できて、なおかつテスト初心者の人にも刺さるような言葉を思いつかなかったので、今回はDRYという言葉をタイトルや本文にちりばめています。

もし他に何かいい表現があれば、ぜひ教えてください m(_ _)m

まとめ

というわけで、今回はQiitaに書いた「テストコードの期待値はDRYを捨ててベタ書きする」という記事を紹介しました。
DRYという言葉が適切かどうかは記事の趣旨ではなく、僕が本当に言いたかったのは「実装コードでは良いとされているとプラクティスをテストコードに持ち込むと具合が悪くなる」ということです。

すべての人に「文句なし!」と言ってもらえる文章を書くのは難しいですが、内容自体はそれなりに読む価値があると思うのでぜひ読んでやってください。

あわせて読みたい

最近書いたその他のQiita記事を載せておきます。
まだ読んでない記事があれば読んでみてください。

  • 正規表現で名前付きキャプチャを使う方法を説明しました。

  • RubyGems.orgで発生した脆弱性に関する翻訳記事です。

  • 正規表現の\Aや\zの意味を詳しく説明しています。