I use Selenium WebDriver C# and PageFactory (PageObject) pattern to create automated tests. I develop them in Visual Studio 2013.
Before the latest version of Webdriver (now I use 2.47.0) it worked well but now I face the next problem: I can not view properties of my web elements.
Here is how I create and initialize an element:
public class MyPageObj : DriverCover
{
public MyPageObj(IWebDriver driver) : base(driver)
{
//'Driver' is a EventFiringWebDriver (IWebDriver) from parent class
PageFactory.InitElements(Driver, this);
}
[FindsBy(How = How.CssSelector, Using = "#internal")]
private IWebElement _myElement;
}
When I run tests and at a breakpoint I want to watch properties of _myElement I see only non-public members: http://prntscr.com/8o075p
If I don't use PageFactory and find elements using Driver.FindElement(By.How()) method it works well.
Well as I found in this commit https://github.com/SeleniumHQ/selenium/commit/689276b5e39c414edccf8a1bd11d71fd81b5fad4 were made some changes and that's why my problem is not a bug and won't be fixed(
Related
I currently have an nunit project outputting a class library 'RegressionTests.dll' that opens the Selenium WebDriver and runs a few dozen UI tests. I have created a WinForm app with a button 'Run Tests'. When clicking this button, I want to execute a series of n-unit tests from RegressionTests.dll.
I had gotten this to work on my local machine using Process.Start("nunit3-console.exe, nunit-console RegressionTests.dll"), but realized that it would only work on my local if I had installed nunit3-console as a standalone app. After realizing this, I dug more into the n-unit documentation and discovered the n-unit engine. I have tried leveraging the n-unit3 Engine in order to run it internally but have faced issues with implementation of the ITestEventListener in the WinForm project. I've attached the code to my button here:
Form1.cs
private void btnRun_Click(object sender, EventArgs e)
{
TestRunner.Run();
}
Inside TestRunner.cs, we have this code:
[Extension(Description = "Test Reporter Extension", EngineVersion = "3.11")]
public class TestRunner : ITestEventListener
{
public static void Run()
{
ITestEngine engine = TestEngineActivator.CreateInstance();
TestPackage package = new TestPackage("RegressionTests.dll");
ITestEventListener testListener = new TestRunner();
using (ITestRunner runner = engine.GetRunner(package))
{
XmlNode result = runner.Run(testListener, TestFilter.Empty);
}
}
public void OnTestEvent(string report)
{
throw new NotImplementedException();
}
}
Currently, the solution layout is as follows.
Solution
Regression (project)
RegressionTests.dll
TestRunner.cs (file that contains my code linked above)
SeleniumFormApp
Form1.cs (contains button that, upon click, should run Selenium test cases)
How can I leverage n-units Nuget packages to accomplish what I want to here? Is n-unit engine the proper one? If so, how should the ITestEventListener be implemented to accomplish this?
Thank you - please let me know if this is unclear.
I'm trying to execute test program which uses selenium web driver in custom test runner.
In the test runner, selenium web driver equiped test method is invoked by reflection.
When the test program is run by Visual Studio Test Explorer, it works fine.
Problem occurs when it is run dynamically by reflection.
The test program is as follows.
namespace TrialWebUnitTest
{
public class WebDriverTest01
{
private IWebDriver driver;
[TestMethod]
public void NavigateToSeleniumHQByChrome()
{
string TargetUrl = "https://www.seleniumhq.org/projects/webdriver/";
this.driver = new ChromeDriver();
driver.Manage().Window.Size = new System.Drawing.Size(1000, 800); // <- driver throws exception here.
this.driver.Navigate().GoToUrl(TargetUrl);
this.driver.Dispose();
}
}
}
The custom test runner's core test executing method is as follows.
namespace TrialWebUnitTestRunner
{
public partial class TestForm : Form
{
// test button click's event handler.
private void TestButton_Click(object sender, EventArgs e)
{
string retErrorMsg = string.Empty;
if (!ExecTestDynamically(ref retErrorMsg))
{
// show error information in UI textbox.
this.this.ResultMessage.Text = retErrorMsg;
}
}
internal bool ExecTestDynamically(ref string retErrorMsg)
{
var target = new TrialWebUnitTest.WebDriverTest01();
System.Type targetType = typeof(TrialWebUnitTest.WebDriverTest01);
var method = targetType.GetMethod("NavigateToSeleniumHQByChrome");
try
{
method.Invoke(target, null);
return true
}
catch (Exception exp)
{
retErrorMsg = exp.Message + Environment.NewLine + exp.StackTrance;
return false;
}
}
}
}
Exception information
System.InvalidOperationException:
disconnected: unable to connect to renderer
(Session info: chrome=65.0.3325.181)
(Driver info: chromedriver=2.31.488763
Sample program
I've written a sample program to reproduce the error.
Please download it from my dropbox url: https://db.tt/HqUTMOKWBl
You can click the link and download 'TrialWebTestForInspection.zip'.
Please extract it in any arbitrary folder and find TrialWebTestForInspection.sln.
The solution consists of two projects, "TrialWebUnitTest" and "TrialWebUnitTestRunner".
The first one is MS Unit Test, and you can run 3 test methods from Visual Studio Test Explorer.
The 3 test methods are very simple. They just launch the browser correspond to the webdriver, and navigate to Selenium HQ site.
The other project is a WindowsForm application which provide a very simple test runner.
It kicks the test methods in previous test project.
When you choose the test method using IE or FireFox driver, it works fine.
On the other hand, when you choose Chrome driver test, it thows exception which I mentioned above.
Things I'd like to know.
First I'd like to know, if it is a bug of current Chrome driver version, or it is a part of specification.
Then I'd like to know, if there is a way to avoid this problem or not.
What I'm afraid of is the possibility that IWebDriver specification originally does not support correct action whent it is run by reflection.
spec of sample program
.NET Framework version 4.6.1
nuget package
MSTest.TestFramework.1.2.0 MSTest.TestAdapter.1.2.0
Selenium.WebDriver.3.11.0 Selenium.WebDriver.ChromeDriver.2.37.0
Selenium.WebDriver.IEDriver.3.11.1 Selenium.Firefox.WebDriver.0.20.0
Chrome Browser version 65.0.3325.181(Official Build)(64 bit)
The problem was solved. Please refer to this.
The custom TestRunner application didn't refer to the latest chrome-driver version. I had to install selenium.webdrivers not only to the testclass, but also to the testrunner program.
For further information, please refer to the following issue in GitHUB.
https://github.com/SeleniumHQ/selenium/issues/5705
I've been trying to get my Grid working with IE, but at some point I need to specify the full path to my driver's exe.
InternetExplorerOptions ieOptions = new InternetExplorerOptions();
DesiredCapabilities ieCapability = DesiredCapabilities.InternetExplorer();
ieCapability.SetCapability(ieOptions.EnsureCleanSession.ToString(), true);
ieCapability.SetCapability(ieOptions.BrowserCommandLineArguments.ToString(), "-private");
I need to know if this can be done via InternetExplorerOptions or DesiredCapabilities or if I just should create an environment variable holding the path to my IE driver.
Thanks!
One of the most common practices i've seen in my Selenium experience, is testers will put their statement in their super class.
Consider the following (I'm a Java programmer, so this will be java code, you can convert to C#):
public class SuperTest {
public SuperTest() {
System.setProperty("webdriver.ie.driver", "C:\\Path\\To\\IEDriver.exe");
}
}
public class Test extends SuperTest {}
You can see how you can do it in the Getting started with Selenium framework (again, Java).
I'm moving from a Java environment to .NET and need to write Webdriver tests using a page object model.
In Java I would use the following annotation:
#FindBy(linkText = "More details")
WebElement moreDetailsButton;
Please would someone be able to tell me how to define a WebElement using C#? Also, is the PageFactory.initElements used the same way?
Thanks
Steve
Yes, there is a direct translation.
You are looking for FindsBy:
[FindsBy(How = How.LinkText, Using = "More details")]
private IWebElement moreDetailsButton;
As for the PageFactory.initElements, yes, it's a very similar thing in .NET, usually called in the constructor of the Page Object:
public class LoginPage
{
private IWebDriver _driver;
public LoginPage(IWebDriver driver)
{
_driver = driver;
PageFactory.InitElements(_driver);
}
}
Note, that the Selenium project is entirely open source. You can easily see the source the Page Objects 'helper' classes here.
I'm using Selenium's IWebDriver to write Unit Tests in C#.
Such is an example:
IWebDriver defaultDriver = new InternetExplorerDriver();
var ddl = driver.FindElements(By.TagName("select"));
The last line retrieves the select HTML element wrapped in a IWebElement.
I need a way to simulate selection to a specific option in that select list but I can't figure out how to do it.
Upon some research, I found examples where people are using the ISelenium DefaultSelenium class to accomplish the following, but I am not making use of this class because I'm doing everything with IWebDriver and INavigation (from defaultDriver.Navigate()).
I also noticed that ISelenium DefaultSelenium contains a ton of other methods that aren't available in the concrete implementations of IWebDriver.
So is there any way I can use IWebDriver and INavigation in conjunction with ISelenium DefaultSelenium ?
As ZloiAdun mentions, there is a lovely new Select class in the OpenQA.Selenium.Support.UI namespace. That's one of the best ways to access a selection element and it's options because it's api is so easy. Let's say you've got a web page that looks something like this
<!DOCTYPE html>
<head>
<title>Disposable Page</title>
</head>
<body >
<select id="select">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
</body>
</html>
You're code to access the select would look like this. Note how I create the Select object by passing a normal IWebElement to it's constructor. You have plenty of methods on the Select object. Take a look at the source for more information, until it gets properly documented.
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium;
using System.Collections.Generic;
using OpenQA.Selenium.IE;
namespace Selenium2
{
class SelectExample
{
public static void Main(string[] args)
{
IWebDriver driver = new InternetExplorerDriver();
driver.Navigate().GoToUrl("www.example.com");
//note how here's i'm passing in a normal IWebElement to the Select
// constructor
Select select = new Select(driver.FindElement(By.Id("select")));
IList<IWebElement> options = select.GetOptions();
foreach (IWebElement option in options)
{
System.Console.WriteLine(option.Text);
}
select.SelectByValue("audi");
//This is only here so you have time to read the output and
System.Console.ReadLine();
driver.Quit();
}
}
}
A couple things to note about the Support class however. Even if you downloaded the latest beta, the support DLL won't be there. The Support package has a relatively long history in the Java libraries (that's where PageObject lives) but it's still pretty fresh in the .Net driver. Fortunately, it's really easy to build from source. I pulled from SVN then referenced the WebDriver.Common.dll from the beta download and built in C# Express 2008. This class hasn't been as well tested as some of the other classes, but my example worked in Internet Explorer and Firefox.
There's a few other things that I should point out based on your code above. Firstly the line you were using to find the select element
driver.FindElements(By.TagName("select"));
is going to find all select elements. you should probably use driver.FindElement, without the 's'.
Also, very rarely would you use INavigation directly. You'll do most of your navigation like driver.Navigate().GoToUrl("http://example.com");
Lastly, DefaultSelenium is the way to access the older Selenium 1.x apis. Selenium 2 is a pretty significant departure from Selenium 1, so unless you're trying to migrate old tests to the new Selenium 2 api (often referred to as the WebDriver api) you won't use DefaultSelenium.
You should get all option elements from your select using ddl.FindElements(By.TagName("option"));. Then you can iterate through the returned collection and select required item(s) by using SetSelected method of the IWebElement
Update: It seems that there's now a C# implementation of the Select in WebDriver - previously it was in Java only. Please take a look at its code and it is easier to use this class