I have the following code,
[Binding]
public class Setup
{
private readonly Context _context;
public const int DefaultTimeOut = 10;
public Setup(Context context)
{
_context = context;
}
public static IWebDriver Driver;
[BeforeTestRun]
public static void SetUpBrowser()
{
ChromeOptions options = new ChromeOptions();
options.EnableMobileEmulation("Apple iPhone 6");
Driver = new ChromeDriver(options);
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(DefaultTimeOut);
}
I want to be able to run the browser using Google Chrome's emulator, but unfortunately, I'm recieving the following error message: "Message: There is already an option for the mobileEmulation capability. Please use the instead. Parameter name: capabilityName"
It'd be even more beneficial if I could use this outside the SetUpBrowser method, e.g. within a method that runs later in my test, I was thinking possibly adding the above to ChromeOptions but I didn't have any success
The way in which I tried the above is:
[Binding]
public class Setup
{
private readonly Context _context;
public const int DefaultTimeOut = 10;
public Setup(Context context)
{
_context = context;
}
public static IWebDriver Driver = new ChromeDriver();
[BeforeTestRun]
public static void SetUpBrowser()
{
Driver.Manage().Window.Maximize();
Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(DefaultTimeOut);
}
And the method in which I want to switch to the Mobile Emulator was:
[Given(#"I am on the mobile website version")]
public void GivenIAddAmOnTheMobileWebsiteVersion()
{
ChromeOptions options = new ChromeOptions();
options.EnableMobileEmulation("Apple iPhone 6");
Cookie SetMobileCookie = new Cookie(VariableList.MobileCookieValue, "true");
MobileCookie = VariableList.MobileCookieValue;
_driver.Manage().Cookies.AddCookie(SetMobileCookie);
_driver.Click(ElementType.Id, VariableList.MemberLoginButton); //should be a new method
}
Change text to "iPhone 6"
ChromeOptions options = new ChromeOptions();
options.EnableMobileEmulation("iPhone 6");
IWebDriver driver = new ChromeDriver(options);
It works for me
you have to match the EnableMobileEmulation with parameter on your chrome
go to developer mode > then click on mobile icon. on the top left you can find list of all available device name you can use.
for example if you want to use iphone x, your code should be like this
options.EnableMobileEmulation("iPhone X");
Related
So I have create two methods which I want to use the same ChromDriver. I want the first method to do something with a ChromeDriver and the second method to "continue" the process with the same ChromeDriver.
static void FirstDriver()
{
IWebDriver Driver1 = new ChromeDriver();
Driver1.Navigate().GoToUrl("login page");
//login to the page
}
static void SecondDriver()
{
IWebDriver Driver2 = new ChromeDriver();
Driver2.Navigate().GoToUrl("login page");
//continue while still loged-in
}
I know that an alternative solution would be to get the cookies from Driver1 and use them for Driver2, but I don't know how to do that in selenium...
You need to create a Chrome Driver object out of the method so it can be used in multiple places.
Something like this should help get you started.
public static IWebDriver Driver { get; set; }
static void Main(string[] args)
{
Driver = new ChromeDriver();
// Both should use the same driver object.
FirstDriver();
SecondDriver();
}
static void FirstDriver()
{
Driver.Navigate().GoToUrl("login page");
//login to the page
}
static void SecondDriver()
{
Driver.Navigate().GoToUrl("login page");
//continue while still loged-in
}
Under the class define driver as global variable and use it
**static WebDriver driver;**
driver = new ChromeDriver();
I need to know how we can use the same instances of a Selenium Driver in different classes? So I have created an instance of the driver in a class, using the code :
IWebDriver driver = new ChromeDriver("C:/Users/Krishna/source/repos/G1ANT.Addon.YouTube/packages/Selenium.Chrome.WebDriver.83.0.0/driver");
So I need to use this instance in the new class, how could I do that?
Thank You
The simplest approach is to put the driver in a static field of another class like below. Or you can use a singleton design pattern for returning the driver instance one and only once throughout the application
public class DriverHelper
{
public static readonly IWebDriver Driver = new ChromeDriver("C:/Users/Krishna/source/repos/G1ANT.Addon.YouTube/packages/Selenium.Chrome.WebDriver.83.0.0/driver");
}
Then access the driver like
var _driver = DriverHelper.Driver;
You need to create utils class for driver instance so you can ignore nullpoint exception. i will share my utils class for driver instance you can use it (create package for utils classes inside you project folder)
package utils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
public class TestApp {
private WebDriver driver;
private static TestApp myObj;
// public static WebDriver driver;
utils.PropertyFileReader property = new PropertyFileReader();
public static TestApp getInstance() {
if (myObj == null) {
myObj = new TestApp();
return myObj;
} else {
return myObj;
}
}
//get the selenium driver
public WebDriver getDriver()
{
return driver;
}
//when selenium opens the browsers it will automatically set the web driver
private void setDriver(WebDriver driver) {
this.driver = driver;
}
public static void setMyObj(TestApp myObj) {
TestApp.myObj = myObj;
}
public void openBrowser() {
//String chromeDriverPath = property.getProperty("config", "chrome.driver.path");
//String chromeDriverPath = property.getProperty("config", getChromeDriverFilePath());
System.setProperty("webdriver.chrome.driver", getChromeDriverFilePath());
ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-notifications");
options.addArguments("disable-infobars");
driver = new ChromeDriver(options);
driver.manage().window().maximize();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void navigateToURL() {
String url =property.getProperty("config","url");
driver.get(url);
}
public void closeBrowser()
{
driver.quit();
}
public WebElement waitForElement(By locator, int timeout)
{
WebElement element = new WebDriverWait(TestApp.getInstance().getDriver(), timeout).until
(ExpectedConditions.presenceOfElementLocated(locator));
return element;
}
private String getChromeDriverFilePath()
{
// checking resources file for chrome driver in side main resources
URL res = getClass().getClassLoader().getResource("chromedriver.exe");
File file = null;
try {
file = Paths.get(res.toURI()).toFile();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return file.getAbsolutePath();
}
}
Note if you are using mac mention above chromedriver only
Keep chrome driver in resource folder
TestApp.getInstance().getDriver() -This is way use driver.
the 2 nd option is you can create global variable for driver instance
---**static private WebDriver driver;**
I am currently using the following code to shutdown my browsers after each test:
[TearDown]
public void StopBrowser()
{
if (Driver == null)
return;
Driver.Quit();
}
This works fine when running single tests however when I run multiple tests in Parallel using NUnit's [Parallelizable] tag, I get my tests starting to fail due to no such session errors, Unable to connect to the remote server errors and then an Object Reference error on top so it's definitely something to do with the parallel tests.
Please find below the code that I use in the [SetUp] method:
public IWebDriver Driver { get; set; }
public string TestUrl;
[SetUp]
public void Setup()
{
string Browser = "Chrome";
if (Browser == "Chrome")
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("--start-maximized");
Driver = new ChromeDriver(options);
}
else if (Browser == "Firefox")
{
FirefoxDriverService service = FirefoxDriverService.CreateDefaultService();
service.FirefoxBinaryPath = #"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
Driver = new FirefoxDriver(service);
}
else if (Browser == "Edge")
{
EdgeDriverService service = EdgeDriverService.CreateDefaultService();
Driver = new EdgeDriver(service);
}
BasePage Code:
public class BasePage<TObjectRepository> where TObjectRepository : BasePageObjectRepository
{
public BasePage(IWebDriver driver, TObjectRepository repository)
{
Driver = driver;
ObjectRepository = repository;
}
public IWebDriver Driver { get; }
internal TObjectRepository ObjectRepository { get; }
}
BasePageObjectRepository Code:
public class BasePageObjectRepository
{
protected readonly IWebDriver Driver;
public BasePageObjectRepository(IWebDriver driver)
{
Driver = driver;
}
}
My Tests simply call specific functions inside their relevant page and then the code inside the page simply has Selenium code that points to the elements in that Pages Object Repository i.e.
ObjectRepository.LoginButton.Click();
Im not sure if the way I have my tests set up is whats partially causing the issues but any help I can get in regards to this would be greatly appreciated
EDIT: Added more of my code in to help:
BaseTest Class:
[TestFixture]
public class BaseTest
{
public IWebDriver Driver { get; set; }
public string TestUrl;
[SetUp]
public void Setup()
{
string Browser = "Chrome";
if (Browser == "Chrome")
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("--start-maximized");
Driver = new ChromeDriver(options);
}
else if (Browser == "Firefox")
{
FirefoxDriverService service = FirefoxDriverService.CreateDefaultService();
service.FirefoxBinaryPath = #"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
Driver = new FirefoxDriver(service);
}
else if (Browser == "Edge")
{
EdgeDriverService service = EdgeDriverService.CreateDefaultService();
Driver = new EdgeDriver(service);
}
Driver.Manage().Window.Maximize();
string Environment;
Environment = "Test";
if (Environment == "Test")
{
TestUrl = "https://walberton-test.azurewebsites.net/";
}
else if (Environment == "Live")
{
TestUrl = "";
}
}
}
[OneTimeTearDown]
public void TeardownAllBrowsers()
{
Driver.Close();
Driver.Quit();
}
Example of One of the Tests:
[TestFixture]
public class TimeLogsTestChrome: BaseTest
{
[Test]
[Parallelizable]
[Category("Time Logs Test for Chrome")]
public void AssertTimeLogsHeading()
{
Driver = new ChromeDriver();
Driver.Manage().Window.Maximize();
var loginPage = new LoginPage(Driver);
var dashboard = new Dashboard(Driver);
var timeSheets = new Timesheets(Driver);
loginPage.GoTo("Test");
loginPage.EnterEmailAddress("Valid");
loginPage.EnterPassword("Valid");
loginPage.ClickLoginButtonForLoginToDashboard();
dashboard.ClickTimesheetsButton();
timeSheets.AssertHeading();
Driver.Close();
}
}
Example of Underlying Code to the Test:
internal class Timesheets : BasePage<TimesheetsPageObjectRepository>
{
public Timesheets(IWebDriver driver) : base(driver, new TimesheetsPageObjectRepository(driver))
{
}
internal void AssertHeading()
{
try
{
Assert.AreEqual("Timesheets", ObjectRepository.TimesheetHeading);
}
catch (Exception ex)
{
throw;
}
}
internal void ClickAddTimesheetButton()
{
ObjectRepository.AddTimesheetButton.Click();
}
internal void ClickSubmitTimeButton()
{
ObjectRepository.SubmitTimeButton.Click();
Thread.Sleep(5000);
}
}
Partial Example of the Page Object Repository that has most of the FindElement code:
internal class TimesheetsPageObjectRepository : BasePageObjectRepository
{
public TimesheetsPageObjectRepository(IWebDriver driver) : base(driver) { }
public string TimesheetHeading => Driver.FindElement(By.ClassName("pull-left")).Text;
}
NUnit tests in a fixture all share the same instance of the fixture. That's one of the fundamentals of NUnit's design that programmers have to keep in mind because it's easy for tests to step on one another's toes through use of shared state. You have to watch out for tests interfering with one another even in non-parallel situations but parallelism makes it worse.
In your case, the most likely culprit is the Driver property of the fixture. It is set by the setup of every test and whatever is held there is closed by every test. That's not what you want.
I also notice that the Driver is defined twice, once in the fixture and once in the base class. You have not posted enough code for me to understand why you are doing this, but it seems problematic.
You have to decide whether all the tests in a fixture are intended to use the same driver or not. I suspect that's not what you want, since the driver itself may have changeable state. However, you can set it up either way.
To use the same driver for all tests, make it a property of the fixture. Initialize it in a OneTimeSetUp method and release it in a OneTimeTearDown method.
To use a different driver for each test, do not make it a property. Instead, initialize a local variable in each test and release it in the test itself.
First sorry about my English.
Here is my problem:
I make a test for mantisbt with many test cases(report issue), so i put the login in [SetUpFixture] and in [TestFixture] [Test, TestCaseSource("function")] I don't know how to get driver which i use for creating chrome browser to get elements.
Here is my code:
namespace testcailz
{
[SetUpFixture]
public class TestsSetupClass
{
public void login(IWebDriver driver)
{
IWebElement username = driver.FindElement(By.Name("username"));
username.SendKeys("1353049");
IWebElement password = driver.FindElement(By.Name("password"));
password.SendKeys("123456");
IWebElement login = driver.FindElement(By.XPath("//input[#value='Login'][#class='button']"));
login.Click();
}
[SetUp]
public void GlobalSetup()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.cs.hcmus.edu.vn/mantisbt/login_page.php");
login(driver);
}
[TearDown]
public void GlobalTeardown()
{
// Do logout here
}
}
[TestFixture]
public class Class1
{
private static int[] data()
{
return new int[3] { 1, 2, 3 };
}
[Test, TestCaseSource("data")]
public void TestCaiLz(int i)
{
//wanna click to report new issue but how to get driver for Findelement
Assert.AreEqual(i, i);
}
}
}
As per java prospective, create driver object globally in class may be TestsSetupClass
public static WebDriver driver;
#BeforeSuite
public void startUp(){
driver=new FirefoxDriver();
driver.manage().window().maximize();
login(driver);
}
If you what to use this driver in another classes then extends this class. like below in java
public class Home extends Setup{ //...
}
Thank You,
Murali
So I've gone back to basics with a blank project to test this out, I'm trying to use the example...
[TestFixture(typeof(ChromeDriver))]
public class TestWithMultipleBrowsers<TWebDriver> where TWebDriver : IWebDriver, new()
{
private IWebDriver driver;
[SetUp]
public void CreateDriver()
{
this.driver = new TWebDriver();
}
[Test]
public void GoogleTest()
{
driver.Navigate().GoToUrl("http://www.google.com/");
IWebElement query = driver.FindElement(By.Name("q"));
query.SendKeys("Bread" + Keys.Enter);
Thread.Sleep(2000);
Assert.AreEqual("bread - Google Search", driver.Title);
driver.Quit();
}
}
However it just does not run. If I remove the TestFixture typeof parameter though and set the driver manually it works fine.
[TestFixture]
public class TestWithMultipleBrowsers
{
private IWebDriver driver;
[SetUp]
public void CreateDriver()
{
this.driver = new ChromeDriver();
}
[Test]
public void GoogleTest()
{
driver.Navigate().GoToUrl("http://www.google.com/");
IWebElement query = driver.FindElement(By.Name("q"));
query.SendKeys("Bread" + Keys.Enter);
Thread.Sleep(2000);
Assert.AreEqual("bread - Google Search", driver.Title);
driver.Quit();
}
}
Any ideas on why using TextFixture with a parameter would prevent the test from running? I've already checked over CPU settings and Resharper settings based on other posts.
Many Thanks
After comparing NuGet packages with an old project looks like there may be an issue with the most recent version of NUnit. Downgraded to 2.6.4 all seems to be working fine.