Selenium sometimes fails to close after calling driver.quit() when it gets stuck at "connection to server was reset" or when it simply "stops responding". When this occurs, it is impossible kill the process (browser) using WebDriver directly, the only way I can think of is by retrieving the PID of browser and destroying process via:
String cmd = "taskkill /F /PID " + pidOfBrowser;
Runtime.getRuntime().exec(cmd);
I'm aware of this response which suggests retrieving a list of processes currently running and filtering it down to Firefox browser. However, as someone pointed out in one of the comments this does not work if a user has many concurrent sessions running and only wishes to kill a select few.
Another solution suggested in the comment section of that thread is to get a list of PIDs from the browser before starting, and only close those that were not running before the test started (so any browser launched manually before tests began won't close)
However, this does not apply to my situation because I am launching many browsers at a time from my program (not manually) and only wish to close some of the browsers launched (the ones that are hanging and not responding to WebDriver anymore).
How can I get PID of a specific Firefox WebDriver session (ideally when it is created) so I can kill the process later if it hangs or gets 'stuck'?
Thanks!
You can kill the Browser instance initiated using Selenium retriving the PID from the capabilities object and then invoking getRuntime() with taskkill /PID as follows:
Code Block:
import java.io.IOException;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
public class Kill_Firefox_PID {
public static void main(String[] args) throws IOException {
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
Capabilities cap = ((RemoteWebDriver) driver).getCapabilities();
System.out.println("moz:processID value is : "+cap.getCapability("moz:processID"));
Runtime.getRuntime().exec("taskkill /PID "+cap.getCapability("moz:processID"));
}
}
Console Output:
moz:processID value is : 8492
In Java 9+ version you can do like this. It is taken from here
public static void main(String[] args) {
ProcessHandle.allProcesses()
.forEach(process -> System.out.println(processDetails(process)));
}
private static String processDetails(ProcessHandle process) {
return String.format("%8d %8s %10s %26s %-40s",
process.pid(),
text(process.parent().map(ProcessHandle::pid)),
text(process.info().user()),
text(process.info().startInstant()),
text(process.info().commandLine()));
}
private static String text(Optional<?> optional) {
return optional.map(Object::toString).orElse("-");
}
and then get info of the process like above. There is a totalCpuDuration​() method in ProcessHandle.Info class. use this to see which process is taking long and then act accordingly. There are other methods in that class that can be beneficial in your scenario. Hope this helps.
Related
I'm trying to kill my network in the middle of a test. and when I kill the network, the system should prompt a dialog saying network is gone. When I do this manually, I get the dialog. And I used the following code,
public void exitBrowserTab() throws IOException {
WebDriver driver = new ChromeDriver();
driver.get("url");
driver.findElement(By.id("login-username")).sendKeys("username");
driver.findElement(By.id("login-password")).sendKeys("password");
driver.findElement(By.id("signin-button")).click();
Map map = new HashMap();
map.put("offline", true);
map.put("latency", 5);
map.put("download_throughput", 500);
map.put("upload_throughput", 1024);
CommandExecutor executor = ((ChromeDriver)driver).getCommandExecutor();
Response response = executor.execute(new Command(((ChromeDriver)driver).getSessionId(), "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map))));
}
When I run this code, it won't give me that dialog. but, when I refresh the page, it tells me that there's no network.
What did I do wrong?
Manual Steps -
Go to the url
Successful login
Network drop
Dialog appears
I could turn of internet using the bash command,
Runtime.getRuntime().exec("cmd /c ipconfig /release");
and turn it back on using,
Runtime.getRuntime().exec("cmd /c ipconfig /renew");
This will automatically turn off your wifi and turn it on again.
I want to kill the browser instance (chrome) that was opened by web driver previously. How would I do that? In my code below, I intentionally didn't want to include quit() or close() as I want to leave the browser open. So every time I execute or run this program, I want to kill/close the previously opened browser and then start a new instance and leave it on. As a result, only one instance of browser should be open at a time. I am using Mac.
public static void main(String[] args){
String website = "http://www.google.com";
System.setProperty(".....");
WebDriver driver = new ChromeDriver();
driver.get(website);
}
The behaviour atm is that everytime I execute this, chrome instance will just pile up. What is the best way to avoid this? I am not doing this for testing purpose. I'm doing this because I want to automate a task. Thanks.
You can try out this code :
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "D:\\Automation\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.com/");
try{
Runtime.getRuntime().exec("TASKKILL /F /IM chrome.exe");
}
catch(IOException io){
System.out.println(io.getMessage());
}
}
Note : It will kill all instances of chrome that was previously opened along with the newly opened instance.
If I understand correctly, you are trying to automate a part of the flow, then let the automation program exit leaving the browser open for completing rest of the steps manually. In this case, the best way to ensure only one such window is open would be to keep the automation script idling until you are done with with manual task. Something like this at end of your main function:
try {
while(true) {
Thread.sleep(1000);
driver.getCurrentUrl();
}
} catch(Exception e) {}
Would ensure that the program remains alive as long as the browser window is open. You can continue manual process in the browser. Once you are done, you can close the browser, which would automatically end this process. Or before starting the new task, you kill the old one with ^c, which in turn closes the browser.
The second option without keeping the automation script idling, would be to find the process id of newly created browser instance. You can save the process id in some file in temporary folder. Every time your script starts, it'd check the the file, read pid from it, and if the process id exists, try to kill it before spawning a new browser window.
this my code open fire fox and get google
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class auto {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "//root//Desktop//jarselenium//geckodriver-v0.20.1-linux64/geckodriver");
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
//driver.get("https://www.easybooking.lk/login");
//driver.manage().timeouts().implicitlyWait(25, TimeUnit.SECONDS);
driver.get("https://www.google.com");
}
}
but when i run this code selenium open fire fox but wont get url im running this code in linux
As per the current implementation of Selenium v3.11.0, GeckoDriver 0.20.1 I don't see any major issue in your code block perhaps the trace logs would have helped us to understand your issue better. Having said that you need to follow the below mentioned steps :
As you are using Linux based System you need to pass the absolute path of the GeckoDriver within single forward slashes i.e. / as follows :
System.setProperty("webdriver.gecko.driver", "/root/Desktop/jarselenium/geckodriver-v0.20.1-linux64/geckodriver");
As GeckoDriver opens Firefox Browser client in maximized mode you need to omit the line of code :
driver.manage().window().maximize();
There is a test, smth like:
import //needed imports
public class TestClass{
WebDriver driver;
#Before
public void setUp() {
//some code
}
#Test
public void test1() {
//some code, including init of driver (geckodriver)
}
//#After
// public void tearDown() {
// driver.quit();
//}
}
So, I inited geckodriver, and successfully running my tests, using firefox instances.
But I want Not to close firefox window after each run, because I just want to analyse what I have, and fix any needed, after test run(I'm going to unComment driver.quit() later).
At the same time, each calling without closing the driver leads to over-impact to RAM on my PC(and does not matter - did I close browser manually, or not, after test):
So, question is:
is there any way to close the process(more precisely - do smth, which will close geckodriver.exe process in taskmgr) of "geckodriver", but will NOT close the browser after test finished? e.g., adding some method in test itself, whatever... This not impacts my work/test itself, I just want to add some optimizing.
As per your question commenting out driver.quit() just Not to close firefox window after each run, because I just want to analyse what I have won't be a part of best practices.
For any detailed analysis we can create log entries and take snapshots.
While automating through Selenium as per the best practices you should invoke the quit() method within the tearDown() {}. Invoking quit() DELETEs the current browsing session through sending "quit" command with {"flags":["eForceQuit"]} and finally sends the GET request on /shutdown EndPoint. Here is an example below :
1503397488598 webdriver::server DEBUG -> DELETE /session/8e457516-3335-4d3b-9140-53fb52aa8b74
1503397488607 geckodriver::marionette TRACE -> 37:[0,4,"quit",{"flags":["eForceQuit"]}]
1503397488821 webdriver::server DEBUG -> GET /shutdown
So on invoking quit() method the Web Browser session and the WebDriver instance gets killed completely. Hence you don't have to incorporate any additional steps which will be an overhead.
Solution
Still if you want to execute kill the dangling WebDriver instances e.g. GeckoDriver.exe instances you can use either of the following code block to kill any of the dangling WebDriver instances :
Java Solution(Windows):
import java.io.IOException;
public class Kill_ChromeDriver_GeckoDriver_IEDriverserver
{
public static void main(String[] args) throws Exception
{
Runtime.getRuntime().exec("taskkill /F /IM geckodriver.exe /T");
Runtime.getRuntime().exec("taskkill /F /IM chromedriver.exe /T");
Runtime.getRuntime().exec("taskkill /F /IM IEDriverServer.exe /T");
}
}
Python Solution (Windows):
import os
os.system("taskkill /f /im geckodriver.exe /T")
os.system("taskkill /f /im chromedriver.exe /T")
os.system("taskkill /f /im IEDriverServer.exe /T")
Python Solution(Cross Platform):
import os
import psutil
PROCNAME = "geckodriver" # or chromedriver or IEDriverServer
for proc in psutil.process_iter():
# check whether the process name matches
if proc.name() == PROCNAME:
proc.kill()
I've been struggling with this for the past few hours. I'm trying to install Selenium web driver and have been running into a bunch of errors which prevent me from running the test page. I'm pretty sure my most recent issue is with this code:
public static void main(String[] args) throws InterruptedException{
System.setProperty("webdriver.gecko.driver","C:/Users/theone/Downloads/geckodriver 2.exe");
Would really appreciate any feedback on second steps!
package automationFramework;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class FirstTestCase {
public static void main(String[] args) throws InterruptedException{
System.setProperty("webdriver.gecko.driver","C:/Users/theone/Downloads/geckodriver 2.exe");
// Create a new instance of the Firefox driver
WebDriver driver = new FirefoxDriver();
//Launch the Online Store Website
driver.get("http://www.store.demoqa.com");
// Print a Log In message to the screen
System.out.println("Successfully opened the website www.Store.Demoqa.com");
//Wait for 5 Sec
Thread.sleep(5);
// Close the driver
driver.quit();
}
}
You can setup Selenium with GeckoDriver either with webdriver.gecko.driver property or using environment properties. It would be good if you the latest version of Firefox, GeckoDriver and Selenium 3.0
Check out this article which provides setup using both these ways -
http://automationtestinghub.com/selenium-3-0-launch-firefox-with-geckodriver/
C:/Users/theone/Downloads/geckodriver 2.exe
There's a space in the path, it may work if you rename your file geckodriver2.exe.