5

I'm a noob as it comes to linux setup (and heroku), so apologies if this question is basic.

I want to run selenium webkit (in ruby) on Heroku. I face a difficulty that my script cannot find Chrome binary file.

I actually got chrome to work by itself:

~ $ chromedriver
Starting ChromeDriver 2.22.397932 (282ed7cf89cf0053b6542e0d0f039d4123bbb6ad) on port 9515
Only local connections are allowed.

chromedriver being a file that I copied from /app/vendor/bundle/bin/chromedriver, just to make it easier for now. chromedriver file there exists because I installed chromedriver-helper gem. The gem was supposed to make the binary file available for ruby processes but didn't.

I've also tried setting path explicitly, e.g. Selenium::WebDriver::Chrome.driver_path = 'chromedriver' in my ruby code, with the aforementioned file located in the root category.

It all works perfectly locally (with or without the driver_path)

What can be the cause? I've read this SO thread from years ago, but it seems outdated to me. Any ideas would be greatly appreciated!

error trace:

~ $ ruby bin/run.rb
/app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/response.rb:70:in `assert_ok': unknown error: cannot find Chrome binary (Selenium::WebDriver::Error::UnknownError)
  (Driver info: chromedriver=2.22.397932 (282ed7cf89cf0053b6542e0d0f039d4123bbb6ad),platform=Linux 3.13.0-91-generic x86_64)
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/response.rb:34:in `initialize'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/common.rb:78:in `new'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/common.rb:78:in `create_response'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/default.rb:90:in `request'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/bridge.rb:649:in `raw_execute'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/bridge.rb:123:in `create_session'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/bridge.rb:87:in `initialize'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/chrome/bridge.rb:48:in `initialize'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/common/driver.rb:64:in `new'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/common/driver.rb:64:in `for'
    from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver.rb:84:in `for'
    from /app/lib/mealpass_orderer.rb:12:in `initialize'
    from /app/lib/mealpass_orderer.rb:8:in `new'
    from /app/lib/mealpass_orderer.rb:8:in `run'
    from bin/run.rb:3:in `<main>'

UPDATE:

I tried the same with AWS EC2 server (launched instance, cloned git repo, installed all dependencies). The same happens there as well. That is, able to execute chromedriver from terminal, but seeing same error when run the script.

Community
  • 1
  • 1
Petr Gazarov
  • 3,602
  • 2
  • 20
  • 37

3 Answers3

5

ChromeDriver is just a driver for Chrome. It needs the actual Chrome browser installed on the same machine to actually work.

Heroku doesn't have Chrome installed on its dynos by default. You need to use a buildpack that installs Chrome. For example:

https://github.com/dwayhs/heroku-buildpack-chrome

You can see how it fetches Chrome:

https://github.com/dwayhs/heroku-buildpack-chrome/blob/master/bin/compile#L36-38

Ilya Vassilevsky
  • 981
  • 6
  • 14
  • Thanks @Ilya. I tried this buildpack and it didn't work. I'm suspecting installing google chrome (or any browser) on heroku might be more involved. – Petr Gazarov Jul 12 '16 at 05:29
  • Yes, Heroku is a very opinionated and closed platform. It should be much easier to set up Chrome with ChromeDriver on your own VM on AWS, Linode, or DigitalOcean. – Ilya Vassilevsky Jul 12 '16 at 09:56
  • 1
    Thanks for your answer Ilya. I ended up re-writing with Watir with phantomjs because I couldn't get Heroku to install Chrome. – Petr Gazarov Jul 17 '16 at 23:34
1

ANSWER

YOUR_PATH = 'whatever/your/path/is' # to your bin dir
CURRENT_DIR = File.expand_path(File.dirname(__FILE__))
CHROMEDRIVER_FN = File.join(CURRENT_DIR, YOUR_PATH, "bin/chromedriver")
# —OR—
#CHROMEDRIVER_FN = File.join(File.absolute_path('..', CURRENT_DIR), YOUR_PATH, "bin/chromedriver")
Selenium::WebDriver::Chrome.driver_path = CHROMEDRIVER_FN

CONTEXT

The example below shows my setup for Selenium Chromedriver in a recent Ruby project.

1) The file structure:

ruby_app/
├── Gemfile
├── Gemfile.lock
├── History.txt
├── Manifest.txt
├── README.md
├── Rakefile
├── bin
│   └── chromedriver
├── doc
├── lib
│   └── ruby_app.rb
└── test
    ├── test_files
    │   ├── test_config.yml
    │   └── uris_array_dump.yml
    ├── test_ruby_app.rb
    ├── test_google.rb
    ├── test_helper.rb
    └── test_output

2) In test/test_helper.rb:

TEST_DIR = File.expand_path(File.dirname(__FILE__))
TEST_FILES = File.join(TEST_DIR, "test_files")
TEST_OUTPUT = File.join(TEST_DIR, "test_output")
CHROMEDRIVER_FN = File.join(File.absolute_path('..', TEST_DIR), "bin", "chromedriver")

The above code uses File.absolute_path, see: http://ruby-doc.org/core-2.3.1/File.html#method-c-absolute_path

Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless dir_string is given, in which case it will be used as the starting point.


3) In test/test_google.rb:

Selenium::WebDriver::Chrome.driver_path = CHROMEDRIVER_FN
SoAwesomeMan
  • 3,226
  • 1
  • 22
  • 25
  • 1
    Hey man, thanks for your answer. I tried playing with it, including do all of the above in code as well as in the irb console. I also tried hardcoding the executable in bundle folder (`/app/vendor/bundle/bin/chromedriver`). I tried printing value of `CHROMEDRIVER_FN`. `CHROMEDRIVER_FN` gets set correctly. The file is definitely there, but Selenium doesn't see it on runtime. – Petr Gazarov Jul 10 '16 at 23:34
  • I started a bounty for this – Petr Gazarov Jul 10 '16 at 23:37
  • Too bad. At least we know now that Heroku is the factor here… Good luck with the bounty! – SoAwesomeMan Jul 11 '16 at 00:05
  • Thanks! Do you know if not running processes on heroku might be the cause? I'm not running server or other processes... – Petr Gazarov Jul 11 '16 at 00:35
  • _"third-party buildpacks that enable you to use languages and frameworks beyond those that are officially supported by Heroku."_ https://github.com/tstachl/heroku-buildpack-selenium + https://devcenter.heroku.com/articles/third-party-buildpacks – SoAwesomeMan Jul 11 '16 at 05:46
  • Thanks! I think I've seen one for googlechrome, I'll try to find and use it. – Petr Gazarov Jul 11 '16 at 16:52
1

Here's a minimal configuration that's worked for me. You'll need to have the right buildpacks to install chrome too, it looks like you're only installing chromedriver which is a separate binary.

https://github.com/jormon/minimal-chrome-on-heroku-xvfb

You can test one-button deploy it to Heroku using the button on the README.md.

Let me know how it goes!