Two threads, one database
The first thread is running the cucumber scenario for example, where you'll create a
User, some other objects and then login, click here and there and so on, and the second thread is where Capybara is piloting the web browser through a driver like poltergeist.
The problem with the 2 threads is that the Rails database connections aren't shared so that the second thread doesn't know when the first one has commited some data, or when DatabaseCleaner rollbacked the transaction at the end of your scenario.
This will lead you where data is missing or some remaining data from a previous test is present having as a consequence to have random failing test suite (the test is passing when running alone but fails when the suite is running, or even worst it is failing on the CI but not your local machine).
Let's share the database connections
You probabely read about a patch sharing the ActiveRecord connections between the 2 threads, you run your tests and it's green!
So what's the problem?
Okay then you run the entire suite and here you have concurrency issues with the database:
Mysql2::Error: This connection is in use by: #<Celluloid::Thread:0x0000000d1b56e0 sleep>
There seems to be a way to avoid this issue, I didn't tried yet, but the 100% working solution is to not use transactionnal tests, but it slows your test suite a lot 😢.
features/env.rb file, change the DatabaseCleaner strategy to
# Remove/comment out the lines below if your app doesn't have a database. # For some databases (like MongoDB and CouchDB) you may need to use :truncation # instead. begin DatabaseCleaner.strategy = :truncation rescue NameError raise 'You need to add database_cleaner to your Gemfile ' \ '(in the :test group) if you wish to use it.' end
Also ensure the
Testing the AngularJs application
My first try was to install poltergeist like I always did in the past and test the AngularJs app.
Fortunately Google has released the Chrome Driver allowing to use the Chrome headless mode for running tests.
This image contains Selenium, Firefox and Chrome all configured in order to allow you to run your tests 🎉.
Plus they have a debug image which includes a VNC server allowing you to see the web browser and having a control access, just perfect!
Capybara with Selenium and Chrome headless
Here is how to configure Capybara in your Rails application so that it uses Selenium to execute the Cucumber scenarios.
This config is registering a new Capybara driver named
:chrome using the selenium-webdriver gem to define the capabilities to configure Chrome (flags from
:prefs) also increase the timeout and finally defines the URL where is running the selenium node (in this case the hostname is
selenium which is the container name, Docker adds a DNS entry to resolve containers IP from their names).
Next we are configuring the
A very important line is
Capybara.server_host = '0.0.0.0' # bind to all interfaces.
Without it, Capybara is binding to the local loop
127.0.0.1 and Chrome can't reach the app.
Bonus: The capybara-screenshot gem is working so that when the test is failing (or you request yourself), HTML and PNG screenshots are generated in the
tmp/capybara folder of your project.
Finally you need to add the Docker image containing Selenium and the web browsers:
Add the following block to your
version: "2" services: ... selenium: links: - app:one-test.pharmony.eu image: selenium/standalone-chrome:3.11.0-antimony # image: selenium/standalone-chrome-debug:3.11.0-antimony # For Debug (And uncomment the `ports` node to connect with VNC) # ports: # - "5900:5900" volumes: - /dev/shm:/dev/shm
And also add the environment variable in your app container:
version: "2" services: app: ... environment: ... - SELENIUM_PORT=4444
You're ready to go! Now run the
docker-compose up command and it will download the image and start it.
(FYI as you updated the environment variables of your app image, you need to stop, remove and create it again in order to get the new variable in your container)
Now you want to run the tests and see the Chrome app running?
docker-compose.yml file comment the
image: selenium/standalone-chrome:3.11.0-antimony line from the
selenium service and uncomment the lines after (
Stop and remove the selenium container and start it again.
Now you can connect to the VNC server at vnc://localhost:5900 using the Screen Sharing app.
If you want to have the Chrome devtools opened automatically, uncomment the
--auto-open-devtools-for-tabs flag from the capybara configuration file.