How to run tests in Pytest in parallel inside the Docker container? - python-3.x

I ran into a problem when running GUI tests in parallel inside a Docker container. I use a bunch: Selenium webdriver + Pytest + Xdist + Chrome.
I use following command to run the tests:
pytest -v -n=4 --headless=True --production=True --browser=chrome --dist=loadfile --junitxml=test.xml
But all the tests fail. If I do the same outside the docker container or use 1 thread - it's working fine.
So, how can I resolve this problem and execute tests in parallel inside the docker container? Thanks a lot)
I have this in logs:
selenium.common.exceptions.WebDriverException: Message: chrome not reachable (Session info: headless chrome=73.0.3683.86) (Driver info: chromedriver=73.0.3683.20 (8e2b610813e167eee3619ac4ce6e42e3ec622017),platform=Linux 4.15.0-46-generic x86_64)

Try to use boxed processes + tx flag: (--tx 3*popen//python=python3.6 --boxed, so run your tests with the command below:
pytest -v --headless=True --production=True --browser=chrome --dist=loadfile --junitxml=test.xml --tx 3*popen//python=python3.6 --boxed
More information of how you can run your tests in parallel is available under that SO answer .
Good Luck !

Related

How to run Cypress tests on circle-ci orb using Cypress-tags

I am trying to run a small test collection with Cypress using the cucumber plugin and the official Circle-ci Orb.
I've been going through the documentation and I've got them running without issues locally. The script I'm using to run them locally is this one:
"test:usa": "cypress-tags run --headless -b chrome -e TAGS='#usa'"
*Note the cypress-tags command and the TAGS option.
For the CI I use the official Circle-ci Orb and have a configuration like this:
- cypress/run:
name: e2e tests
executor: with-chrome
record: true
parallel: true
parallelism: 2
tags: 'on-pr'
group: 2x-chrome
ci-build-id: '${CIRCLE_BUILD_NUM}'
requires:
- org/deployment
As you can read, I want to raise 2 machines where I divide my feature files, setting the tag to 'on-pr' and grouping the run under '2x-chrome' using as well the ci-build-id.
The thing is that the official Orb uses the cypress run command which does not filter scenarios by their tags, so it is of no use here. My options were:
Using the command parameter in the orb to call the required script as I do locally:
command: npm run test:usa
My problem with this option is that the parallel configuration does not work as expected so I discarded it.
I tried to pass the TAGS parameter as an env var within the Circle-ci executor to see if the Orb was able to see it, but it was of no use as the Orb does not use cypress-tags run but cypress run.
environment:
TAGS: '#usa'
At this point my question is, is there a workaround to this (using cypress-tags in the Circle-ci orb) or shall I opt for a different way of testing this?
Thanks in advance

Running a pytest fixture only once when running tests in parallel

I'm having some real difficulty in running a pytest fixture within a conftest file only once when the tests are run in parallel via a shell script. Contents of the shell script are below:
#!/usr/bin/env bash
pytest -k 'mobile' --os iphone my_tests/ &
pytest -k 'mobile' --os ipad my_tests/
wait
The pytest fixture creates resources for the mobiles tests to use before running the tests:
#pytest.fixture(scope='session', autouse=True)
def create_resources():
// Do stuff to create the resources
yield
// Do stuff to remove the resources
When running each on its own it works perfectly. Creates the resources, runs the tests and finally removes the resources it created. When running in parallel (with the shell script) both try to run the create_resources fixture at the same time.
Does anyone know of a way I can run the create_resource fixture just once? If so then is it possible for the second device to wait until the resources are created before all devices run the tests?

Selenium::WebDriver::Error with Firefox & Chrome

Problems
1. Browser = Firefox (Non Geckodriver, Selenium v2.53.4)
(Works on one linux thin client but not on another...)
$ bundle exec rake parallel:spec
Selenium::WebDriver::Error::WebDriverError:
unable to bind to locking port 7054 within 120 seconds
2. Broswer = Firefox (Geckodriver v0.14.0, Selenium-webdriver v3.1.0)
$ bundle exec rake parallel:spec
Net::ReadTimeout:
Net::ReadTimeout
3. Browser = Chrome (Chromedriver v2.27, Selenium-webdriver v3.1.0)
$ bundle exec rake parallel:spec
Selenium::WebDriver::Error::NoSuchDriverError:
no such session
(Driver info: chromedriver=2.27.440175 ,platform=Linux 3.16.0-0.bpo.4-amd64 x86_64)
My Setup
Server with the following installed:
-Linux - Debian x86_64 Wheezy
-ruby 2.2.5p319 (2016-04-26 revision 54774)
-Firefox v46.0.3
-Chrome 56.0.2924.87 (64-bit)
-ChromeDriver 2.27.440175
-Xvfb (x11-xserver-utils v 7.7~3 through headless gem)
Gems
-Selenium v3.1.0 (was 2.53.4)
-parallel_tests v2.10.0
-capybara (2.7.1)
-rspec-activemodel-mocks (1.0.3)
-rspec-core (3.4.4)
-rspec-expectations (3.4.0)
-rspec-mocks (3.4.1)
-rspec-rails (3.4.2)
-rspec-support (3.4.1)
-headless (2.2.3) (Xvfb)
Multiple thin clients running their software off the mentioned server setup.
My computer is one of many...
Important: There is another computer that does NOT encounter the mentioned problem running the same software and same versions off the same server!
Things that are NOT the problem
It is not an incompatibility between my firefox browser version and Selenium.
Why not?
a) Firefox v46.0.3 and Selenium v2.53.4 is currently installed on our server and another client of this server successfully runs parallel_tests using the mentioned versions of Firefox & Selenium.
b) Which Firefox version is compatible with Selenium 2.53.0?
There are no zombie processes(still running firefox) causing firefox to lock port 7054.
This is specifically after each failure has occurred and prior to starting a new $ bundle exec rake parallel:spec run.
Why not?
refer to items 1 & 2 in 'Things I Have Tried'
Turned Out this was not the case, although it was not the cause of the problem
Databases were not always properly killed, See Update 5.
However the databases not being killed were an outcome of the problem.
They were not the cause of the problem, refer to solution section.
Side note
For those wishing to install the mentioned versions to get selenium / firefox working:
Installing a previous version doesn't fix most problems
Things I have tried
Removed any processes still running
$ killall ruby; killall rspec; killall firefox
Result: Failed...
Discovered that completing step 1 is not enough to kill all zombie processes.
After logging out into a different tty i discovered that there was still an rspec, ruby and firefox process running!
So I logged out of my user, logged into a new tty, killed all zombie processes using:
$ kill -9 process_id
I then rerun $ ps aux to ensure all processes are cleaned.
Result: Failed...
Gain insight into the problem.
Ran $ lsof -i TCP:7054 see what is holding that process.
Result: It was my firefox test, no suprise, no real insight gained.
Ensured parallel test databases were running correctly.
Dropped all databases, recreated databases, reloaded all schemas, reseeded (development), reprepared.
Result: Failed... I doubted this was the cause, but doing this certainly eliminated it.
Deleted firefox cache, all persisted setting, everything, for a clean start.
Result: Failed...
Try to eliminate any local environment variables obtained from the project.
Did this by copying the project directory from the working computer.
Then reran $ bundle exec rake parallel:spec.
Result: Failed...
Try to eliminate all local environment variables (project and linux).
Did this by creating a new linux user.
Then switched into the new user.
$ su new_user -l
Copied over the minimum zsh items needed.
Then ran $ bundle exec rake parallel:spec
Result: Failed...
Ensured that /etc/hosts contained:.
127.0.0.1 localhost
Result: Failed...
Running the tests in a single thread (not parallel).
$ rspec spec
Result: Successfully runs (does not hit the problem)
See Update 1
See Update 2
See Update 3
See Update 4
See Update 5
Partial Solution
See Update 6
Debugged Selenium & Parallel_tests gems
Result: Identified that the issue is NOT in Selenium
See Update 7
Result: Running tests in parallel worked. But why?
See Update 8
Result:
Discovered Selenium 3.1.0 changed the way files are automatically downloaded.
This caused tests to hang indefinitely whilst running parallel test.
Which caused the databases to be held open.
Things I am going to try (Updates)
Run tests with chromedriver in chrome browser and see if it passes after the fix.
Update 1
I replaced firefox for chrome.
When I run a single test, the test successfully completes with chrome.
It did so with firefox as well.
However running $ bundle exec rake parallel:spec
Result: Failed...
Selenium::WebDriver::Error::NoSuchDriverError:
no such session
(Driver info: chromedriver=2.27.440175 ,platform=Linux 3.16.0-0.bpo.4-amd64 x86_64)
Update 2
I updated selenium-webdriver gem to the latest gem (was v2.53.4 now 3.2.2)
Result: Failed...
Selenium::WebDriver::Error::NoSuchDriverError:
no such session
(Driver info: chromedriver=2.27.440175 ,platform=Linux 3.16.0-0.bpo.4-amd64 x86_64)
Update 3
Located lock file for parallel test (~.config/google-chrome).
Identified 3 persisting lock files.
Other users only had 1.
Deleted these and reran tests.
Result: Failed...
Selenium::WebDriver::Error::NoSuchDriverError:
no such session
(Driver info: chromedriver=2.27.440175 ,platform=Linux 3.16.0-0.bpo.4-amd64 x86_64)
Update 4
Upgraded selenium-webdriver to v3.1.0 (latest stable)
Upgraded parallel_tests to v2.13.0 (latest)
Installed Geckodriver v0.14.0 (latest)
Then ran $ bundle exec rake parallel:spec
Result: Failed...
Failure/Error: visit "#/login"
Net::ReadTimeout:
Net::ReadTimeout
Update 5
Whilst in the firefox (Geckodriver v0.14.0, Selenium-webdriver v3.1.0) branch.
I only realised when I had to drop all my parallel_test databases that some were still open.
#ltsp:~/ap$ bundle exec rake parallel:drop[32]
Couldn't drop ap_test_andre32 : #<ActiveRecord::StatementInvalid: PG::ObjectInUse: ERROR: database "ap_test_andre32" is being accessed by other users
DETAIL: There are 3 other sessions using the database.
: DROP DATABASE IF EXISTS "ap_test_andre32">
Couldn't drop ap_test_andre25 : #<ActiveRecord::StatementInvalid: PG::ObjectInUse: ERROR: database "ap_test_andre25" is being accessed by other users
DETAIL: There are 3 other sessions using the database.
: DROP DATABASE IF EXISTS "ap_test_andre25">
When rake parallel:spec does not complete (indefinetly hangs during ),
the process must be killed manually.
Doing so leaves databases locked to the parallel_tests that were using them at the time.
So they must be identified and cleaned up.
postgres 743 0.0 0.0 222364 33628 ? Ss 15:30 0:00 postgres: andre ap_test_andre32 [local] idle in transaction
andre 24581 0.0 0.0 7852 2028 pts/36 S+ 15:49 0:00 grep andre32
postgres 26822 0.0 0.0 220032 23400 ? Ss 15:35 0:00 postgres: andre ap_test_andre32 [local] ALTER TABLE waiting
postgres 29684 0.0 0.0 220032 24064 ? Ss 15:40 0:00 postgres: andre ap_test_andre32 [local] ALTER TABLE waiting
Update 5 Solution:
search for database processes & kill all of them
ps aux | grep test_andre
andre#ltsp:~/ap$ sudo kill -9 743 26822 29684
I was then able to drop my databases.
bundle exec rake parallel:drop[32]
Update 6
Whilst in the firefox (Geckodriver v0.14.0, Selenium-webdriver v3.1.0) branch.
Cloned parallel_tests & Selenium projects locally.
Replaced my gems with a path to the locally cloned projects.
Debugged starting with the error stack trace.
Results
Updated to selenium 3.1.0 and loaded geckodriver (marionette).
I discovered that my firefox profile was not setup correctly with Capybara.
This broke my local single thread tests.
Fixed this.
Discovered that geckodriver is not to be used for FF<48.
Also discovered that the capybara, selenium 3+ & FF48+ combo is not yet ready for use.
Some vital functions are not working. (Right clicking, window resizing...)
Refer here for full details
After investigating parallel_tests, was able to rule that out.
Continued to debug in the firefox test case.
Used the locking port error as my guide.
Ruled out Selenium as the cause of the error.
After debugging the stack trace, it was proving to be very likely that the error state was inherited.
This was just a strong hunch at the time.
It later proved to be correct...
So summary here was that firefox had processes that were being locked.
And they were not being locked by Selenium.
Update 7
Whilst in the firefox (Selenium-webdriver v2.53.4) branch.
Went back to the new linux user that was created.
In light of Update 5, I dropped cleaned up all running processes.
Dropped all databases.
$ bundle exec rake parallel:spec
Result: Parallel tests worked
But why?
The databases were not the cause of the issue.
There was something else.
Update 8
Whilst in the firefox (Geckodriver v0.14.0, Selenium-webdriver v3.1.0) branch.
Identified the reason why the tests were failing and idenfinitely hanging.
This caused the issues described in Update 5 & 6.
It was caused by a change in the way Selenium accepts firefox profile settings.
I identified that the integration tests that were failing were ones that launched a pdf download.
Previously, I had this automated so that the download modal would not appear.
Instead it would automatically download the file to a specified folder.
Updating to Selenium 3.1.0 broke this.
Tests hanged indefinitely.
Databases were held open.
The problems identified, in the updates were not the root cause.
The root cause was that firefox/chrome browser ports were not closed and held open.
After looking at htop, Polkitd was seen to be taking up 16.5gb of ram!
This was caused by a memory leak in Polkitd.
After checking the issues it was confirmed that Polkitd memory leak is a know issue.
The issue has been fixed but only in later distributions of linux debian and not for Wheezy.
After restarting Polkitd, and rerunning the tests in parallel they worked!
This explains why the first time I created a new linux user with a clean profile the parallel test issues were still occuring. - Memory leaks are unpredictable.
It also explains why another computer did not run into the issue.
And why the second time I created a new user the parallel tests worked!
Phew, that took a lot of effort!
Polkitd was uninstalled as it was not needed for any printers or other software that we run.
Overall, if anyone else has the locking issue, it would be helpful to follow some of the process detection that I have done as some of the issues are common to all OS.

