0
votes

For our BDD tests we use Specflow that talks to selenium 2 webdriver (Chrome driver in this instance).

While running on local host (Yes, "it works on my machine" has came up in conversation a few times) the tests work fine. They setup the data and a new webdriver, do the test and then tear down the webdriver and data. Even if a test goes horribly wrong because I'm using correct attributes the tear down is always hit and therefore driver.Quit() is run destroying the browser and the driver.

The problem arises when I run it on our server [Windows Server 2008 r2] using our continuous integration [TeamCity]. For some reason it will start to run multiple driver instances which cause the tests to fail.

Has anyone ran into this problem before and found a fix? We need a solution that uses a driver that isn't HtmlUnitDriver.

Extra information:

  • Language = C#
  • Server = Windows Server 2008 R2
  • CI = TeamCity

EDIT: The Webdriver is set up by making sure that it isn't already created and then creates a new instance of the ChromeDriver. Pseudo/real code example bellow shows how its set up, sorry I cant show the full code as it has to much fluff in that we use for other options that we stick in (e.g zap or fiddler integration / language changes etc).

Setup

[SetUp]
[BeforeScenario()]
public static void BeforeWebScenario()
{
   if driver == null
     driver = new ChromeDriver();
   // Code to start page
}

Tear down

[TearDown]
[AfterScenario()]
public static void AfterWebScenario()
{
   try
   {
       driver.Quit();
   } catch (Exception)
   {
       throw Exception
   }
   driver = null;
}
2
Can you give a sample test that reproduces this? - Arran
Two questions: First, how are you starting the driver, by using ChromeDriver or RemoteWebDriver? Second, what does a typical constructor for the driver for your test look like? - JimEvans
Hi thanks for the interest, its quite difficult to give an example test as they use a framework I've created and operate the page object model (There's a lot of abstraction). I'll edit the post to show how the driver is set up. - Ankou

2 Answers

1
votes

I had this problem too. I fixed it by killing any running instances of chromedriver.exe in my testSetup() method. I used a VBScript and some Groovy code to run the scripts. Sorry this answer is kind of long.

I had this in my setUp):

if (wshsc.isRunningByCommandLineContents("chromedriver.exe"))
    wshsc.killProcessByCommandLineContents("chromedriver.exe")

isRunningByCommandLineContents:

If WScript.Arguments.Count = 1 Then

strCmdLine = WScript.Arguments.Item(0)
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objShell = CreateObject("WScript.Shell")
Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process")
If colProcessList.Count > 0 Then
    For Each objItem in colProcessList
        If (InStr(objItem.CommandLine, strCmdLine)) Then
            If (InStr(objItem.CommandLine, "cscript")) Then
            Else
                WScript.StdOut.Write "A process is running with " + strCmdLine + " in its command line = " + objItem.Name
            End If  
        End If
    Next
End If
End If

killProcessByCommandLineContents:

If WScript.Arguments.Count = 1 Then
strProcess = WScript.Arguments.Item(0)
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objShell = CreateObject("WScript.Shell")
Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process")

If colProcessList.Count > 0 Then
    For Each objItem in colProcessList
        If InStr(objItem.CommandLine, strProcess) Then
            If (InStr(objItem.CommandLine, "cscript")) Then
            Else
                WScript.StdOut.Write objItem.Name + " "
                objItem.Terminate()
            End If
        End If
    Next
Else
    WScript.StdOut.Write "No instances found running"
End If
Else
WScript.StdOut.Write "Bad Arguments"
End If

And the "run the scripts part":

public void killProcessByCommandLineContents(String contents) {
    List<String> arg = new ArrayList<String>()
    arg.add(contents)
    String [] args = arg.toArray()
    runScript("killByCmdLineContents.vbs", args, true)
}
public boolean isRunningByCommandLineContents(String contents) {
    List<String> arg = new ArrayList<String>()
    arg.add(contents)
    String [] args = arg.toArray()
    String returnData = runScript("IsRunningByCmdLineContents.vbs", args, true)
    if (returnData.contains(contents)) {
        return true
    } else {
        return false 
    }
}
public String runScript(String name, String [] args, boolean returnOutput) {
    String s = null;
    List<String> cmdLine = new ArrayList<String>()
    cmdLine.add("C://Windows//System32//cscript.exe")
    cmdLine.add(dir + "dir//src//com//misc//wshScripts//" + name)
    int index = 0
    args.each() {
        cmdLine.add(args[index])
        index++
    }

    try {
        String [] cmdLineArray = cmdLine.toArray()
        Process p = Runtime.getRuntime().exec(cmdLineArray, null);
        if (returnOutput) {
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            String dataToReturn
            Log.logger.info("Standard output: ");
            while ((s = stdInput.readLine()) != null) {
                Log.logger.info(s)
                dataToReturn = s // should get last line
            }

            Log.logger.info("Standard error: ");
            while ((s = stdError.readLine()) != null) {Log.logger.info(s);}
            return dataToReturn
        } else {
            return ""
        }
    }
    catch (IOException e) {
        Log.logger.info(e.message, e);
    }
}
0
votes

If you use the DriverService interface, hold onto the service until you're done with the driver, and call DriverService.stop() as well. For me, the driver.quit() wasn't enough because I was using DriverService as well.

driver.close();
driver.quit();
driverService.stop();