launching appium server through python script gives error - shell

I am launching appium server through terminal by command appium and in another terminal I run my test suite python test.py This works fine.
But if launch through python script I get error between 2 tests
def setup(self):
subprocess.Popen('appium', shell=False)
time.sleep(5)
desired_caps = dict()
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '6.0'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = os.path.abspath('test.apk')
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
return self.driver
error: Couldn't start Appium REST http interface listener. Requested port is already in use. Please make sure there's no other instance of Appium running already.
The error has no effect tests still pass
I tried adding killall node in teardown
def tearDown(self, driver):
self.driver = driver
self.driver.quit()
subprocess.Popen('killall node', shell=False)
but it gives me error
OSError: [Errno 2] No such file or directory
How can I get rid of error and stop appium server?
Setup is called through launch app -> click some buttons -> call teardown through close app

Related

How to fix error when .launch() application

I am writing ui tests for an application. I have a set of 40 test scripts. When I run each test separately, there are no problems. But when I try to run all the tests in a row, I get this error:
Failed to create directory on device 'iPhone (o...a)' (1...c) to hold runtime profiles for application with bundle ID '...': No matching application with bundle identifier '...'
Domain: IDEFoundationErrorDomain
Code: 17
--
No matching application with bundle identifier '...'
Domain: com.apple.platform.iphoneos
Code: 0
--
On completion of each test in tearDownWithError() I delete my app. At the beginning of each test in setUpWithError() I launch my application using XCUIApplication().launch().
The error occurs after the application tries to run in the second test
tearDownWithError() looks like that:
let springboard = XCUIApplication(bundleIdentifier:"com.apple.springboard")
XCUIApplication().terminate()springboard.icons["MyApp"].press(forDuration: 3)
sleep(1)
springboard.icons["MyApp"].buttons["DeleteButton"].tap()
sleep(3)
let deleteapp = springboard.buttons["Удалить приложение"]
if deleteapp.waitForExistence(timeout: 1){deleteapp.tap()}
let delete = springboard.buttons["Удалить"]
if delete.waitForExistence(timeout: 1){delete.tap()}
setUpWithError() looks like that:
continueAfterFailure = false
XCUIApplication().launch()
The specified error occurs at the line XCUIApplication().launch()

I get an error when using selenium chromedriver to create a session where I am logged into my account

