【Rspec】CSVファイルのBOMの有無にハマった話
こんにちは!サーバーサイドエンジニアのメグミです!
弊社サービスの「Carely」では、テストを Rspec で書いています。
先日、実装に合わせてテストを修正したところ、うまくテストが通らず
長時間格闘してしまったときのことについて書こうと思います。
テストしたかったこと
ダウンロードしたCSVファイルのデータが期待した値であること
背景
出力されるCSVファイルの項目に変更が必要だったため、実装を変更しました。
そのため、既存のテストコードも修正が必要でした。
テストの修正
既存のテストコード
it "CSVのダウンロードができること" do
click_on "CSVダウンロード"
file_downloaded = File.open(CapybaraDownloadsHelper.files[0])
downloaded_array = [].tap do |array|
file_downloaded.each { |line| array << line }
end
file_expected = File.open("expected_data.csv")
expected_array = [].tap do |array|
file_expected.each { |line| array << line }
end
expect(downloaded_array).to match_array(expected_array)
end
expected_data.csv
ヘッダ1,ヘッダ2,ヘッダ3,... 省略 ...,ヘッダ100
データ1,データ2,データ3,... 省略 ...,データ100
...データがつづく
修正したところ
今回、ヘッダの項目を2つ追加するように実装を変更したので、
以下のように expected_data.csv
を修正しました。
expected_data.csv
ヘッダ1,ヘッダ2,ヘッダ3,... 省略 ...,追加ヘッダ1,追加ヘッダ2,ヘッダ100
データ1,データ2,データ3,... 省略 ...,追加データ1,追加データ2,データ100
...データがつづく
この内容で spec を実行したところ、失敗してしまいました。
エラーメッセージは以下でした。
Failure/Error: expect(downloaded_array).to match_array(expected_array)
expected collection contained: ["ヘッダ1,ヘッダ2,ヘッダ3...,ヘッダ100"]
actual collection contained: ["ヘッダ1,ヘッダ2,ヘッダ3...,ヘッダ100"]
the missing elements were: ["ヘッダ1,ヘッダ2,ヘッダ3...,ヘッダ100"]
the extra elements were: ["ヘッダ1,ヘッダ2,ヘッダ3...,ヘッダ100"]
🤔?・・・何が違うんだ?
私はこのとき、CSVの項目が多すぎたため、項目の追加を誤ったのだと思いました。
いざ、デバッグ!
[1] pry > downloaded_array[0]
=> ["ヘッダ1,ヘッダ2,ヘッダ3,...省略...,ヘッダ100"]
[2] pry > expected_array[0]
=> ["ヘッダ1,ヘッダ2,ヘッダ3,...省略...,ヘッダ100"]
んー、同じ。
ではどの値が違うのか差分をとってみよう!
[3] pry > downloaded_array[0].split(',') - expected_array[0].split(',')
=> ["ヘッダ1"]
ヘッダ1が残った!ってどういうこと?
それぞれの文字数を見てみよう!
[4] pry > downloaded_array[0].split(',')[0].length
=> 5
[5] pry > expected_array[0].split(',')[0].length
=> 4
なんと!長さがちがう!
なぜだろう?
原因
同じチームのいっせいさんに相談したところ、
BOMの有無で先頭の文字列の長さが変わってしまうから ということがわかりました。
こうして解決
expected_data.csv
をBOM付きに変更したところ、
無事にテストが通りました 🙌
さいごに
目に見える値が同じだったので同じ値とばかり思い込んでいました。
今後はもうBOMに振り回されないようにします!
以上、BOMの有無にハマったときのお話でした。
おわり