Ruby: テストを不安定にする5つの残念な書き方(翻訳)

こんにちは、hachi8833です。今回はテストを正しく書く方法を解説する記事の翻訳をお送りします。 概要 原著者の許諾を得て翻訳・公開いたします。 元記事: Five ways to write a flaky test 著者: Kir Shatrov(@kirshatrov) テストを不安定にする5つの残念な書き方(翻訳) 不安定なテストは、毎日の苦労を台無しにしてくれる技術上の負債の一部となります。テストが不安定だとCIが赤信号になってしまい、それだけのために新しいコードのリリースを中断してビルドをやりなおすはめになります。実際のコードはどこもおかしくないのに、どこかがおかしいのではないかという疑念が湧くと、ストレスの元になります。 数百人の開発者と5万件のテスト項目があるような大規模案件では、不安定なテストが混入する可能性がさらに高まります。 本記事で扱うデモの中には、テストの実行順序に関連するものもありますが、そうでないものもあります。テストの実行順序とは何か、それがテストにどう関連するのか。それを確認する一番の方法は、テストの実行順序をランダムにしてみることでしょう。そうすれば、あるテストが他のテストに紐付けられていないことと、テストが実行順序に依存していないことがわかります。 本記事ではMiniTestを用いますが、どの問題もフレームワークに依存しないものばかりなので、MiniTestであるかRSpecであるかを問わず、一般的に応用できます。 1. ランダムなファクトリー # emailフィールドにはunique制約がかかっているとする 10.times do Customer.create!(email: Faker::Internet.safe_email) end どこに問題があるかおわかりでしょうか。 このテストはほとんどの場合パスしますが、ごくたまに、既に使ったメールアドレスがFakerからもう一度返されることがあります。そしてunique制約エラーに引っかかってテストがクラッシュするというわけです。 正しい書き方はこうです。 10.times do |n| Customer.create!(email: Faker::Internet.safe_email(n.to_s)) end Fakerに渡す引数を、(デフォルトの)ランダムなメールではなく、n番目のメールを指定するのがポイントです。 2. データベースのレコード順 assert_equal([1, 2, 3], @products.pluck(:quantity)) このテストもほぼすべてのケースでパスしますが、ORDERなしのSELECTクエリではレコードの順序が保証されません。こうしたランダムな要素が原因のエラーを回避するには、次のように明示的に順序を指定します。 assert_equal([1, 2, 3], @products.pluck(:quantity).sort) # または assert_equal([1, 2, 3], @products.order(:quantity).pluck(:quantity)) … Continue reading Ruby: テストを不安定にする5つの残念な書き方(翻訳)