How to parameterized C# NUnit TestFixtures with multiple browsers - c#

So I am pretty new to webdriver and nunit, I am building out regression tests for my legacy products and have the need to run my tests in multiple browsers and I would like them to be configurable to different integration environments. I have the multiple browsers working but am unsure how to parameterize the test fixtures.
[TestFixture(typeof(FirefoxDriver))]
[TestFixture(typeof(ChromeDriver))]
[TestFixture(typeof(InternetExplorerDriver))]
public class UnitTest1<TWebDriver> where TWebDriver: IWebDriver, new()
{
PTGeneral General;
[TestFixtureSetUp]
public void SetUp()
{
General = new PTGeneral();
General.Driver = new TWebDriver();
}

I would just use the TestCaseSource attribute to specify the values to each test:
[TestFixture(typeof(FirefoxDriver))]
[TestFixture(typeof(ChromeDriver))]
[TestFixture(typeof(InternetExplorerDriver))]
public class UnitTest1<TWebDriver> where TWebDriver: IWebDriver, new()
{
// ...
public IEnumerable<string> UrlsToTest
{
get
{
yield return "http://www.example.com/1";
yield return "http://www.example.com/2";
yield return "http://www.example.com/3";
}
}
[TestCaseSource("UrlsToTest")]
public void Test1(string url)
{
// ...
}
[TestCaseSource("UrlsToTest")]
public void Test2(string url)
{
// ...
}
}

The most simple answer to your question is to use [TestCase] attributes for your test methods.
Use the next example:
[TestFixture("sendSomethingToConstructor")]
class TestClass
{
public TestClass(string parameter){}
[TestCase(123)] //for parameterized methods
public void TestMethod(int number){}
[Test] //for methods without parameters
public void TestMethodTwo(){}
[TearDown]//after each test run
public void CleanUp()
{
}
[SetUp] //before each test run
public void SetUp()
{
}
}

Related

GuardClauseAssertion does not fail if limited to only public constructors

Why does this unit test not fail when no guard clause is present?
[Test]
public void ConstructorLooksGuardedAgainstNulls()
{
// ARRANGE
var fixture = new Fixture();
var assertion = fixture.Create<GuardClauseAssertion>();
// ACT & ASSERT
assertion.Verify(typeof(TestClass).GetConstructors(BindingFlags.Public));
}
Classes used in unit test:
public class TestBaseClass
{
private readonly string _firstDependency;
private readonly string _secondDependency;
protected TestBaseClass(string firstDependency, string secondDependency)
{
_firstDependency = firstDependency;
_secondDependency = secondDependency;
}
}
public class TestClass : TestBaseClass
{
public TestClass(string firstDependency)
: base(firstDependency, string.Empty)
{
}
}
I removed all the irrelevant lines.
This will return all public constructors, and then the test will fail as expected:
typeof(TestClass).GetConstructors()
The version with the BindingFlags parameter doesn't return the public constructors (although it reads like it really should do). Because no constructor are found, the test passes
typeof(TestClass).GetConstructors(BindingFlags.Public)

Reduce duplication in NUnit tests for different implementations of interface

I have the following interface:
public interface IStack
{
int Peek();
void Push(int i);
}
And two implementations:
public class LinkedListStack : IStack
{
public void Push(int x)
{
...
}
public int Peek()
{
...
}
}
public class ArrayStack : IStack
{
public void Push(int i)
{
...
}
public int Peek()
{
...
}
}
For my unit tests - I currently have something like this, two files containing the same tests - the only difference being the implementation:
LinkedListStackTest.cs:
public class LinkedListStackTest
{
[Test]
public void PushToStack()
{
//Arrange
IStack stack = new LinkedListStack();
//Act
stack.Push(1);
//Assert
Assert.AreEqual(1, stack.Peek());
}
}
ArrayStackTest.cs
public class ArrayStackTest
{
[Test]
public void PushToStack()
{
//Arrange
IStack stack = new ArrayStack();
//Act
stack.Push(1);
//Assert
Assert.AreEqual(1, stack.Peek());
}
}
Given the tests for the implementations should be the same - is there a way I can write a single set of NUnit tests that will run against all my implementations of IStack?
You can use the TestCaseSourceAttribute:
[Test]
[TestCaseSource(typeof(StackTestCases))]
public void PushToStack(IStack stack)
{
//Arrange/Act
stack.Push(1);
//Assert
Assert.AreEqual(1, stack.Peek());
}
Implementation of StackTestCases:
internal class StackTestCases : IEnumerable
{
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new LinkedListStack());
yield return new TestCaseData(new ArrayStack());
}
}
/// <inheritdoc />
public IEnumerator GetEnumerator()
{
return TestCases.GetEnumerator();
}
}
Please note that the test method will take an IStack as a parameter:
[Test]
[TestCaseSource(typeof(StackTestCases))]
public void PushToStack(IStack stack)
...And you can return the different implementations of IStack in TestCases property of StackTestCases:
yield return new TestCaseData(new LinkedListStack());
yield return new TestCaseData(new ArrayStack());
You will have to use generics for this purpose with TextFixture attributes having the implementations of your interface.
[TestFixture(typeof(LinkedListStack))]
[TestFixture(typeof(ArrayStack))]
class IStack_Contract<T> where T : IStack, new()
{
}
You just pass the types to your tests and then they will execute for the respective implementations.
You can use abstract classes to achieve this.
First, create an abstract class where you will define all your common/share tests among all your implementations:
public abstract class MyClassShould
{
protected abstract MyInterface Initialize();
protected MyInterface myInterface;
[SetUp]
public void SetUp()
{
myInterface = Initialize();
}
[Test]
public void FirstTest()
{
// do something with myInterface
// assert results
}
}
Then create a test class for your Implemenetation1
public abstract class MyFirstImplementationShould
{
protected override MyInterface Initialize()
{
return new MyFirstImplementation();
}
}
And the same for your Implementation2 which may have extra tests. For example, this implementation has a TTL expiration while the first one doesn't.
public abstract class MySecondImplementationShould
{
protected override MyInterface Initialize()
{
return new MySecondImplementation();
}
[Test]
public void TtlTest()
{
// do something with myInterface
// assert results
}
}

