I have following problem. I need to register my webdriver instance inside of the specflow BeforeFeature method using context injection, but this method must be static. I have an error that my global container object have to be static. Is there any way to use this context injection in static method?
Here is my code:
[Binding]
public class SpecflowHooks
{
private readonly IObjectContainer container;
public SpecflowHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeFeature]
public static void OneTime()
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("--ignore-ssl-errors=yes");
options.AddArgument("--ignore-certificate-errors");
ChromeDriver driver = new ChromeDriver();
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
container.RegisterInstanceAs<IWebDriver>(driver);
}
[BeforeScenario]
public void SetUp()
{
}
[AfterScenario]
public void TearDown()
{
}
[AfterFeature]
public static void FeatureTearDown()
{
IWebDriver driver = container.Resolve<IWebDriver>();
driver.Close();
driver.Dispose();
}
}
I presume you want to initialize the web driver only once per feature, and reuse an existing web driver object for each scenario in the feature.
As you noted, the BeforeFeature hook is static. You can still use this to initialize the web driver, but assign it to a static field on your hooks class. Then inside a BeforeScenario, register the static web driver object with the dependency injection container:
[Binding]
public class SpecflowHooks
{
private static IWebDriver driver;
private readonly IObjectContainer container;
public SpecflowHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeFeature]
public static void OneTime()
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("--ignore-ssl-errors=yes");
options.AddArgument("--ignore-certificate-errors");
driver = new ChromeDriver(options); // <-- don't forget to pass 'options' here
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
}
[BeforeScenario]
public void SetUp()
{
container.RegisterInstanceAs<IWebDriver>(driver);
}
[AfterScenario]
public void TearDown()
{
}
[AfterFeature]
public static void FeatureTearDown()
{
if (driver == null)
return;
driver.Close();
driver.Dispose();
driver = null;
}
}
Related
I am opening a browser session at [BeginScenario] and Quit the session at the [AfterScenario].
At the beginning of second scenario, i am getting 'OpenQA.Selenium.WebDriverException: 'invalid session id'.
How do we start a new session at the beginning of each scenario.?
[Binding]
public class BasePage
{
public static IWebDriver driver;
public static void BrowserSetup()
{
driver = new ChromeDriver();
//driver.Manage().Cookies.DeleteAllCookies();
driver.Manage().Window.Maximize();
}
}
[Binding]
public class Hook : BasePage
{
[BeforeScenario]
public void Initialize(ScenarioContext scenarioContext)
{
BrowserSetup(); // Initialise the driver from BaseClass
scenario = featureName.CreateNode<Scenario>(scenarioContext.ScenarioInfo.Title);
//scenario = featureName.CreateNode<Scenario>(scenarioContext.ScenarioInfo.Title);
}
[AfterScenario]
public void CleanUp(ScenarioContext scenarioContext)
{
if (scenarioContext.TestError != null)
{
TakeScreenshot(driver);
}
//driver.Close();
driver.Quit();
}
}
I'm new to mobile automation, and I'm facing a problem with page object pattern. When I try to find element with FindElementById everything works, here is my class with pop:
public class SamplePage
{
private AndroidDriver<AndroidElement> _driver;
[FindsByAndroidUIAutomator(ID = "com.miui.calculator:id/btn_1_s")]
private readonly AndroidElement _buttonOne;
[FindsByAndroidUIAutomator(ID = "android:id/button1")]
private readonly AndroidElement _confirmButton;
public SamplePage(AndroidDriver<AndroidElement> driver)
{
_driver = driver;
PageFactory.InitElements(_driver, this);
}
public void ClickOnConfirmButton()
{
//AndroidElement _confirmButton = _driver.FindElementById("android:id/button1");
_confirmButton.Click();
}
public void ClickOnButtonOne()
{
//AndroidElement _buttonOne = _driver.FindElementById("com.miui.calculator:id/btn_1_s");
_buttonOne.Click();
}
}
And here is main class
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Enums;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Remote;
using System;
using AppiumDotNetSamples.Helper;
namespace AppiumDotNetSamples
{
[TestFixture()]
public class AndroidBasicInteractionsTest
{
private AndroidDriver<AndroidElement> driver;
private SamplePage _samplePage;
[SetUp()]
public void BeforeAll()
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability(MobileCapabilityType.PlatformName, "Android");
capabilities.SetCapability(MobileCapabilityType.PlatformVersion, "7.1.2");
capabilities.SetCapability(MobileCapabilityType.AutomationName, "UIAutomator2");
capabilities.SetCapability(MobileCapabilityType.DeviceName, "3e52f2ee7d34");
capabilities.SetCapability("appPackage", "com.miui.calculator");
capabilities.SetCapability("appActivity", "com.miui.calculator.cal.CalculatorActivity");
driver = new AndroidDriver<AndroidElement>(new Uri("http://localhost:4723/wd/hub"), capabilities, TimeSpan.FromSeconds(180));
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
_samplePage = new SamplePage(driver);
}
[Test()]
public void Click()
{
_samplePage.ClickOnConfirmButton();
_samplePage.ClickOnButtonOne();
}
[TearDown()]
public void AfterAll()
{
driver.Quit();
}
}
}
What am I doing wrong? I test on on Xiaomi Calculator app, but earlier I got the same issues on any other app like Google Calculator.
The ClickConfirmButton method is not returning the driver and hence it is null.
You may want to try something similar this and see if it is working
public AboutPage goToAboutPage()
{
about.Click();
return new AboutPage(driver);
}
I have these 2 classes
public class BrowserContext
{
private readonly ChromeDriver _driver;
public BrowserContext(ChromeDriver driver)
{
_driver = driver;
}
public void NavigateTo()
{
_driver.Navigate().GoToUrl("http://bbc.com");
}
}
public class Homepage
{
private readonly BrowserContext _browserContext;
public Homepage(BrowserContext browserContext)
{
_browserContext = browserContext;
}
[Given(#"I navigate to url")]
public void GivenINavigateToUrl()
{
_browserContext.NavigateTo();
}
When I try to run the test I get below error
Multiple public constructors with same maximum parameter count are not
supported! OpenQA.Selenium.Chrome.ChromeDriver (resolution path:
ClassLibrary3.Steps.Homepage->ClassLibrary3.Support.BrowserContext)
Please help!
Based on this answer https://stackoverflow.com/a/26402692/10148657 solution is to instantiate ChromeDriver in BrowserContext constructor rather than accept it in constructor:
public class BrowserContext
{
private readonly ChromeDriver _driver;
public BrowserContext()
{
_driver = new ChromeDriver();
}
public void NavigateTo()
{
_driver.Navigate().GoToUrl("http://bbc.com");
}
}
I need help with expanding my already build Selenium framework with WebDriver. I want to add eventHandlers that use EventFiringWebDriver on top of my code to add event for each action triggered by WebDriver for logging purposes.
To begin with, I will try to clearly present code flow.
Test starts...
Step 1. CspTestBase
public class CspTestBase : CommonElements
{
[BeforeScenario]
public void Init()
{
Initialize(); <- Code to init driver.
// more code here.
LoginPage.Goto();
LoginPage.LoginAs(TestConfig.Username).WithPassword(TestConfig.Password).Login();
}
[AfterScenario]
public void CleanUp()
{
Close();
}
When it jumps to Init method. This class holds all methods that directly require WebDriver instance.
public static class Driver
{
public static IWebDriver Instance { get; private set; }
public static void Initialize()
{
Instance = new TestDriverFactory().CreateDriver(); <- Next step
Instance.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 30));
Instance.Manage().Cookies.DeleteAllCookies();
//Instance.Manage().Window.Maximize();
}
Then when WebDriver Instance is created:
public class TestDriverFactory
{
public IWebDriver CreateDriver()
{
return new TestBase().Create(
new LocalDriverConfig(
TestConfig.Browser));
}
}
And when it finally comes to creating actual driver:
public class TestBase
{
private static IWebDriver _driver;
//string env;
private DesiredCapabilities _capabilities;
public IWebDriver Create(LocalDriverConfig config)
{
switch (config.Browser)
{
case "Chrome":
_driver = new ChromeDriver(#"C:\Utilities");
break;
case "Firefox":
SetFirefoxCapabilities();
//_driver = new FirefoxDriver(_capabilities);
break;
...
private void SetFirefoxCapabilities()
{
...
_capabilities = DesiredCapabilities.Firefox();
//FirefoxOptions options = new FirefoxOptions();
//options.SetLoggingPreference(LogType.Browser, LogLevel.Warning);
_capabilities.SetCapability(FirefoxDriver.ProfileCapabilityName, profile);
//capabilities.SetCapability(FirefoxDriver.ProfileCapabilityName, options);
EventFiringWebDriver firingDriver = new EventFiringWebDriver(new FirefoxDriver(binary, profile, TimeSpan.FromSeconds(60)));
// copy the profile for ommiting duplicate references
firingDriver.ExceptionThrown += firingDriver_TakeScreenshotOnException;
_driver = firingDriver;
}
private void firingDriver_TakeScreenshotOnException(object sender, WebDriverExceptionEventArgs e)
{
TakeScreenshot();
}
As you can see, I'm using EventFiringWebDriver already but I want to have it done properly to save me as much work as possible.
I did some reading and looked up solutions but these were simple or in Java. Any help will be much appreciated.
I have te code below:
[TestClass]
public class UnitTest3
{
private static FirefoxDriver _webDriver;
private TestContext testContextInstance;
private static string _baseUrl;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
public static string BaseUrl
{
get
{
return _baseUrl;
}
set
{
_baseUrl = value;
}
}
[ClassInitialize()]
public static void Initialize(TestContext testContext)
{
_webDriver = new FirefoxDriver();
}
[ClassCleanup()]
public static void Cleanup()
{
_webDriver.Quit();
}
[TestMethod]
public void OpenGoogle_PageOpenSuccessfully()
{
BaseUrl = "http://www.google.es";
_webDriver.Navigate().GoToUrl(BaseUrl);
}
}
When debugging the test _webDriver = new FirefoxDriver is left wondering and does not launch.
I'm use Selenium-Webdriver and c# unit test (mstest)
Are there any issue with firefoxdriver?
I update to Selenium Web Driver 2.33 an working successfully.
Thanks