Before Suite initialization in Xunit (C#) [duplicate] - c#

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
}
}

Related

Does AutoFixture support `DateOnly` for .NET6?

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) { }
}
}

Webdriver inheritance between clases

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()
{
}
}

Selenium tests running in parallel causing error: invalid session id

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.

AssemblyInitialize method doesnt run before tests

I am using MsTest V2 framewrok for my tests.
I have Test automation framework (TAF) project and project with tests.
Tests project inherited from TAF and contains only tests.
In TAF i have a class which contains method which should run before all tests but it doesnt work at all.
By the way BeforeTest method works fine.
public class TestBase
{
[AssemblyInitialize]
public static void BeforeClass(TestContext tc)
{
Console.WriteLine("Before all tests");
}
[TestInitialize]
public void BeforeTest()
{
Console.WriteLine("Before each test");
}
}
[TestClass]
public class FirstTest : TestBase
{
[TestMethod]
public void FailedTest()
{
Assert.IsTrue(false,"ASDASDASD");
}
}
If I put "AssemblyInitialize" method to tests projects then it work.
What am I doing wrong?
Just put [TestClass] onto your TestBase:
[TestClass]
public class TestBase
{
[AssemblyInitialize]
public static void BeforeClass(TestContext tc)
{
Console.WriteLine("Before all tests");
}
[TestInitialize]
public void BeforeTest()
{
Console.WriteLine("Before each test");
}
}

Get IWebDriver from setupfixture

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

Categories