How do I pass reference to active driver between classes

My problem is that when firstname is suppose to be set by the driver in the FetchName method I get an error message that the driver is null. Can I pass the active driver instance in some way so I can continue fetch data?
[TestFixture]
public class TestBase
{
protected IWebDriver driverChrome;
[SetUp]
public void Setup()
{
driverChrome = new ChromeDriver();
}
[TearDown]
public void CleanSite()
{
driverChrome.Quit();
}
}
Class "Tests" where I create all my [test] methods.
public void tests: Testbase
{
[Test]
public void testmethods()
{
string blabla = driverChrome.FindElement(By.id("dsd")).Text;
Reuse.FetchName(out string firstname, out string lastname);
Assert.isTrue(firstname.equals(lastname));
}
}
One Class "Reuse" where I have methods that the [test] methods will use multiple times.
public class Reuse: Testbase
{
[Test]
public void FetchName(out string firstname, out string lastname)
{
firstname = driverChrome.FindElement(By.XPath("/html/body/div[2]/table/tbody[last()]/tr/td[2]/div")).Text;
lastname = driverChrome.FindElement(By.XPath("/html/body/div[2]/table/tbody[last()]/tr/td[2]/div")).Text;
}
}
Reuse class is not a test case. When you add attribute [Test] to the method, the method should contains an assertion. So Reuse should not inherit from Testbase.
If you want to have a class that contains multiple actions, it should be static class.
WebDriver is a standalone process. You can use multiple classes or multiple process to access it. They all will get the same WebDriver.
The example below shows how to change the Reuse class and how to use it.
public static class Reuse
{
public static IWebDriver driverChrome;
public static void FetchName(out string firstname, out string lastname)
{
firstname = driverChrome.FindElement(By.XPath("/html/body/div[2]/table/tbody[last()]/tr/td[2]/div")).Text;
lastname = driverChrome.FindElement(By.XPath("/html/body/div[2]/table/tbody[last()]/tr/td[2]/div")).Text;
}
}
You can call it like this.
public void tests: Testbase
{
[Test]
public void testmethods()
{
string blabla = driverChrome.FindElement(By.id("dsd")).Text;
Reuse.driverChrome = driverChrome;
Reuse.FetchName(out string firstname, out string lastname);
Assert.isTrue(firstname.equals(lastname));
}
}