The code I'm using start the session doesn't seem to be working, but I don't know what is wrong with it.
I can create a session without logging in and do what I want but when I try to the use the recommended method of creating the driver with an Options object and adding a user-data-dir, I run into errors.
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('user-data-dir=C:\Users\user\AppData\Local\Google\Chrome\User Data')
driver = Selenium::WebDriver.for(:chrome, options: options)
driver.get("https://login.tripleseat.com/")
email_field = driver["login"]
email_field.send_keys("clshaps93#gmail.com")
email_field.submit
I want my program to get to the bottom section signed into my account without running into an error.
If I don't have a Chrome window already open, I end up with this error:
1: from C:/Ruby25-x64/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/response.rb:32:in initialize'
C:/Ruby25-x64/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/response.rb:69:inassert_ok': unknown error: cannot determine loading status (Selenium::WebDriver::Error::UnknownError)
from no such execution context
If I do have Chrome window already open, I end up with this error:
1: from C:/Ruby25-x64/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/response.rb:32:in initialize'
C:/Ruby25-x64/lib/ruby/gems/2.5.0/gems/selenium-webdriver-3.141.0/lib/selenium/webdriver/remote/response.rb:69:inassert_ok': unknown error: Chrome failed to start: crashed (Selenium::WebDriver::Error::UnknownError)
(unknown error: DevToolsActivePort file doesn't exist)
(The process started from chrome location C:\Program Files (x86)\Google\Chrome\Application\chrome.exe is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
Other values I have tried to use for user-data-dir just end up being ignored, in that a session starts without logging me in. Is there some code I need to add somewhere to avoid these errors?

Chromedriver remote-debugging-port with Selenium

I am using Capybara Selenium to run headless Chrome, which works great, except I cannot figure out how to use remote debugging. When I add --remote-debugging-port=4444 or --remote-debugging-port=9222 or --remote-debugging-port=9521, Selenium no longer connects to the browser to run the test.
How do I get remote debugging to work? Here is my code for reference:
Capybara.register_driver :selenium do |app|
# from https://github.com/SeleniumHQ/selenium/issues/3738
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: {browser: 'ALL'})
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument '--disable-infobars' # hide info bar about chrome automating test
# if we don't use this flag, every selenium test will die with the error:
# "unknown error: Chrome failed to start: exited abnormally"
options.add_argument '--no-sandbox'
# BREAKS THINGS if uncommented
# options.add_argument '--remote-debugging-port=4444'
options.add_argument '--headless'
options.add_argument '--window-size=1600,2400'
options.add_preference('profile.default_content_settings.popups', 0)
options.add_preference('download.default_directory', DownloadHelpers::PATH.to_s)
Capybara::Selenium::Driver.new(
app,
clear_local_storage: true,
clear_session_storage: true,
browser: :chrome,
options: options,
desired_capabilities: capabilities,
)
end
Since chrome 67 and chromedriver 2.39, chromedriver now correctly uses the port you specify with --remote-debugging-port. This removes quite a bit of complexity from my answer above. The steps I now take, which work for my use case of needing to configure download settings using chrome_remote, are as follows:
It makes uses of a nodejs library, crmux - which allows multiple clients to connect to the remote debug port of chrome at the same time.
Get nodejs installed first: Nodejs v9.7.0 works fine
Install crmux by running npm install crmux -g
Before you start chromedriver (Capybara::Selenium::Driver.new), you need to spawn a separate thread that will fire up crmux, which will let both you and chromedriver communicate with chrome itself via the port you specified in Capybara (4444):
crmux --port=4444 --listen=4444
You may want to add a sleep 3 after the spawn command in the main script/thread to give time for crmux to start before you continue with your test startup.
You can then use chrome_remote (for example) to access chrome using port 4444, while capybara is doing its thing.
Updating my ChromeDriver fixed it for me. I didn't have to do anything else. Before it would hang when attempting to start the test.
Specifically I was on ChromeDriver 2.36 and I upgraded to ChromeDriver 2.40. I don't think the Chrome version was a problem, since I was on Chrome 67 both before and after.
Here's how I'm registering the driver:
Capybara.register_driver :headless_chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless window-size=1280,960 remote-debugging-port=9222] }
)
Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
end
After that I ran my test with a debugger (binding.pry) placed where I wanted to inspect. Then when I hit the debugger I navigated to http://localhost:9222/ in a normal instance of Chrome and was able to follow a link to view what was happening in the headless Chrome instance, including the browser console output I needed.
Update: if using versions since Chrome 67/chromedriver 2.39, my alternative answer above provides a simpler solution
The core issue here is Chromedriver also uses the remote debugging port connection to communicate with Chrome. This uses the websocket protocol, which only supports a single-client connected at a time. Normally, when chromedriver starts the chromedriver process, it will choose a random free TCP port number and use this to access the remote debug port. If you specify --remote-debuggging-port=9222 however, Chrome will be opened with the debug port you have requested, but chromedriver will silently continue to try and open a connection using this random port number.
The solution I ended up with was heavily inspired by comment 20 in this chromedriver issue. It required quite a bit of code to get it working, but works solidly. It makes uses of a nodejs library, crmux - which allows multiple clients to connect to the remote debug port of chrome at the same time.
Get nodejs installed first: Nodejs v9.7.0 works fine
Install crmux by running npm install crmux -g
Before you start chromedriver (Capybara::Selenium::Driver.new), you need to spawn a separate thread that will do a few things: look for the remote debug port chromedriver is trying to use to connect to chrome, and then use this to fire up crmux. Once this has happened Capybara etc will work as normal.
My separate thread runs a ruby script that first executes a netstat command repeatedly until it finds the relevant entry for chromedriver (TCP status is SYN_SENT). This separate thread must continue to run in the background while chrome is up and running.
The code for this is:
$chrdrv_wait_timeout = 60
$chrdrv_exe = "chromedriver.exe"
def get_netstat_output
stdout = `netstat -a -b -n`
stat_lines = stdout.split("\n")
stat_lines
end
def try_get_requested_port
socket_state = "SYN_SENT" # i.e. sent with no reply
statout = get_netstat_output
n = statout.length
i = 0
loop do
i += 1
# find lines relating to chromedriver
exe_match = /^ +\[#{$chrdrv_exe}\]$/.match statout[i]
if exe_match != nil
# check preceeding lines which should contain port info
port_match = /TCP.*:([0-9]+)\W+#{socket_state}/.match statout[i-1]
if port_match != nil
return port_match[1].to_i
end
end
break unless i < n
end
return nil
end
def get_tcp_port_requested_by_chromedriver
i = 1
loop do
puts "Waiting for #{$chrdrv_exe}: #{i}"
port = try_get_requested_port
if port != nil
return port
end
break unless i < $chrdrv_wait_timeout
sleep 1
i += 1
end
raise Exception, "Failed to get TCP port requested by #{$chrdrv_exe} (gave up after #{$chrdrv_wait_timeout} seconds)"
end
(I'm working in Windows: for Mac/Linux the netstat syntax/output is probably different so the code will need adjustment; the key thing is you need it to output the executable owner of each connection entry - and parse the bit relating to chromedriver to get the port in question).
Once this has found the random port (I'll use 12225 as an example), the background ruby script can then execute a crmux process, which will reunite chromedriver with chrome itself via the port you specified in Capybara (4444):
crmux --port=4444 --listen=12225
Finally, this separate script saves the discovered listen port to a text file. This allows the main script/thread that is running capybara to know the port number it can use to get access to chrome (via crmux's multiplexed connection) by reading in the port from that file. So you can then use chrome_remote to access chrome using port 12225, for example, while capybara is doing its thing.

IE capabilities with Jenkins

I have installed:
selenium grid 2.53.0 hub +node for IE;
Jenkins;
IE 11.
When I try to run a build for IE via batch command with variable BROWSER=ie I'm getting next error:
Error forwarding the new session cannot find : Capabilities [{browserName=internetexplorer, version=null}] (org.openqa.grid.common.exception.GridException) (Selenium::WebDriver::Error::UnknownError)
What can be wrong? Because when I run my tests not via grid everything is ok.
If I connect node for chrome and specify chrome everything is ok too.
Try this:
DesiredCapabilities cap = null;
WebDriver driver = null;
cap = DesiredCapabilities.internetExplorer();
cap.setBrowserName("internet explorer");
cap.setPlatform(Platform.WIN8); //specify the platform
driver = new RemoteWebDriver(new URL(nodeURL), cap);
I resolved this.
I specified incorrectly BROWSER value in Jenkins. Must be BROWSER="internet explorer"

How do you give WWW::Mechanize::Firefox permission to launch Firefox?

I'm on a Mac. I've got a simple Perl script that uses WWW::Mechanize::Firefox to pull up a web page.
The script works perfectly when Firefox is already open and running on my computer. Here's the line the creates the object:
my $mech = WWW::Mechanize::Firefox->new(
launch => '/Applications/Firefox.app'
);
However, when Firefox is shutdown and I run the script, I get the following error:
exec failed: Permission denied at /Library/Perl/5.12/MozRepl/RemoteObject.pm line 463
at /Library/Perl/5.12/MozRepl/RemoteObject.pm line 463
What do I do to give the perl script permission to launch Firefox?
Try:
my $mech = WWW::Mechanize::Firefox->new(
launch => '/Applications/Firefox.app/Contents/MacOS/firefox'
);
/Applications/Firefox.app is the application wrapper and is a directory that contains the various files that make up the application. The file at Contents/MacOS/firefox within the application wrapper is the main executable of the application.

Resources