poyopoyo0のブログ

poyopoyoのブログ

Web 関連のメモ書きブログです。

execute_script と evaluate_script の違いって何だろう

Capybara でテストを実行した際、下記のようなエラーが出てテスト失敗することがある。

1) Error:
TopTest#test_Post_note:
JSON::NestingError: nesting of 101 is too deep
    test/integration/top_test.rb:65:in `block in <class:TopTest>'

テストのソースを見たら evaluate_script で発生しているエラーらしい。

github.com

のコメントに「 evaluate_script でエラーが出るときは execute_script を使ったらいいよ」と書かれていたので、その通りにしたら、テストが通るようになった。

じゃあ、 execute_scriptevaluate_script って何が違うんだろう、と疑問に思ったので、 binding.pry で二つの違いを追っかけてみた。結果は以下の通り。

1. execute_script の動き

capybara-webkit/lib/capybara/webkit/driver.rb

def execute_script(script)
  value = @browser.execute_script script
  value.empty? ? nil : value
end

capybara-webkit/lib/capybara/webkit/browser.rb

def execute_script(script)
  command('Execute', script)
end

capybara-webkit/lib/capybara/webkit/driver.rb

def execute_script(script)
  value = @browser.execute_script script
  value.empty? ? nil : value
end

2. evaluate_script の動き

capybara-webkit/lib/capybara/webkit/driver.rb

def evaluate_script(script)
  @browser.evaluate_script script
end

capybara-webkit/lib/capybara/webkit/browser.rb

def evaluate_script(script)
  json = command('Evaluate', script)
  JSON.parse("[#{json}]").first
end

ここで

JSON.parse("[#{json}]").first

を実行すると

JSON::NestingError: nesting of 101 is too deep
from /vendor/bundle/ruby/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `parse'

とエラー(= この記事の冒頭で出ていたエラーと同じ)が出てしまうが、

JSON.parse("[#{json}]").first

の代わりに

JSON.parse("[#{json}]", max_nesting: 101).first

としてやると、エラーが出なくなる( 参考 )。

3. 結論

execute_scriptevaluate_script でやってることは同じだけど、evaluate_script の方は Command の返り値を JSON.parse してて、そこで nest が deep になる…、ということらしい。

テストで返り値を使ってないのであれば、 evaluate_script は使わず execute_script に統一しておいてもいいかも。