NUnit test and how to initialize DependencyManager.Resolve

I have the following code that I need to initiate within my integration test in my C# NUnit test.
How can I initialize the DependencyManager.Resolve method please?
Many thanks,
Unit test calls this method
public static Account GetCustomer(string databaseName)
{
Database db = DatabaseFactory.CreateDatabase(databaseName);
using(DbCommand cmd = db...)
{
}
}
CreateDatabase method
public static Database CreateDatabase(string name)
{
IDbFactory factory = DependencyManager.Resolve<IDbFactory>();
return factory.GetDatabase(name);
}
Unit test
[Test]
public void When_I_Call_GetCustomer_A_Customer_Is_Returned()
{
var result = CustomerAccount.GetCustomer(..);
}
Update
DependencyManager implementation shown below
public class DependencyManager
{
public static T Resolve<T>(string key = "", ParamDictionary parameters = null)
{
return Resolver.Resolve<T>(key, parameters);
}
}
private static volatile IDependencyResolver resolver;
...
public static IDependencyResolver Resolver
{
get { return DependencyManager.resolver; }
}
It eventually gets to
public class CastleDependencyContainer : IDependencyBuilder, IDependencyResolver

AutoComplete for string parameter

I have set up a testproject using NUnit and Selenium Webdriver of which you can find a shortened version below.
class ByHolder
{
public readonly string name, path;
public readonly Func<string, By> call;
public ByHolder(string name, string path, Func<string, By> call)
{
this.name = name;
this.path = path;
this.call = call;
}
}
class Page
{
private readonly List<ByHolder> LocatorList = new List<ByHolder>();
public Page()
{
SetUpList();
}
private void SetUpList()
{
AddLocator("Button0", "//button0", By.XPath);
AddLocator("Button1", "button1", By.Id);
...
}
public By Get(string locatorName)
{
var holder = LocatorList.FirstOrDefault(p => p.name.Equals(locatorName));
return holder?.call(holder.path);
}
public void AddLocator(string name, string path, Func<string, By> call)
{
LocatorList.Add(new ByHolder(name, path,call ));
}
}
class PersonelDriver : IWebDriver
{
IWebDriver driver = new FirefoxDriver();
Page page = new Page();
public void Click(string locatorName)
{
driver.FindElement(page.Get(locatorName)).Click();
}
...
}
[TestFixture]
class PageTest
{
private readonly PersonelDriver d = new PersonelDriver();
[Test]
public void ClickTest0()
{
d.Click("Button0");
}
[Test]
public void ClickTest1()
{
d.Click("Button1");
}
...
}
As you can hopefully see I tried implementing a shortened method with a minimum of variables to make longer testcases easier to read mainly for outsiders but also for me, for example.
d.Click("that");
d.EnterText("thisLocator","text");
d.WaitFor("somethingElse");
d.Click("this");
(After using Selenium for some time I find that things can become chaotic quite fast when repeatedly using the driver.FindElement... in the tests themselves.)
Even tough I'm happy with the shortened versions and readability, there is of course no autocomplete or check since i'm handling strings and not IWebElement objects or By references that have been named or put in a specific getter.
What I used to do was the following, but it just felt wrong:
class Locators
{
public By GetButton()
{
return By.Id("button");
}
...
}
I was wondering if there is a way to implement an autocomplete or some other check for the string values when adding for example d.Click("stringvalue");
Thank you in advance.

Categories

Resources