14

I would really appreciate a guide on how to connect to an already open browser using Selenium Webdriver via C#.

This issue eats around 30% of my script development time!

Yi Zeng
  • 29,005
  • 11
  • 87
  • 116
Andrey
  • 550
  • 3
  • 8
  • 20
  • I dont thinks that is possible – Tarun Oct 14 '11 at 10:10
  • why dont you just create a test suite and use same selenium instance? – Çağdaş Oct 14 '11 at 10:21
  • How can I do that? After the test has stopped, how do you connect to an existing browser? – Andrey Oct 14 '11 at 11:20
  • Ever find a solution to this? – atwellpub Dec 30 '11 at 22:28
  • No. I'm not sure about the answers below, please comment back if something works for you – Andrey Feb 03 '12 at 16:06
  • 1
    If you started a test and then didn't quit the browser you could potentially re-attach to it IF you keep track of the Selenium SessionId and port on which to connect to the browser. Then you'd have to extend the RemoteWebDriver to allow you to pass in your own SessionId and point the url to the port you kept track of. NOTE: This could only possibly work if you've started the browser with Selenium. – lukeis Mar 02 '12 at 17:43
  • Andrey, Have you tried my answer ? – joinsaad Aug 10 '15 at 11:25
  • It is indeed possible. by using a derived class of remote webdriver. Please see this post http://binaryclips.com/2015/08/25/selenium-webdriver-in-c-how-to-use-the-existing-window-of-chrome-browser/ – joinsaad Aug 25 '15 at 11:27

5 Answers5

1

Refer to Selenium Issue 18. This is a very popular feature request, which has unfortunately not been implemented. The comments suggest a few workarounds for now, I haven't tried them but you might find something useful.

prestomanifesto
  • 11,600
  • 5
  • 30
  • 49
1

You can specify starting and closing browser in [TestFixtureSetUp] and [TestFixtureTearDown] and remove it from [SetUp] and [TearDown]. All the tests in [TestFixture] will be run in the same browser. So if you have for example 10 classes and each of them contains 5 tests, instead of 50 browser's openings and closings there will be only 10.

    public IWebDriver driver { get; private set; };

    [TestFixtureSetUp]
    public void TestFixtureSetup()
    {
        driver = new FirefoxDriver();
        driver.Navigate().GoToUrl("http://www.google.com/");
    }

    [TestFixtureTearDown]
    public void TestFixtureTearDown()
    {
         driver.Quit();
    }

If you want to open and close your browser once, you can inherit [TestFixtureSetUp] and [TestFixtureTearDown] methods from base class and if you have one test class that is executed before others (A_test) and one that is executed last (Z_test) you can set and unset some flags that will tell if we should start browser or not:

namespace Tests
{
[TestFixture]
public abstract class Test
{
    private static bool _flagSetUp;
    private static bool _flagTearDown;
    public IWebDriver driver { get; private set; };

    protected Test()
    {
    }

    public static void SetFlag(bool flagSetUp, bool flagTearDown)
    {
        _flagSetUp = flagSetUp;
        _flagTearDown = flagTearDown;
    }

    [TestFixtureSetUp]
    public void TestFixtureSetup()
    {
        if(_flagSetUp)
        {
            driver = new FirefoxDriver();
            driver.Navigate().GoToUrl("http://www.google.com/");
            _flagSetUp = false;
        }
    }

    [TestFixtureTearDown]
    public void TestFixtureTearDown()
    {
        if(_flagTearDown)
        {
            driver.Quit();
        }
    }
}

namespace Tests
{
[TestFixture(new object[] { true, false })]
public class A_Test : Test
{
    public A_Test(bool flagSetUp, bool flagTearDown)
    {
        SetFlag(flagSetUp, flagTearDown);
    }

    [Test]
    public void Test1()
    {
       ...
    }
}

namespace Tests
{
[TestFixture(new object[] { false, true })]
public class Z_Test : Test
{
    public A_Test(bool flagSetUp, bool flagTearDown)
    {
        SetFlag(flagSetUp, flagTearDown);
    }

    [Test]
    public void Test2()
    {
       ...
    }
}

The last workaround looks like not good solution. Althouth first workaround also doesn't guarantee 100% tests isolation (btw don't forget to write driver.Navigate().GoToUrl("http://www.google.com/"); as first step for each test). So probably the best solution will be parallel execution and Setup, Teardown methods for each test.

Aleh Douhi
  • 1,894
  • 1
  • 14
  • 13
0

You can run your tests in parallel, but that is a just a good idea when you're ready to run all of your tests. Below is an idea that you can use while you're developing and running newly compiled code.

Serialize your WebDriver {browser} instance object into a file (or in memory in a Windows service if you prefer), and then retrieve (de-serialize) that file into an object each time you launch WebDriver. It takes a little massaging though, of the WebDriver source code.

When I get some time, I will update my answer here. I hope Stack Overflow will allow me to paste as much code changes as it took. Plus, I should still give credit to Erik in his answer and comments. Although it was my idea to begin with (for making WebDriver faster).

.NET: Serializing object to a file from a 3rd party assembly (to make Selenium WebDriver faster)

==========

Simple logic:

  • if serialized object file doesn't exist ==> open browser instance as normal, and create the file

  • if serialized object file exists ==> deserialize file into object ==> set browser instance equal to deserialized object (casted correctly of course)

==========

The other requirement is that you put in a condition into your method decorated with the [TearDown] attribute so your browser doesn't close when the script (test) finishes. The first time through, it'll take time to open it up. But once that browser window is open, you're good to go.

[TearDown]
public void TeardownTest()
{
    try
    {
        if (Config.CLOSE_BROWSER_AFTER_TEST_CASE)
        {
            driver.Quit();
        }
    }
    catch (Exception)
    {
        // Ignore errors if unable to close the browser
    }
    Assert.AreEqual("", verificationErrors.ToString());
}
Community
  • 1
  • 1
MacGyver
  • 16,700
  • 37
  • 145
  • 233
  • instead of serializing the whole object, you can just save the session id and reuse the session id to connect to already opened instance. please see this post. http://binaryclips.com/2015/08/25/selenium-webdriver-in-c-how-to-use-the-existing-window-of-chrome-browser/ – joinsaad Aug 25 '15 at 11:29
0

you can use below code sample to achieve this task

IWebDriver WebDriver = null;


try
{
  System.Uri uri = new System.Uri("http://localhost:7055/hub");
  WebDriver = new RemoteWebDriver(uri, DesiredCapabilities.Firefox());
  Console.WriteLine("Executed on remote driver");
}
catch (Exception)
{
  WebDriver = new FirefoxDriver();
  Console.WriteLine("Executed on New FireFox driver");
}

if a firefox browser is opened using a Firefox web driver, you can use Remote WebDriver to use that browser instance. So First I try to initialize a Remote Web Driver, if no instance is running, then try block will fail and Catch block will open the Firefox driver. Now for example, your script fails on a specific location and the browser remained open. Now again run that initialization code, the try block will pass this time and remote web Driver will use the existing opened browser. (No new browser window will open).

Put this initialization in your Test Startup method
This block of code saves my ample amount of time. I have also written a blog post on it. You can read it here. http://www.binaryclips.com/2016/03/selenium-web-driver-in-c-how-to.html

joinsaad
  • 763
  • 7
  • 13
  • In a few words, your solution is not to use Selenim Firefox driver, and use the stand-alone-server instead. Even if i don't really like to run Java app's, i've to admit that standalone server has few headaches. – m3nda Jun 27 '15 at 09:36
  • I use this approach, while developing the scripts. Not when I execute them. It saves time in debugging etc. I don't have to re-open the browser again and again after fixing my code each time with this approach – joinsaad Jun 30 '15 at 08:04
  • Also, in C#, we don't have to open a standalone server to use remote webDriver. If you have opened the browser with firefox driver, Remote webDriver can attach to this browser. – joinsaad Jun 30 '15 at 08:07
  • mmm interesting, didn't know about that feature. Do you need to supply any argument doing that? or does the remote just connect to the last instance? – m3nda Jul 01 '15 at 03:29
  • it juts connects to the last instance . You just have to provide this URL "http://localhost:7055/hub" – joinsaad Jul 07 '15 at 08:40
  • And can I choose the id too? – m3nda Jul 08 '15 at 20:06
  • Which id are you talking about? – joinsaad Jul 10 '15 at 10:06
  • Exactly the same ID used by the remoteWebdriver to create, handle or destroy the current sessions. Did u open that URL on a browser? Nothing happends with an active handle, or with an ID. I've look a bit inside and found `org.openqa.selenium.remote.server.handler.GetAllSessions`. Here is my id, but i don't know if i can invoke it to rehuse certain session instead the lastest session used. – m3nda Jul 10 '15 at 15:43
  • I did not use any id the first time as well. Why don't you just try my code on visual studio? – joinsaad Jul 13 '15 at 11:03
  • Okey you don't know about the id, no problem. – m3nda Jul 14 '15 at 02:03
  • Why my answer is downvoted? Can anyone explain please ? – joinsaad Jul 15 '15 at 07:32
  • And I do know about the id. Please see this answer about getting a session id in c#.http://stackoverflow.com/questions/15767066/get-session-id-for-a-selenium-remotewebdriver-in-c-sharp – joinsaad Jul 15 '15 at 07:34
0

Since time is your primary issue and this is not natively supported. Why adopt an alternative approach. Develop/implement a basic connect & navigate to home page use case. Then extend that class for your more complex use case. Alternatively make Test case controller, then use a factory to instantiate your detailed tests, passing the webdriver instance into the test case.

Martin Spamer
  • 5,180
  • 26
  • 44