Question is probably really trivial but I cannot handle it in proper way. I'm using Selenium with NUnit, having two clases:
1) "DemoTest" which involves one simply test "DummyTest":
public class DemoTest : TestBase
{
public class RunTest
{
[Test, Category("Main-Tests"), Order(1)]
public void DummyTest()
{
}
}
}
2) "Test base" class where I want to place all of the NUnit/ driver attributes like: "SetUp" / "TearDown"
[TestFixture]
public class TestBase
{
public IWebDriver driver;
public IWebDriver Driver
{
get { return driver; }
set { driver = value; }
}
public string pageURL = "http://automationpractice.com/";
[SetUp]
public void SetUp()
{
driver = new ChromeDriver();
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(15);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(0);
driver.Navigate().GoToUrl(pageURL);
}
[TearDown]
public void TearDown()
{
driver.Close();
driver.Dispose();
}
}
}
As NUnit attributes are declared (SetUp section) my test from DemoTest class should at least move on the page under pageURL variable.
Result is that after running a test it's immediately jump on "passed" without opening the specified address.
"DemoTest" inherits from "Test base" class. Nuget packages are installed correctly. When I'm placing test inside the "Test base" class everything works correctly but I want to have it separated.
Try to fix DemoTest class as follows:
[TestFixture]
public class DemoTest : TestBase
{
[Test, Category("Main-Tests"), Order(1)]
public void DummyTest()
{
}
}
Related
I'm getting exception on constructing DateOnly variables/fields with AutoFixture.
(constructing of TimeOnly works fine)
AutoFixture.ObjectCreationExceptionWithPath : AutoFixture was unable to create an instance from System.DateOnly because creation unexpectedly failed with exception. Please refer to the inner exception to investigate the root cause of the failure.
AutoFixture, AutoFixture.NUnit3 nugets version: 4.17.0
using AutoFixture;
using AutoFixture.NUnit3;
using NUnit.Framework;
namespace UnitTests
{
[TestFixture]
public class AutoFixtureCreateTests
{
private readonly Fixture fixture = new();
[SetUp]
public void Setup()
{
var date = fixture.Create<DateOnly>(); //fails
var time = fixture.Create<TimeOnly>(); //works fine
}
[Test, AutoData]
public void CreateString(string str) { } //works fine
[Test, AutoData]
public void CreateDateOnly(DateOnly date) { } //fails
[Test, AutoData]
public void CreateTimeOnly(TimeOnly time) { } //works fine
}
}
The answer: at the moment does not.
There is a pull request: https://github.com/AutoFixture/AutoFixture/pull/1305
(however it's in open state almost for a year, without any milestones)
But there is a workaround.
My temporary solution is to create AutoFixture customization (CustomFixture.cs) file and include it to the project:
using AutoFixture;
using AutoFixture.NUnit3;
namespace UnitTests
{
public class CustomFixture
{
public static Fixture Create()
{
var fixture = new Fixture();
fixture.Customize<DateOnly>(composer => composer.FromFactory<DateTime>(DateOnly.FromDateTime));
return fixture;
}
}
public class CustomAutoDataAttribute : AutoDataAttribute
{
public CustomAutoDataAttribute()
: base(()=>CustomFixture.Create())
{}
}
}
After it include customization in the test code:
using AutoFixture;
using AutoFixture.NUnit3;
using NUnit.Framework;
namespace UnitTests
{
[TestFixture]
public class AutoFixtureCreateTests
{
private readonly Fixture fixture =
CustomFixture.Create(); //custom factory
[SetUp]
public void Setup()
{
var date = fixture.Create<DateOnly>(); //now works
var time = fixture.Create<TimeOnly>();
}
[Test, AutoData]
public void CreateString(string str) { }
[Test, CustomAutoData] //custom attribute
public void CreateDateOnly(DateOnly date) { } //now works
[Test, AutoData]
public void CreateTimeOnly(TimeOnly time) { }
}
}
Looking to get some help around making my tests Parallelizable. I have a selenium c# setup that uses a combination of NUnit, C# and selenium to run tests in sequence locally on my machine or on the CI server.
I've looked into Parallelization of testing before but have been unable to make the jump, and running in a sequence was fine.
At the moment when I add the NUnit [Parallelizable] tag, I get an 'OpenQA.Selenium.WebDriverException : invalid session id' error, based on the reading I've done I need to make each new driver I call unique. However, I'm uncertain on how to do this? or even start for that matter... is this even possible within my current set up?
My tests are currently doing limited smoke tests and just removing the repetitive regression testing against multiple browsers, however, I foresee a need to vastly expand my coverage of testing capability.
I will probably be looking at getting Browserstack or Sauselab in the long term but obviously, that requires funding, and I need to get that signed off, so I will be looking to get it running locally for now.
here is a look at the basic set up of my code
test files:
1st .cs test file
{
[TestFixture]
[Parallelizable]
public class Featur2Tests1 : TestBase
{
[Test]
[TestCaseSource(typeof(TestBase), "TestData")]
public void test1(string BrowserName, string Environment, string System)
{
Setup(BrowserName, Environment, System);
//Run test steps....
}
[Test]
[TestCaseSource(typeof(TestBase), "TestData")]
public void test2(string BrowserName, string Environment, string System)
{
Setup(BrowserName, Environment, System);
//Run test steps....
}
}
}
2nd .cs test file
{
[TestFixture]
[Parallelizable]
public class FeatureTests2 : TestBase
{
[Test]
[TestCaseSource(typeof(TestBase), "TestData")]
public void test1(string BrowserName, string Environment, string System)
{
Setup(BrowserName, Environment, System);
//Run test steps....
}
[Test]
[TestCaseSource(typeof(TestBase), "TestData")]
public void test2(string BrowserName, string Environment, string System)
{
Setup(BrowserName, Environment, System);
//Run test steps....
}
}
}
TestBase.cs where my set up for each test
{
public class TestBase
{
public static IWebDriver driver;
public void Setup(string BrowserName, string Environment, string System)
{
Driver.Intialize(BrowserName);
//do additional setup before test run...
}
[TearDown]
public void CleanUp()
{
Driver.Close();
}
public static IEnumerable TestData
{
get
{
string[] browsers = Config.theBrowserList.Split(',');
string[] Environments = Config.theEnvironmentList.Split(',');
string[] Systems = Config.theSystemList.Split(',');
foreach (string browser in browsers)
{
foreach (string Environment in Environments)
{
foreach (string System in Systems)
{
yield return new TestCaseData(browser, Environment, System);
}
}
}
}
}
}
}
The IEnumerable TestData comes from a file called config.resx and contains the following data:
{Name}: {Value}
theBrowserList: Chrome,Edge,Firefox
theEnvironmentList: QA
theSystemList: WE
This is where I create my driver in Driver.cs
{
public class Driver
{
public static IWebDriver Instance { get; set; }
public static void Intialize(string browser)
{
string appDirectory = Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).Parent.Parent.Parent.FullName;
string driverFolder = $"{appDirectory}/Framework.Platform/bin/debug";
if (browser == "Chrome")
{
ChromeOptions chromeOpts = new ChromeOptions();
chromeOpts.AddUserProfilePreference("safebrowsing.enabled", true);
chromeOpts.AddArgument("start-maximized");
chromeOpts.AddArgument("log-level=3");
Instance = new ChromeDriver(driverFolder, chromeOpts);
}
else if (browser == "IE")
{
var options = new InternetExplorerOptions { EnsureCleanSession = true };
options.AddAdditionalCapability("IgnoreZoomLevel", true);
Instance = new InternetExplorerDriver(driverFolder, options);
Instance.Manage().Window.Maximize();
}
else if (browser == "Edge")
{
EdgeOptions edgeOpts = new EdgeOptions();
Instance = new EdgeDriver(driverFolder, edgeOpts);
Instance.Manage().Window.Maximize();
Instance.Manage().Cookies.DeleteAllCookies();
}
else if (browser == "Firefox")
{
FirefoxOptions firefoxOpts = new FirefoxOptions();
Instance = new FirefoxDriver(driverFolder, firefoxOpts);
Instance.Manage().Window.Maximize();
}
else { Assert.Fail($"Browser Driver; {browser}, is not currently supported by Initialise method"); }
}
public static void Close(string browser = "other")
{
if (browser == "IE")
{
Process[] ies = Process.GetProcessesByName("iexplore");
foreach (Process ie in ies)
{
ie.Kill();
}
}
else
{
Instance.Quit();
}
}
}
}
All your tests use the same driver, which is defined in TestBase as static. The two fixtures will run in parallel and will both effect the state of the driver. If you want two tests to run in parallel, they cannot both be using the same state, with the exception of constant or readonly values.
The first thing to do would be to make the driver an instance member, so that each of the derived fixtures is working with a different driver. If that doesn't solve the problem, it will at least take you to the next step toward a solution.
do not use static and that should help resolve your issue
public IWebDriver Instance { get; set; }
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace Nunit_ParalelizeTest
{
public class Base
{
protected IWebDriver _driver;
[TearDown]
public void TearDown()
{
_driver.Close();
_driver.Quit();
}
[SetUp]
public void Setup()
{
_driver = new ChromeDriver();
_driver.Manage().Window.Maximize();
}
}
}
I see there is no [Setup] on top of setup method in the TestBase. Invalid session is caused because you are trying to close a window which is not there. Also try to replace driver.close() with driver.quit();
You should call the driver separately in each test, otherwise, nunit opens only one driver for all instances. Hope this makes sence to you.
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
This question already has answers here:
Run code once before and after ALL tests in xUnit.net
(10 answers)
Xunit create new instance of Test class for every new Test ( using WebDriver and C#)
(3 answers)
Closed 8 years ago.
Updated question ::
I want to set up data before any Test in the test suite is run using xUnit.net. I tried IUseFixture but its run before any test class is run (not before the test suite)
Consider your suite has 2 test classes having 2 tests/class, when tried with IUseFixture, SetFixture runs 4 times (once per test).
I need something that run only once when all the four tests run simultaneously (once per test suite)... , here is the example (using WebDriver/C#/xunit)::
Class 1:
public class Class1 : IUseFixture<BrowserFixture>
{
private IWebDriver driver;
public void SetFixture(BrowserFixture data)
{
driver = data.InitiateDriver();
Console.WriteLine("SetFixture Called");
}
public Class1()
{
Console.WriteLine("Test Constructor is Called");
}
[Fact]
public void Test()
{
driver.Navigate().GoToUrl("http://www.google.com");
driver.FindElement(By.Id("gbqfq")).SendKeys("Testing");
}
[Fact]
public void Test2()
{
driver.Navigate().GoToUrl("http://www.google.com");
driver.FindElement(By.Id("gbqfq")).SendKeys("Testing again");
}
}
Class 2 :
public class Class2 : IUseFixture<BrowserFixture>
{
private IWebDriver driver;
public void SetFixture(BrowserFixture data)
{
driver = data.InitiateDriver();
Console.WriteLine("SetFixture Called");
}
public Class2()
{
Console.WriteLine("Test Constructor is Called");
}
[Fact]
public void Test3()
{
driver.Navigate().GoToUrl("http://www.google.com");
driver.FindElement(By.Id("gbqfq")).SendKeys("Testing");
}
[Fact]
public void Test4()
{
driver.Navigate().GoToUrl("http://www.google.com");
driver.FindElement(By.Id("gbqfq")).SendKeys("Testing again");
}
}
Fixture Class ::
public class BrowserFixture
{
private IWebDriver driver;
public BrowserFixture()
{
driver = new FirefoxDriver();
}
public IWebDriver InitiateDriver()
{
return driver;
}
}
Now when i run Test,Test2,Test3,Test4 simultaneously , SetFixture is called 4 times , i need something that run only once before any test run (once per test suite) or i can say something that run only once before any of the test class in the TestSuite is intialized , something like BeforeSuite in TestNG ::
http://testng.org/javadoc/org/testng/annotations/BeforeSuite.html
http://testng.org/doc/documentation-main.html#annotations
The ctor of the fixture will run only once:-
public class Facts : IUseFixture<MyFixture>
{
void IUseFixture<MyFixture>.SetFixture( MyFixture dummy){}
[Fact] void T(){}
[Fact] void T2(){}
}
class MyFixture
{
public MyFixture()
{
// runs once
}
}