Sunday, March 27, 2016

Selenium WebDriver in C#: How to use the existing window of Chrome Browser.

Selenium WebDriver with all its advantages has some pain points. One of them is to reuse the existing window of your opened browser so that you can continue your test cases from where they are failed. Unfortunately there is no direct method to use the browser window. You have to be a little creative to come up with a solution.
Luckily, after spending hours of internet search and trial and error, I am finally able to devise a solution for this problem.
I have also posted a solution about re-using the existing window of Firefox here.
This solution is specifically for chrome browser. I have also attached the source code.
The steps are as follows.
  1. Create a class which is derived from RemoteWebDriver. We name this class as CustomRemoteDriver.cs.
  2. Override the constructor and Execute() method in the new class like this .
 public class CustomRemoteWebDriver : RemoteWebDriver
    {
        public static bool newSession = false;
        public static string capPath = @"c:\automation\sessionCap";
        public static string sessiondIdPath = @"c:\automation\sessionid";

        public CustomRemoteWebDriver(Uri remoteAddress, DesiredCapabilities desiredCapabilities)
            : base(remoteAddress, desiredCapabilities)
        {


        }




        /// 
        /// Store for the name property.
        /// 
        /// A  value representing the command to execute.
        /// A  containing the names and values of the parameters of the command.
        /// 
        /// A  containing information about the success or failure of the command and any data returned by the command.
        /// 
        protected override Response Execute(string driverCommandToExecute, Dictionary < string, object > parameters)
        {
            if (driverCommandToExecute == DriverCommand.NewSession)
            {
                if (!newSession)
                {
                   
                    var sidText = File.ReadAllText(sessiondIdPath);

                  
                    return new Response
                    {
                        SessionId = sidText,
                        
                    };
                }
                else
                {
                    var response = base.Execute(driverCommandToExecute, parameters);
                  
                    File.WriteAllText(sessiondIdPath, response.SessionId);
                    return response;
                }
            }
            else
            {
                var response = base.Execute(driverCommandToExecute, parameters);
                return response;
            }
        }
    }
This above code is just basically saving the session id in a file when new session is created and in case this is not a new session, it is reading the session id  from the saved file and returning the response based on this session id.
  1. In your [TestInitialize] method, initialize your CustomRemoteWebDriver. Start the chromedriver with Process.Start(). For every test case, check if process is already started. If yes, then Attach the custom remote webdriver to this process, otherwise start the new process. Like this.
  [TestInitialize]
        public void MyTestInitialize()
        {
            if (ConfigurationManager.AppSettings["UseChromeDebugging"] == "true")
            {

                var pr = Process.GetProcessesByName("chromedriver");
                if (pr.Length > 0)
                {
                    CustomRemoteWebDriver.newSession = false;
                    var driver = new CustomRemoteWebDriver(new Uri("http://localhost:9515"), DesiredCapabilities.Chrome());
                    WebDriver = driver;
                }

                else
                {
                    Process.Start(ConfigurationManager.AppSettings["ChromeDriverPath"]);
                    CustomRemoteWebDriver.newSession = true;
                    var driver = new CustomRemoteWebDriver(new Uri("http://localhost:9515"), DesiredCapabilities.Chrome());
                    WebDriver = driver;

                }
            }

            else
            {
                //normal execution
                WebDriver = new ChromeDriver(DRIVER_PATH);                
            }
            
            
        }
  • You are good to go. Now create two test methods. In the first method navigate to google.com and in the second method, search something in google search box.
  • Build the solution, in the test view window, you will be able to see two test methods
  • Execute the first method, chrome driver command prompt window will open,  a chrome window will open and it will navigate to google.com. Test case will be passed.
  • Now the real magic will happen, Execute the second method, It will use the existing window of chrome, No new window will open and google will search the given text.

Full source code will be attached soon. Please do give your feedback. I hope I can make lives of some test automation engineers easier with this approach :)

19 comments:

  1. Great :) i have one question..
    Do you know how to convert the chromedriver source code to the exe file (chromedriver.exe) ?

    ReplyDelete
  2. Hi, thanks for your solution. I tried to use this, but i get an error:
    Exception in thread "main" org.openqa.selenium.remote.SessionNotFoundException: no such session

    ReplyDelete
  3. Hello, thank you for the code. I'm beginner so maybe I have stupid question, but I have also some issues with this line:
    "protected override Response Execute (string driverCommandtoExecute, Dictionary parameters)"
    The "execute" issue: there no suitable method found to override
    and the "dictionary", using the generic type 'Dictionary requires 2 type arguments.
    So from were are those parameters? ..
    and maybe I haven't right right References Added...which are needed for this code?


    Thank you very much

    ReplyDelete
    Replies
    1. Use Dictionary and it will work like a charm.

      Delete
    2. Hi,

      I also have the Dictionary problem. The rest of the code seems fine but i have an error in Dictionary because it "requires 2 type arguments".
      I'm using "Dictionary" with the reference "System.Collections.Generic". Is it the wrong one?

      Thanks for the help.

      Delete
    3. This comment has been removed by the author.

      Delete
    4. This comment has been removed by the author.

      Delete
    5. I am just setting this up, but depending on your version of .Net it may require a "Dictionary<string, object> parameters"

      Delete
    6. I am figuring out that some of this sample code is being escaped from this post, that is why the dictionary types arguments do not show up, also missing is "\" from the file paths.

      Delete
    7. Thanks Matthew for pointing out. I have fixed this.

      Delete
    8. I took your code and extended it Firefox and Internet Explorer and removed the app config settings, email me if you would like a copy matthew@matthewbierman.com

      Delete
  4. For those that have asked: https://github.com/matthewbierman/RemoteWebDriverExtended

    ReplyDelete
  5. Hi Mohammad,

    Thanks for sharing your knowledge.

    Actually I am using selenium with Java and you have written this blog with C#. So if it is possible for you to share the complete code as above mentioned code is not complete.

    It would really helpful for me or If you have done the same thing using java then its a best for me. So would request you to please share any one of the solution at "manish1561988@gmail.com".

    A big thanks in Advance..!!

    ReplyDelete
  6. Hi Mohammad,

    I also want the code in java. Please share me @ swapnil.surwase@gmail.com

    @Manish - if you have it , you too can share with me

    ReplyDelete
  7. This is an awesome solution! I was able to get this running with my code perfectly fine yesterday, however today I'm getting the error without having changed any of my code:

    "'Unexpected error. System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:9515"

    Would you happen to know the cause of this, and the fix?

    ReplyDelete
  8. Awesome solution..!! If anyone has the code in java. Please share @ kamalvdm@gmail.com

    ReplyDelete
  9. hi, i try the code above but in every run the:
    ConfigurationManager.AppSettings["UseChromeDebugging"] always equal to null.
    when you iniliaze it?

    ReplyDelete
    Replies
    1. Sorry, apparently the code did not display. You initialize it in the "app.config" file in the appSettings section, add key="UseChromeDebugging" value="true".

      Hope this helps

      Delete

Testing Challenge

Can you find more than 20 defects in the below image? Write your defects in the comments section.