docker - libudev: udev_has_devtmpfs: name_to_handle_at on /dev: Operation not permitted

I doing Docker tests about using apps with GUI. SublimeText,Eclipse,Hangout and others apps good working but in this case i try install popcorntime app in to docker container using Debian image and when i execute the app show me some errors. Sorry, but i'm new in Docker world and would like know how to fix this problem for future occasions.
First, I execute to docker container of next form:
docker run -ti -v /tmp/.X11-unix/:/tmp/.X11-unix -e DISPLAY --shm-size=1024m --memory 512m --device /dev/snd popcorntime bash
Next, into contaniner:
root#1cc4aea76556:/opt/popcorntime# ./Popcorn-Time
libudev: udev_has_devtmpfs: name_to_handle_at on /dev: Operation not permitted [59:1106/211526:WARNING:x11_util.cc(315)] X failed to attach to shared memory segment 262145 [59:1106/211529:INFO:CONSOLE(120)] "Uncaught ReferenceError: pageOptions is not defined", source: http://app.time4popcorn.eu/?uid=17F98CC7FD403488DA7B5E1D6989EE2C&register_date=1478465906&version=0.3.0&os=linux&r=0.025844353018328547 (120) [59:1106/211529:INFO:CONSOLE(120)] "Uncaught ReferenceError: pageOptions is not defined", source: http://app.time4popcorn.eu/?uid=17F98CC7FD403488DA7B5E1D6989EE2C&register_date=1478465906&version=0.3.0&os=linux&r=0.025844353018328547 (120) [59:1106/211529:ERROR:crash_handler_host_linux.cc(380)] Failed to write crash dump for pid 79 Cannot upload crash dump: cannot alloc [59:1106/211529:ERROR:breakpad_linux.cc(1225)] crash dump file written to /tmp/chromium-renderer-minidump-b10e73ec0d1694fc.dmp
Please, someone that me orient for know how to execute this app using docker container???....
Docker Seccomp default profile disabled a system call that your container is calling.
As quick and dirty solution, try running the container with additional option after docker run
--security-opt seccomp=unconfined
This way you run a container without the default seccomp profile. Then it should be better to use a custom profile putting in the white list the systemn call your container needs.

