简体   繁体   中英

Running one tests on multiple browsertypes in parallel using Selenium, NUnit and C#

What I'm using:

  • Selenium WebDriver (v3.2.0)
  • NUnit (v3.6.0)
  • C#

I've found online how to run a single test using multiple browser types in parallel, my code is as follows and this works:

namespace MultipleBrowserTest
{
    [TestFixture(typeof(FirefoxDriver))]
    [TestFixture(typeof(ChromeDriver))]
    [TestFixture(typeof(InternetExplorerDriver))]
    [TestFixture(typeof(EdgeDriver))]
    public class SiteLoadsTest<TWebDriver> where TWebDriver : IWebDriver, new()
    {
        private IWebDriver _driver;

        [Test]
        public void MultipleBrowserTests()
        {
            _driver = new TWebDriver();

            _driver.Navigate().GoToUrl("https://google.com/");

            Assert.AreEqual("https://google.com/", _driver.Url);
        }

        [TearDown]
        public void FixtureTearDown()
        {
            _driver?.Quit();
            if (_driver != null) _driver.Dispose();
        }
    }
}

However, I want to make this more maintainable so that every test class the QA doesn't have to format the class with the 'where...' part ( public class SomeUITestClass<TWebDriver> where TWebDriver : IWebDriver, new() ). I was looking at making the test inheriting a Browser class like this:

public class Browsers<TWebDriver> where TWebDriver : IWebDriver, new()
{

    private IWebDriver Browser { get; set; }

    public IWebDriver Driver
    {
        get
        {
            if (Browser == null)
            {
                throw new NullReferenceException(
"The WebDriver browser instance was not initialized.");
            }
            return null;
        }
        set { Browser = value; }
    }

    public void LaunchDriver()
    {
        Browser = new TWebDriver();
    }
}

And editing my test to be like this:

namespace MultipleBrowserTest
{
    [TestFixture(typeof(FirefoxDriver))]
    [TestFixture(typeof(ChromeDriver))]
    [TestFixture(typeof(InternetExplorerDriver))]
    [TestFixture(typeof(EdgeDriver))]
    public class SiteLoadsTest_InheritedBrowser : Browsers<>
    {
        [SetUp]
        public void Setup()
        {
            LaunchDriver();
        }

        [Test]
        public void MultipleBrowserTests()
        {

            Driver.Navigate().GoToUrl("https://google.com/");
            Assert.AreEqual("https://google.com/", Driver.Url);
        }

        [TearDown]
        public void FixtureTearDown()
        {
            Driver?.Quit();
            if (Driver != null) Driver.Dispose();
        }
    }
}

However I don't know what to pass into Browsers<>. If I don't pass anything I get "Unexpected use of an unbound generic name". If I pass in IWebDriver I am getting 'IWebDriver' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TWebDriver' in the generic type or method 'Browsers'.

I've got to the extent of my C# skills (as a QA) and I'm not sure how to resolve this or even whether it's resolvable! Any help would be much appriciated.

So with the amazing help of a fellow QA, we've worked out how to do this using reflection. We do have to add the constructor for our test (see below the Test Class):

namespace MultipleBrowserTest
{
[TestFixture(typeof(FirefoxDriver))]
[TestFixture(typeof(ChromeDriver))]
[TestFixture(typeof(InternetExplorerDriver))]
[TestFixture(typeof(EdgeDriver))]
public class SiteLoadsTest_InheritedBrowser : Browsers_Reflection
{
public SiteLoadsTest_InheritedBrowser(Type type) : base(type)
    {
    }

    [Test]
    public void MultipleBrowserTests()
    {
        Driver.Navigate().GoToUrl("https://google.com/");
        Driver.Url.ShouldContain("google");
    }

}
}

And this is the Browser class that we'll keep in our framework:

namespace MultipleBrowserTest
{
    public class Browsers_Reflection
    {       
        public Browsers_Reflection(Type type)
        {
            Driver = (IWebDriver)Activator.CreateInstance(type);
        }
        private IWebDriver Browser { get; set; }

        public IWebDriver Driver
        {
            get {
                if (Browser == null)
                    throw new NullReferenceException(
                        "The WebDriver browser instance was not initialized.");
                return Browser;
            }
            set { Browser = value; }
        }
    }
}

Edit: We are also looking at using UnityContainer which we were having issues with but have worked it out, here is the code:

namespace MultipleBrowserTest
{
    public class Browsers_UnityContainer
    {
        public Browsers_UnityContainer(Type type)
        {
        _unityContainer.RegisterType(typeof(IWebDriver), type, new InjectionConstructor());
        Browser = _unityContainer.Resolve<IWebDriver>();

        }

        private IWebDriver Browser { get; set; }
        private readonly UnityContainer _unityContainer = new UnityContainer();

        public IWebDriver Driver
        {
            get { return Browser; }
            set { Browser = value; }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM