Test if element is present - c#

I've added Selenium WebDriver to the Powershell and create WebDriver instance:
Add-Type -path C:\Windows\net40\WebDriver.dll
$driver = New-Object OpenQA.Selenium.Firefox.FirefoxDriver
$driver.Url = "https://www.google.com"
Now I want to find input field:
$singleRecord = ($driver.FindElementByCssSelector("input.gbqfif"))
I found several examples how to "Test if element is present" in C#:
Selenium WebDriver - Test if element is present
Selenium c# Webdriver: Wait Until Element is Present
There is also guide here:
IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("someDynamicElement"));
});
but I cannot create something similar in Powershell, and almost all my tests fails because it takes time for page to load elements.

I'm not familiar with this API but if you're having problems getting it to work in PowerShell but it works in C#, then just create C# wrappers around the functionality you need that you can access from PowerShell. You can do this fairly easily with the Add-Type command. From the first example in its doc page:
$source = #"
public class BasicTest {
public static int Add(int a, int b) {
return (a + b);
}
public int Multiply(int a, int b) {
return (a * b);
}
}
"#
Add-Type -TypeDefinition $source
[BasicTest]::Add(4, 3)
$basicTestObject = New-Object BasicTest
$basicTestObject.Multiply(5, 2)
As you find C# code for this API that does work, you can plop it into a C# wrapper class that you can call from PowerShell. The key is to avoid features PowerShell can't handle like C# static extension methods.

The only really safe way is:
static bool isElementPresent(dynamic element, By by)
{
try
{
element.FindElement(by);
return true;
}
catch (NoSuchElementException e)
{
return false;
}
}
This method accept both, an IWebDriver or an IWebElement, as a starting point for FindElement().
And so you can us it on a LINQ Query:
_infodeskSectionContracts = from contract in
_infodeskSection.FindElements(By.CssSelector(_base + " * ul.list.type-itemlist li"))
select new Contract
{
element = contract.FindElement(By.TagName("a")),
label = contract.FindElement(By.TagName("h4")).Text,
contractNumber = (isElementPresent(contract, By.TagName("p")) ? contract.FindElement(By.TagName("p")).Text : "0000")
};

Related

How do I run a test on multiple browsers at the same time? Selenium Grid, C#, Specflow, NUnit

I have been bouncing between guides and YouTube videos trying to implement Selenium Grid 2 on an existing project for a couple of days and I've gotten stuck, please help!
Our framework is Specflow 3.0.220, Selenium WebDriver 3.141.0, C#, NUnit 3.12.0, Selenium Grid selenium-server-standalone-3.141.59.
My initial objectives to implement Selenium Grid 2 are as follows:
Set up a hub and node(s) on my local machine = done.
Run a test through one of the nodes = done.
Run a test on all nodes simultaneously = headache.
Regarding item 2, I have set up two nodes, one is a Chrome node and one is a Firefox node. I can run a test through both of them, but not simultaneously.
I feel that I missing a piece of the puzzle here.
Here's the set-up:
Scenario Outline: Log in
Given I launch the site for <profile> and <environment> and <parallelEnvironment>
When I log in to the Normal account
Then I see that I am logged in
Examples:
| profile | environment | parallelEnvironment |
| parallel | Chrome75 | grid |
If profile is parallel and parallelEnvironment is grid, environment is ignored. The reason for parallelEnvironment is because we may still use Browserstack in the interim while setting up Selenium Grid.
These steps use relevant step files etc and page files (but not using Page Object Model as that's been deprecated).
The driver set-up is as follows:
namespace OurAutomation
{
[Binding]
public sealed class BrowserStack
{
private BrowserStackDriver bsDriver;
public static BrowserStackDriver bdriver;
[BeforeScenario]
public void BeforeScenario()
{
bsDriver = new BrowserStackDriver();
bdriver = bsDriver;
}
[AfterScenario]
public void AfterScenario()
{
bsDriver.Cleanup();
}
}
public class CustomRemoteWebDriver : RemoteWebDriver
{
public CustomRemoteWebDriver(Uri remoteAddress, ChromeOptions options) : base(remoteAddress, options)
{
}
public string getSessionID()
{
return base.SessionId.ToString();
}
}
public class BrowserStackDriver
{
private IWebDriver driver;
public static bool isBrowserStack = false;
public static string Platform;
public static string theEnvironment;
public static string sessionId;
public BrowserStackDriver()
{
}
public string GetString(string property)
{
if (TestContext.Parameters[property] == null)
{
throw new ArgumentException("Property does not exist, does not have a value, or a test setting is not selected. You may need to add the .runsettings file in Visual Studio (Test > Test Settings > Select Test Settings File).");
}
else
{
return TestContext.Parameters[property].ToString();
}
}
public IWebDriver Init(string profile, string environment, string parallelEnvironment)
{
String testString = GetString("BuildNumber");
theEnvironment = environment;
NameValueCollection caps = ConfigurationManager.GetSection("capabilities/" + profile) as NameValueCollection;
NameValueCollection settings = ConfigurationManager.GetSection("environments/" + environment) as NameValueCollection;
ChromeOptions chromeOptions = new ChromeOptions();
if (profile == "single")
{
// logic to invoke relevant browser locally based on Specflow parameter 'profile'
Thread.Sleep(3000);
}
else if (profile == "parallel")
{
if (parallelEnvironment == "browserstack")
{
foreach (string key in caps.AllKeys)
{
chromeOptions.AddAdditionalCapability(key, caps[key]);
}
foreach (string key in settings.AllKeys)
{
chromeOptions.AddAdditionalCapability(key, settings[key]);
}
string username = Environment.GetEnvironmentVariable("BROWSERSTACK_USERNAME");
if (username == null)
{
username = ConfigurationManager.AppSettings.Get("user");
}
string accesskey = Environment.GetEnvironmentVariable("BROWSERSTACK_ACCESS_KEY");
if (accesskey == null)
{
accesskey = ConfigurationManager.AppSettings.Get("key");
}
chromeOptions.AddAdditionalCapability("browserstack.user", username);
chromeOptions.AddAdditionalCapability("browserstack.key", accesskey);
chromeOptions.AddAdditionalCapability("browserstack.local", "true");
chromeOptions.AddAdditionalCapability("build", GetString("BuildNumber"));
chromeOptions.AddAdditionalCapability("name", TestContext.CurrentContext.Test.MethodName);
chromeOptions.AddAdditionalCapability("project", GetString("Project"));
BrowserStackDriver.isBrowserStack = true;
driver = new CustomRemoteWebDriver(
new Uri("http://" + ConfigurationManager.AppSettings.Get("server") + "/wd/hub/"), chromeOptions);
CustomRemoteWebDriver browserRemoteDriver = driver as CustomRemoteWebDriver;
sessionId = browserRemoteDriver.getSessionID();
}
else if (parallelEnvironment == "grid")
{
driver = new RemoteWebDriver(new Uri("http://000.00.00.00:4444/wd/hub"), chromeOptions);
}
}
return driver;
}
public void Cleanup()
{
Thread.Sleep(2000);
if (isBrowserStack)
{
Log.Status status = (TestContext.CurrentContext.Result.Message == null) ? Log.Status.Passed : Log.Status.Failed;
string reason = (TestContext.CurrentContext.Result.Message == null) ? "Passed" : "Error see exception";
Log.UpdateTestStatus(status, reason, sessionId);
}
driver.Quit();
driver = null;
}
}
}
So in here...
else if (parallelEnvironment == "grid")
{
driver = new RemoteWebDriver(new Uri("http://000.00.00.00:4444/wd/hub"), chromeOptions);
}
...I enter the address of one of the nodes and the test gets conducted. However, I just want to send the test to the hub and for it to then execute that one test on all active nodes in their related browsers simultaneously. How do I achieve that? The guides and videos only seem to be taking me so far.
thank you
UPDATE:
So I'm inching further in the right direction I think. Had to roll this back to basics, so I can see how to implement this in my existing project. I've made this work in my grid: https://github.com/teixeira-fernando/Parallel-Execution-with-Selenium-Grid
However I note that I need to add attributes to the tests (to run one test on multiple browsers simultaneously)...
namespace Tutorial_parallel_execution
{
[TestFixture(BrowserType.Chrome)]
[TestFixture(BrowserType.Firefox)]
[TestFixture(BrowserType.Opera)]
[TestFixture(BrowserType.IE)]
[Parallelizable(ParallelScope.Fixtures)]
public class GoogleTesting : Hooks
{
public GoogleTesting(BrowserType browser) : base(browser)
{
}
[Test]
public void GoogleTest()
{
Driver.Navigate().GoToUrl("http://www.google.com");
Driver.FindElement(By.Name("q")).SendKeys("selenium");
Driver.FindElement(By.Name("btnK")).Click();
Assert.That(Driver.PageSource.Contains("Selenium"), Is.EqualTo(true),
"The text selenium doenst exist");
}
}
}
However, since my project started complaining similarly to this SpecFlow Visual Studio extension attempted to use SpecFlow code-behind generator 1.9, I started using SpecFlow.Tools.MsBuild.Generation and lost access to the tests (the code-behind files) in order to add the attributes. The only attribute I can add is [Parallelizable(ParallelScope.Fixtures)] but I have to put this in AssemblyInfo.cs - the other attributes can't be added there.
Do I need to be downgrading the versions of Specflow/Selenium etc in order to make this work??
I was able to strip out the code necessary to implement parallel execution using ThreadLocal from https://github.com/minhhoangvn/AutomationFramework
Add this to your AssemblyInfo.cs file:
[assembly: Parallelizable(ParallelScope.Fixtures)]
[assembly: LevelOfParallelism(4)]
Where you see 4 is the number of tests you want to run at the same time. So if you have 2 nodes, but you want to run 4 tests at the same time, then each node will get 2 chrome browsers.
When you use MsBuild.Generation the feature.cs files are still there, they just don't show up in visual studio.
You could try adding this to your Hooks.cs file when creating the driver:
ScenarioContext _scenarioContext;
IWebDriver _currentWebDriver;
_currentWebDriver = new RemoteWebDriver(new Uri(Utilities.SeleniumHub), options.ToCapabilities(), TimeSpan.FromMinutes(3));
_scenarioContext.ScenarioContainer.RegisterInstanceAs<IWebDriver>(_currentWebDriver);
And then this when you are done with the scenario:
[AfterScenario]
public void CloseBrowserAfterScenario()
{
string driver_process_name = null;
string browser_process_name = null;
switch (browser)
{
case "Chrome":
driver_process_name = "chromedriver.exe";
break;
case "IEX64":
case "IEX86":
driver_process_name = "IEDriverServer.exe";
break;
case "Edge":
driver_process_name = "MicrosoftWebDriver.exe";
browser_process_name = "MicrosoftEdge.exe";
break;
case "Firefox":
driver_process_name = "geckodriver.exe";
break;
default:
LogMessage(browser + "is not found or not supported... Please update the TestUI.dll.Config File");
break;
}
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName(driver_process_name);
foreach (System.Diagnostics.Process app_process in process)
{
if (!string.IsNullOrEmpty(app_process.ProcessName))
{
try
{
app_process.Kill();
}
catch
{
FunctionalUtil.LogMessage("app_process.Kill(); failed in CloseBrowserAfterScenario");
}
}
}

How to use Wait.Until with Selenium if I already have the element with FindsBy

I am using Wait.Until method to check if my page is already loaded or if it still loading .
This is how it looks like :
protected IWebElement FindElement(By by, int timeoutInSeconds)
{
StackTrace stackTrace = new StackTrace();
string callingMethod = stackTrace.GetFrame(1).GetMethod().Name;
string message = "Error finding element in method: " + callingMethod;
if (timeoutInSeconds > 0)
{
try
{
WebDriverWait wait = new WebDriverWait(chromeDriver, TimeSpan.FromSeconds(timeoutInSeconds));
wait.Until(ExpectedConditions.ElementIsVisible(by));
Thread.Sleep(800);
}
catch (Exception)
{
Assert(false, message);
throw new Exception(message);
}
}
return chromeDriver.FindElement(by);
}
But now we want to change our automation pages and start using FindBy foe every element , like this :
[FindsBy(How = How.Id, Using = "username")]
public IWebElement _logInUserName;
but wait.until needs "by" element .
I saw the abstract solution for this problem , but it is no good for my case .
can anyone know another solution that i can use ?
There is a ByFactory class in Selenium .NET solution. I took this implementation to achieve what you want:
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
namespace SeleniumPlayground
{
public static class SeleniumHelper
{
public static FindsByAttribute GetFindsByAttributeFromField(Type pageObject, string iwebElementFieldName)
{
FieldInfo fi = pageObject.GetField(iwebElementFieldName);
FindsByAttribute attr = (FindsByAttribute)fi.GetCustomAttributes(typeof(FindsByAttribute), false).FirstOrDefault();
return attr;
}
public static By GeyByFromFindsBy(FindsByAttribute attribute)
{
var how = attribute.How;
var usingValue = attribute.Using;
switch (how)
{
case How.Id:
return By.Id(usingValue);
case How.Name:
return By.Name(usingValue);
case How.TagName:
return By.TagName(usingValue);
case How.ClassName:
return By.ClassName(usingValue);
case How.CssSelector:
return By.CssSelector(usingValue);
case How.LinkText:
return By.LinkText(usingValue);
case How.PartialLinkText:
return By.PartialLinkText(usingValue);
case How.XPath:
return By.XPath(usingValue);
case How.Custom:
if (attribute.CustomFinderType == null)
{
throw new ArgumentException("Cannot use How.Custom without supplying a custom finder type");
}
if (!attribute.CustomFinderType.IsSubclassOf(typeof(By)))
{
throw new ArgumentException("Custom finder type must be a descendent of the By class");
}
ConstructorInfo ctor = attribute.CustomFinderType.GetConstructor(new Type[] { typeof(string) });
if (ctor == null)
{
throw new ArgumentException("Custom finder type must expose a public constructor with a string argument");
}
By finder = ctor.Invoke(new object[] { usingValue }) as By;
return finder;
}
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Did not know how to construct How from how {0}, using {1}", how, usingValue));
}
}
And here's an example usage:
public class Page
{
private IWebDriver driver;
[FindsBy(How = How.Id, Using = "content")]
public IWebElement ele;
public Page(IWebDriver _driver)
{
this.driver = _driver;
}
}
Use as follows:
Page page = PageFactory.InitElements<Page>(driver);
FindsByAttribute findsBy = SeleniumHelper.GetFindsByAttributeFromField(typeof(Page), "ele");
By by = SeleniumHelper.GeyByFromFindsBy(findsBy);
I found a way to o this :)
public static IWebElement FindElement( IWebElement element, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(chromeDriver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => element);
}
return element;
}
We faced the same issue when using selenium for testing. So we created a mini framework on top of selenium which keeps trying to do (whatever you are trying to do with selenium). Or otherwise you can provide a custom pre or post condition.
https://github.com/LiquidThinking/Xenon
It is very simple to setup and all information is available on github, plus it comes with Screen objects which can help to reuse your code.
For example
new XenonTest(new SeleniumXenonBrowser())
.GoToUrl("http://www.google.co.uk", a => a.PageContains("google") );
So in this example, we added a pre wait condition which says "before going to google.co.uk make sure that the current page contains "google" in page source. Which is obviously incorrect way to do it but it explains how to use pre or post wait conditions.
If you do not specify any wait condition then for some actions, there is a default wait action. for e.g. https://github.com/LiquidThinking/Xenon/blob/master/Xenon/BaseXenonTest.cs#L72
See how we check if a customPreWait is available for "Click" and if not then we added a custom pre-wait to check if that css selectors exists on the page before performing the "actual click action".
Hope it will help you, it is on nuget or otherwise just use the code which you want. it is under MIT license.

How to check for non existence of element using selenium web driver in C#

I goggled this issue but could not find a better answer, so... posting it here.
I click on a button in the browser, which opens up a form/div (which is generated dynamically). The form/div element does not exist until I press button.
Now, I am trying to check whether form/div element is existing or not. I tried with the below code. But it works when an element exists and throws exception (first method - timeout and for second, driver gets stopped) when the element does not exists.
Method 1:
ReadOnlyCollection<IWebElement> elements = Utility.Browser.FindElements(By.TagName("div")); // Utility.Browser is the browser instance.
var expElement = from e in elements
where e.GetAttribute("id").Contains("element id")
select e;
return expElement.Count() > 0;
and
Method 2:
string script = string.Format("return document.getElementById('{0}')", attValue);
IJavaScriptExecutor js = (IJavaScriptExecutor)Utility.Browser; // Utility.Browser is the browser instance.
var ele = js.ExecuteScript(script);
return ele != null;
Any help would be highly appreciated.
Thanks.
Look into WebDriverWait. You can define a wait function that will wait a specific amount of time to satisfy a specific condition. You can essentially say "wait for ten seconds for the element to appear". I'm on my phone and the exact syntax may be incorrect but it would look something like the following.
pulic bool ElementExist(IWebDriver driver)
{
var value = false;
var objWait = new WebDriverWait(driver, Timespan.FromMilliseconds(10000));
objWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
value = objWait.Until(b=>b.FindElements(By.TagName("div")).Count > 0);
return value;
}
You can specify which types of exceptions to ignore, such as ElementNotFound and StaleElement, and the function will continue to wait if those occur. You can also define a function and pass that as a parameter to the .Until function. My skills in lamda expressions and inline function definitions are lacking, otherwise I would give a better example but that is definitely the most customizable approach.
similarly to the other two answers already here, I fashion my test using an extension method along the lines of:
public static bool ElementExists(this IWebDriver driver, By condition, TimeSpan? timeSpan)
{
bool isElementPresent = false;
if (timeSpan == null)
{
// default to 15 seconds if timespan parameter is not passed in
timeSpan = TimeSpan.FromMilliseconds(15000);
}
var driverWait = new WebDriverWait(driver, (TimeSpan)timeSpan);
driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
isElementPresent = driverWait.Until(x => x.FindElements(condition).Any());
return isElementPresent;
}
I then use this in code as such:
var isElementPresent = _driver.ElementExists(By.ClassName("register"), TimeSpan.FromSeconds(90.00));
if (isElementPresent)
{
// do required processing...
}
Hope this helps
[edit] - you could of course refactor the extension method to return the required element, with a default of null if you wanted to do everything in a single action.
public static IWebElement FindElementAfterWait(this IWebDriver driver, By condition)
{
bool isElementPresent = false;
IWebElement singleElement = null;
var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(90));
driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
isElementPresent = driverWait.Until(x => x.FindElement(condition) != null);
if (isElementPresent)
{
singleElement = driver.FindElement(condition);
}
return singleElement;
}
usage:
_driver.FindElementAfterWait(By.ClassName("register"));
also:
public static IWebElement FindElementAfterWait(this IWebDriver driver, Func<IWebDriver, IWebElement> condition)
{
IWebElement singleElement = null;
var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(90));
driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
singleElement = driverWait.Until(condition);
return singleElement;
}
usage:
_driver.FindElementAfterWait(ExpectedConditions.ElementIsVisible(By.Id("firstName")))
enjoy...
The following function helps me to test the existence of an element on a page in C# Selenium code:
public static bool IsElementPresent(this IWebDriver driver, By by)
{
return driver.FindElements(by).Count > 0;
}
Please let me know if it helps you!
Following method is the one that I always use, and trust me really does what it says.
It will return true if the specified element is displayed else it will return false.
You can use it like : IsElementDisplayedByXpathVariableWait("Xpath_Of_The_Element",5);
5 is the number of times it will check if the element is displayed with a pause of 1 sec after every check.
public static bool IsElementDisplayedByXpathVariableWait(string xpath, int iterations)
{
bool returnVal = false;
int tracker = 0;
while (tracker < iterations)
{
try
{
tracker++;
IWebElement pageObject = _driver.FindElement(By.XPath(xpath));
if (pageObject.Displayed)
{
returnVal = true;
break;
}
}
catch (Exception e)
{
Wait(1000);
continue;
}
}
return returnVal;
}

webdriver - Utility / helper method - wait until class name contains specific style attribute

I have a webapp that will contain a class of "Loading" which, when fully loaded on the page, will contain a width property of 100% else it will contain nothing. I'm trying to perform a check on this style attribute but I keep getting a timeout. here is what I'm doing:
I'm calling code from within a helper / utility class as follows as this is something I will be using frequently in multiple classes:
Utility.WaitForStyle("Loading", Utility.driver);
In my helper / utility class I have the following code:
public static void WaitForStyle(string Class, IWebDriver driver)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
wait.Until<bool>((d) =>
{
try
{
IWebElement element = d.FindElement(By.ClassName(Class));
String elementresults = element.GetAttribute("style");
System.Diagnostics.Debug.WriteLine(elementresults);
return false;
}
catch (NoSuchElementException)
{
return true;
}
});
}
Note, The code above is currently just looking to check that it can get a handle on the class's style attribute but it's not getting to that point. I know the problem lies within the utility method as I can use the following code in individual classes:
IWebElement element = Utility.driver.FindElement(By.ClassName("Loading"));
String elementresults = element.GetAttribute("style");
System.Diagnostics.Debug.WriteLine(elementresults);
This will printout "width: 100%" as expected so I know that this block of code is actually working ok.
Does anyone know if I'm doing something silly in my utility method?
Here's my code to wait for an element attribute to have a specific value. It assumes the element passed to it has been verified to exist:
public bool WaitForAttribute(IWebDriver driver, IWebElement element, string attributeName, string attributeValue, int timeOut = 5)
{
// Build a function with a signature compatible with the WebDriverWait.Until method
Func<IWebDriver, bool> testCondition = (x) => element.GetAttribute(attributeName).Equals(attributeValue);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeOut));
// Wait until either the test condition is true or timeout
try { wait.Until(testCondition); }
catch (WebDriverTimeoutException e) { }
// Return a value to indicate if our wait was successful
return testCondition.Invoke(null);
}
This is working for me, since more than 4 months.
public static WebDriverWait wait = new WebDriverWait(SeleniumInfo.Driver, TimeSpan.FromSeconds(20));
public static void WaitUntilAttributeValueEquals(this IWebElement webElement, String attributeName, String attributeValue)
{
wait.Until<IWebElement>((d) =>
{
if (webElement.GetAttribute(attributeName) == attributeValue)
{
return webElement;
}
return null;
});
}

How to run one browser per thread in Selenium?

I don't think this is particular to Selenium, but I've included that tag because I think it's a problem that's very relevant to Selenium tests.
I have a Browser class that's working as it stands:
public static class Browser {
private static IWebDriver webDriver;
private static IWebDriver ieDriver;
private static IWebDriver chromeDriver;
private static BrowserType _browserType;
public static BrowserType BrowserType {
set {
_browserType = value;
switch (_browserType) {
case BrowserType.IE:
if (ieDriver == null)
{
var ieOptions = new InternetExplorerOptions();
ieOptions.InitialBrowserUrl = "about:home";
ieDriver = new InternetExplorerDriver(DriverPath, ieOptions);
}
webDriver = ieDriver;
break;
case BrowserType.Chrome:
if (chromeDriver == null)
{
chromeDriver = new ChromeDriver(DriverPath);
}
webDriver = chromeDriver;
break;
default:
if (chromeDriver == null)
{
chromeDriver = new ChromeDriver(DriverPath);
}
webDriver = chromeDriver;
break;
break;
}
} get { return _browserType; }
}
public static void Goto(string url) {
webDriver.Navigate().GoToUrl(url);
}
}
The problem is that each of these browsers should run in their own thread, so that each test can run on each browser simultaneously (cutting cross-browser test times to the time it takes to run a single browser's test). Right now tests are called sequentially with the following method:
public void RunTest(Func<TestSettings, TestRole, bool> testToRun)
{
foreach (var browserType in BrowserTypes)
{
// Assert test passes in given browser
// browser should have its own thread
}
}
How can multithreading be achieved in this scenario?
Multithreadding is usually achieved to run multiple tests with a testunit.
For PHP you have PHPUnit and some other options:
http://net.tutsplus.com/tutorials/php/parallel-testing-for-phpunit-with-paratest/
For Java you could try to dig in maven-surefire-plugin using JUnit.
http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html
Don't know if it is achievable through any selenium API.
If you find a way, please make sure to let me know!
Hope this helps.
I see that you have only one driver:
private static IWebDriver webDriver;
When you set BrowserType for the first time (for example as IE) you assign webDriver (as IE).
Then when you set BrowserType for the second time (for example as Chrome) you re-assign webDriver (now it is Chrome, IE is lost). You will never get simultaneously run of both browsers in this way.
BrowserType should be set externally. For example, as a parameter of your test-project or from App.config. If you want to run tests in one machine simultaneously, create an app (console app for example), that launches your test-project with different BrowserType values in two different threads.

Categories