Nested TestFixture in different classes - c#

I am trying to create a web automation that logs in and out just once. As the website is formed by different products I am required to build different sets of tests in different classes/files(Exaple: ReportsTests, AuthenticationTests, etc.) I am perfectly able to create a TestFixture which logs in and out using the OneTimeSetup and OneTimeTearDown but that happens once for every class.
What I am trying to create is a TestFixture within a TestFixure in a way that the Login and Logout happens once on the first TestFixture and the second execute the sets of tests.
So far I've got this:
Setup.cs
using NUnit.Framework;
using System;
namespace TestsSetup
{
[TestFixture]
public class TestSetup
{
[OneTimeSetUp]
public void Setup()
{
Console.WriteLine("Login in");
}
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Login out");
}
}
}
TestSuit.cs
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using TestsSetup;
namespace TCISuiteSetup
{
[TestFixture]
public class CWTestSuite : TestSetup
{
[TestFixture(1)]
public class SuiteSetup
{
[OneTimeSetUp]
public void Setup()
{
Console.WriteLine("Nothing happens on this step");
}
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Nothing happens on this step");
}
}
}
}
Test1.cs
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using TCISuiteSetup;
namespace TCI.Tests
{
[TestFixture(1)]
public class UserManagerTests : CWTestSuite.SuiteSetup
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
test2.cs
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using TCISuiteSetup;
namespace TCI.Tests
{
[TestFixture(1)]
public class ReportTests : CWTestSuite.SuiteSetup
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
If I run the test like this all tests fail. If I remove the (1) from the TestFixture(1) it pass everything but it does not hit any of the [OneTimeSetup]/[OneTimeTearDown] if I change the UserManagerTests : TestSuite.SuiteSetup to UserManager : TestSetup it hits just the first [TestFixture]
Am I missing anything.

dNesting of test fixture classes has no meaning whatsoever to NUnit. For a few years we have talked about making it meaningful, but never did anything about it.
SO, in terms of test fixtures, CWTestSuite and CWTestSuite.SetUpFixture have no relationship at all. It's just as if they were defined separately, without nesting.
If you want one fixture to group fixtures, NUnit provides SetUpFixture, which is a way to define one-time setup and teardown behavior that applies across multiple classes. A SetUpFixture is defined for a particular namespace and essentially wraps all the TestFixtures defined within that namespace and subordinate namespaces.
For example, if you were to put all your TestFixtures in some common namespace, then you could add a SetUpFixture in the same namespace like this...
namespace Some.Common.Namespace
{
[SetUpFixture]
public class TestSetup
{
[OneTimeSetUp]
public void Setup()
{
Console.WriteLine("Login in");
}
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Login out");
}
}
public class UserManagerTests
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
public class ReportTests
{
[Test]
public void Test1()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test2()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
Note that I have made no use of inheritance in this example. It's not required and would break things if I had used it. If you need some common initialization logic for some but not all of the fixtures in the namespace, then you can give them a common base class, but that must be separate from the SetUpFixture and should ideally be abstract.
As a minor note, I removed all redundant [TestFixture] annotations. That's the style I recommend.

I found a way but maybe it is not the most elegant:
Setup.cs
using NUnit.Framework;
using System;
namespace TestsSetup
{
[TestFixture]
public class CWTestSuite : TestSetup
{
[TestFixture]
public class SuiteSetup
{
static private bool isLoggedOn;
[OneTimeSetUp]
public void TestSuiteSetup()
{
if (isLoggedOn == false)
{
Console.WriteLine("Loggin happens here");
isLoggedOn = true;
}
}
}
}
[SetUpFixture]
public class TestSetup
{
[OneTimeTearDown]
public void Teardown()
{
Console.WriteLine("Login out happens here");
}
[TestFixture]
public class Testing
{
[Test]
public void Test1()
{
Console.WriteLine("All tests for this product has been executed");
}
}
}
}
any of the test.cs matching the following format
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using static TestsSetup.CWTestSuite;
namespace TestSetup
{
[TestFixture]
public class UserManagerTests : SuiteSetup
{
[Test]
public void Test3()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
[Test]
public void Test4()
{
Console.WriteLine("Assertion");
Assert.AreEqual(1, 1);
}
}
}
I could not get rid of the [TestFixture] within the [TestFixture] (Setup.cs/public class CWTestSuite). If I delete it it will hit the [OneTimeTearDown] after running the tests in a class.
I had to add a flag on the login steps as that [OneTimeSetUp] is called at the beginning of every set of tests.
The only way I found to trigger the [OneTimeTearDown] was to add a [TestFixture]/[Test] afterwards. it is called at the very end and it may just print a console.log but it needs to be there and it needs to be called.
BTW. This is a possible solution/work around but not recommended at all. If you want to do something like this I recommend using NUnit + SpecFlow (The [BeforeTestRun] is what you are looking for.

Related

How can i define a different order of my unit tests?

I have these 3 tests:
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.Threading;
namespace FirstTestCase
{
class _04_02_Media
{
class NUnitTest
{
[TestCase(TestName = "04_02_01_Libraries_Add_OnDemand_Video")]
public void Libraries()
{}
[TestCase(TestName = "04_02_02_Replace_OnDemand")]
public void OnDemandReplace()
{}
[TestCase(TestName = "04_02_03_Delete_OnDemand")]
public void OnDemandDelete()
{}
For some reason i cannot understand and is making me go crazy, the "delete" test, the one supposed to be the last, happens second.
This is a big deal as the "replace" test, that happens last, uses the deleted video.
Why does it run in this order? Is there anything else i should use to change the order?
You can use the Order attribute to specify the order:
[Order(1)]
public void Test1() { /* ... */ }
[Order(2)]
public void Test2() { /* ... */ }
[Order(3)]
public void Test3() { /* ... */ }
However, you should really try to make sure your tests are self-contained otherwise they can be quite brittle.
Just use order attribute.
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.Threading;
namespace FirstTestCase
{
class _04_02_Media
{
class NUnitTest
{
[Test, Order(1)]
public void Libraries()
{}
[Test, Order(2)]
public void OnDemandReplace()
{}
[Test, Order(3)]
public void OnDemandDelete()
{}
}
}
}

NUnit: how to invoke Test from another class with Parallelizable

When trying to invoke a Test from a different class from where it is implemented, it does not execute the Parallelizable attribute, instead, it only executes the methods sequentially ( Alltest_2() and Alltest_1() ). Is there any way to invoke them so that they are executed in parallel?
Here's a code sample:
public class AO_Alarms_4 : AO_Alarms_3
{
[SetUp]
public void DefaultSetUp(){ }
[Test]
public void Alltest_Clases()
{
Alltest_2();
Alltest_1();
}
[TearDown]
public void DefaultTearDown() { }
}
[TestFixture]
[Parallelizable]
public class AO_Alarms_3 : AO_Alarms_2
{
public WebDriverFactory driver = new WebDriverFactory(Utils.Browser);
[SetUp]
public void login_2()
{
//code
}
[Test]
[Parallelizable]
public void Alltest_2()
{
test_2();
}
public void test_2()
{
//code
}
[TearDown]
public void teardown_2()
{
//code
}
}
[TestFixture]
[Parallelizable]
public class AO_Alarms_2
{
public WebDriverFactory driver = new WebDriverFactory(Utils.Browser);
[SetUp]
public void login_1()
{
//code
}
[Test]
[Parallelizable]
public void Alltest_1()
{
test1_1();
test1_2();
}
[Test]
public void test1_1()
{
//code
}
[Test]
public void test1_2()
{
//code
}
[TearDown]
public void teardown_1()
{
//code
}
}
You can't simply call tests yourself and expect to get any of the normal NUnit behavior around tests. For example, NUnit knows what to do when it calls a test with [Parallelizable] on it - and what it does is fairly complicated. Your own call is simply calling the method you wrote.
There is nothing to stop you from calling common methods within a given test, but the tests themselves have to be invoked by NUnit.
If you can rephrase or ask another question about what you are actually trying to accomplish here, we can probably give you some advice about alternatives.

C# calling a static method

So I'm a java developer new to C# and I can't seem to get this trivial thing working. I have a Tests class which tests a method in another class. For convenience, I made these static so not to rely on any instantiation. For some reason though, my Tests class can't seem to find my Kata class.
namespace Codewars
{
public class Program
{
static void Main(string[] args)
{
}
public static string HoopCount(int n)
{
if (n >= 10)
{
return "Great, now move on to tricks";
}
else
{
return "Keep at it until you get it";
}
}
}
}
Test:
using NUnit.Framework;
namespace Codewars
{
[TestFixture]
class Tests
{
[Test]
public static void FixedTest()
{
Assert.AreEqual("Keep at it until you get it", Kata.HoopCount(6), "Should work for 6");
Assert.AreEqual("Great, now move on to tricks", Kata.HoopCount(22), "Should work for 22");
}
}
}
Your static method is declared inside Program, not Kata, so you should refer to it as Program.HoopCount(someint)

NUnit equivalent of JUnit's Rule

Is there an equivalent of JUnit's Rule in C# ? I mean a way to avoid the repetition the same [SetUp] and [TearDown] lines in several different tests. Instead of:
[SetUp]
public void SetUp()
{
myServer.connect();
}
[TearDown]
public void TearDown()
{
myServer.disconnect();
}
... put the logic in a rule that can be declared as field in several tests:
public MyRule extends ExternalResource {
#Override
protected void before() throws Throwable
{
myServer.connect();
};
#Override
protected void after()
{
myServer.disconnect();
};
};
and then
class TestClass
{
#Rule MyRule = new MyRule();
...
}
You could implement your own TestActionAttribute class that runs your before- and after-test code. If you intend to perform the same action before and after every test, you can define your custom attribute at the class declaration.
e.g.:
[MyRule] // your custom attribute - applied to all tests
public class ClassTest
{
[Test]
public void MyTest()
{
// ...
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyRuleAttribute : TestActionAttribute
{
public override void BeforeTest(TestDetails testDetails)
{
// connect
}
public override void AfterTest(TestDetails testDetails)
{
// disconnect
}
}
NUnit works well with tests inheritance, so you can create a base test class with SetUp and TearDown methods:
[TestFixture]
public class BaseTest
{
[SetUp]
public virtual void SetUpTest()
{
//...
}
[TearDown]
public virtual void TearDownTest()
{
//...
}
}
Then create a regular test class that inherits from the base class and it will reuse the SetUp and TearDown implementations:
[TestFixture]
public class RegularTest : BaseTest
{
[Test]
public virtual void MyTest()
{
//...
}
}

How to Run c# Multiple Selenium Unit Test with one driver instance?

i have a problem running Multiple C# Selenium Unit Test tests with one driver instance.
Please find my class as below.
Folder : Com.Main.Web.Selenium
SeleniumTestInitialize.cs is the main class which contains the driver.
[DeploymentItem(#"Resources\IEDriverServer.exe")]
public class SeleniumTestInitialize
{
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
private TestContext testContextInstance;
public bool SeleniumExecutionTerminateFlag=false;
public SeleniumTestInitialize seleniumTestInitalize;
public FindWebDriverElement findWebDriverElement;
public JavaScriptCalls javaScriptCalls;
public OperateOnWebDriverElement operateOnWebDriverElement;
**public RemoteWebDriver driver;**
// how to use this driver object across multiple unit test classes
public string baseURL;
public void SeleniumSetup()
{
try
{
Console.WriteLine("Starting Driver...........");
seleniumTestInitalize = new SeleniumTestInitialize();
var options = new InternetExplorerOptions
{
IntroduceInstabilityByIgnoringProtectedModeSettings = true,
//ForceCreateProcessApi=true
EnableNativeEvents = false,
RequireWindowFocus = false,
IgnoreZoomLevel = true
};
driver = new InternetExplorerDriver(TestContext.DeploymentDirectory, options);
javaScriptCalls = new JavaScriptCalls(driver);
findWebDriverElement = new FindWebDriverElement(javaScriptCalls);
operateOnWebDriverElement = new OperateOnWebDriverElement(findWebDriverElement);
GoToSite(ConfigParameters.WEB_APPLICATION_URL);
driver.Manage().Window.Maximize();
}
catch (Exception e)
{
log.Debug("Error Starting Web Driver...........");
Console.WriteLine(e.StackTrace);
}
}
public bool SeleniumInitalizeCheck()
{
if (seleniumTestInitalize != null)
return true;
else
return false;
}
public void SeleniumQuit()
{
Console.WriteLine("Quitting Driver...........");
try
{
if (driver != null)
{
driver.Quit();
}
log.Info("Closing Web Driver...........");
ProcessMgn.killProcessByNames("IEDriverServer");//Make sure the process is killed
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
public void GoToSite(string urlToOpen)
{
driver.Navigate().GoToUrl(urlToOpen);
}
}
Folder com.main.tests
Test01.cs
[TestClass]
public class Test01 : SeleniumTestInitialize
{
[TestInitialize]
public void Setup()
{
SeleniumExecutionTerminateFlag = false;
if (!SeleniumInitalizeCheck())
{
SeleniumSetup();
}
}
[TestCleanup]
public void TearDown()
{
if (SeleniumExecutionTerminateFlag)
{
SeleniumQuit();
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://tfsserver:8080/tfs/PoL;project", "1320", DataAccessMethod.Sequential)]
public void UCP002_M1()
{
var userName = this.TestContext.DataRow["UserName"].ToString();
var passWord = this.TestContext.DataRow["PassWord"].ToString();
//use the local host adress for your project here->
baseURL = this.TestContext.DataRow["URL"].ToString();
driver.Navigate().GoToUrl(baseURL);
//driver.FindElement(By.XPath("//html/body/div[2]/div/a/p/desc")).Click();
//driver.FindElement(By.Id("registerLink")).Click();
driver.FindElement(By.Id("ctl00_LoginTextBox")).Clear();
driver.FindElement(By.Id("ctl00_LoginTextBox")).SendKeys(userName);
driver.FindElement(By.Id("ctl00_PasswordTextbox")).Clear();
driver.FindElement(By.Id("ctl00_PasswordTextbox")).SendKeys(passWord);
driver.FindElement(By.Id("ctl00_LogInButton")).Click();
}
}
Test02.cs
[TestClass]
public class Test02 : SeleniumTestInitialize
{
[TestInitialize]
public void Setup()
{
SeleniumExecutionTerminateFlag = false;
if (!SeleniumInitalizeCheck())
{
SeleniumSetup();
}
}
[TestCleanup]
public void TearDown()
{
if (SeleniumExecutionTerminateFlag)
{
SeleniumQuit();
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://tfsserver:8080/tfs/PoL;project", "1320", DataAccessMethod.Sequential)]
public void Test02()
{
//some test script
}
}
I have created an ordered test and prioritized the tests in the order of execution . But it is invoking two instances of the driver that means two times the browser.
My question is to How to share a single driver object across all selenium unit tests ?? create at the start and close the driver at the end.
Thanks.
HI If you are using using NUnit.Framework;
The code Execution plan is like below.
For First Test Case
[TestFixtureSetup] ---->For each test case this will work so here we can
initialize the driver instance.
[TestMethod] ----->test method will goes here
[TearDown] -----> clean up code
**For Second Test Case**
[TestFixtureSetup]
[TestMethod]
[TearDown]
If you have to run both test case in one browser instance
Dont close the driver inside TearDown.
AND INITIALIZE THE DRIVER UNDER TextFixtureSetup
[TestFixture()]
public class TestClass
{
[TestFixtureSetUp]
public void Init()
{
Driver.initialize(new InternetExplorerDriver());
}
[TearDown]
public void Close()
{
//dont do any driver.close()
}
[TestMethod]
public void TestCase001()
{
//your code goes here
}
[TestMethod]
public void TestCase002()
{
//your code goes here
}
You can take a look on this thread, where I answered how I did it: How to run multiple test methods in same browser instance without closing it (C#, SeleniumWebDriverz NUnit)?
Basically, I used:
using Microsoft.VisualStudio.TestTools.UnitTesting;
Instead of:
using NUnit.Framework;
So now I have next hierarchy:
[TestFixture]
[TestFixtureSetup] // this is where I initialize my WebDriver " new FirefoxDriver(); "
[Test] //first test
[Test] //second test
[Test] //third test
[TestFixtureTearDown] // this is where I close my driver
With this changes, my browser will open only once for TestFixture (or TestClass if you use "using Microsoft.VisualStudio.TestTools.UnitTesting;") and all [Test]-s from that fixture will run in that same browser instance. After all tests are done, browser will close.
Hope this will help someone else in future. Ask me if you need additional help.
I used NUnit Framework:
using NUnit.Framework;
I then set up my WebDriver initialisation, test and teardown like this:
[TestFixture()]
class NUnitSeleniumTests
{
[OneTimeSetUp]
public void Init()
{
driverIE = new InternetExplorerDriver(ConfigurationManager.AppSettings["IEDriver"]);
driverIE.Manage().Window.Maximize();
// other setup logic
}
[Test]
public void TestMethod1()
{
// Test logic
}
[Test]
public void TestMethod2()
{
// Test logic
}
...
...
...
[Test]
public void TestMethodN()
{
// Test logic
}
[OneTimeTearDown]
public void Close()
{
driverIE.Close();
}
}
When I Run All tests, the WebDriver driverIE is initialised. All tests then execute in that WebDriver instance before the WebDriver instance is closed at the end of the test run.
The tests execute in alphabetical order by default; each test can also execute in isolation.

Categories

Resources