Kernel.#openの例外処理
ruby2.0
特に理由がないのでmechanizeは使わずopenを使ってスクレイピングしてます。歌丸です。
コード
これは記事一覧ページの存在を確認をするためのメソッド。
private def not_found_index_page?(_error_count = 0) is_error_under_5 = ->{ _error_count += 1; _error_count < 5 } begin open(current_index_page_url) return false rescue Timeout::Error retry if is_error_under_5.call rescue SocketError # ホストがないときとか rescue OpenURI::HTTPError => e case e.io.status[0] when /5../ retry if is_error_under_5.call when /4../ end rescue Exception => e puts e end return true end
テスト
スタブぐぐるの結構大変だった。
describe "#not_found_index_page?" do let(:lh){ Lifehacker.new('business') } subject { lh.send('not_found_index_page?') } context "openメソッドが正常終了する時" do before { lh.stub(:open).and_return("") } it { should be_false } end context "例外が発生するとき" do describe "Timeout::Error" do let(:e) { Timeout::Error } before { lh.stub(:open).and_raise(e) } it { should be_true } end describe "SocketError" do let(:e) { SocketError } before { lh.stub(:open).and_raise(e) } it { should be_true } end describe "OpenURI::HTTPError" do let(:io) { double('io') } describe "5XX" do describe "ずっと5XXが返ってくる時" do before do io.stub_chain(:status,:[]).with(0).and_return('502') lh.stub(:open).and_raise(OpenURI::HTTPError.new('', io)) end it { should be_true } end describe "最初だけ5XXで以降は正常になること" do before do pending "例外なげたら次は文字列を返したい" io.stub_chain(:status,:[]).with(0).and_return('509') lh.stub(:open).and_raise(OpenURI::HTTPError.new('', io)).and_return("") # できてない end it { should be_true } end end describe "4XX" do before do io.stub_chain(:status,:[]).with(0).and_return('402') lh.stub(:open).and_raise(OpenURI::HTTPError.new('', io)) end it { should be_true } end end end end
スタブ、and_returnメソッドを使えば同じ型に限って、違う値を返せるけど、
例外と普通の型を交互に投げたい時ってどうするんだろう。