Does 'docker run' modify image state?

I have a Dockerfile that uses an ubuntu base image and installs a bunch of dependencies with apt-get and dpkg. Then it copies some javascript files and runs a node app. The node app spawns a child process and executes xvfb-run selenium-standalone start.
If I build the docker image with --no-cache and run it using docker run -i -t <image id> my app starts and connects to the selenium server immediately. If I kill the container using CTRL-C or docker stop <container id> and then run the exact same docker run command as above, my app starts as normal, but cannot connect to the selenium server. If I leave it alone, five minutes later, it will connect properly on its own. It behaves this way every time I run docker run until I do a clean image build.
Changing a node source file and rebuilding mostly from cache does not alter this behavior. I've repeated the process several times and it's always the same.
I can't figure out how the behavior can change from one docker run to the next, if the same image is used. Where is the shared state?
Log when working:
gulp run
22:42:31.541 INFO - Launching a standalone Selenium Server
Setting system property webdriver.chrome.driver to /usr/lib/node_modules/selenium-standalone/.selenium/chromedriver/2.16-x64-chromedriver
22:42:31.579 INFO - Java: Oracle Corporation 24.79-b02
22:42:31.579 INFO - OS: Linux 3.18.5-tinycore64 amd64
22:42:31.594 INFO - v2.46.0, with Core v2.46.0. Built from revision 87c69e2
22:42:31.676 INFO - Driver provider org.openqa.selenium.ie.InternetExplorerDriver registration is skipped:
registration capabilities Capabilities [{platform=WINDOWS, ensureCleanSession=true, browserName=internet explorer, version=}] does not match the current platform LINUX
22:42:31.676 INFO - Driver class not found: com.opera.core.systems.OperaDriver
22:42:31.677 INFO - Driver provider com.opera.core.systems.OperaDriver is not registered
[22:42:31] Using gulpfile /opt/app/gulpfile.js
[22:42:31] Starting 'run'...
[22:42:31] Finished 'run' after 1.29 ms
Started App.
22:42:31.764 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
22:42:31.764 INFO - Selenium Server is up and running
Selenium started
2015-08-19T22:42:32.445Z Starting app on port: 8000
Logs when not working are exactly the same except missing the RemoteWebDriver, 'Selenium Server is up and running', and 'Selenium started.' lines.
Try removing the container instead of just stopping it:
docker stop <container id>
docker rm <container id>

Resources