Introduction
The newest article from the Design & Architecture Series is going to be dedicated to another abstraction. My colleagues and I decided that NUnit will be our preferred unit testing framework for our projects. However, all of our existing automation tests depend on MSTest. So we decided to add a new layer of abstraction and create a solution where you can easily choose which unit test framework you want to use.
Abstract Unit Test Framework
We created a new separate project where all abstract unit test framework's items are placed called HybridTestFramework.Core.Asserts
. The different concrete implementations reference the project and implement the interface it provides.
IAssert Interface
This is the interface that all concrete implementations need to implement. It doesn't include all methods that exist, but you can add them on demand. Include only the ones that you use in your tests.
public interface IAssert
{
void AreEqual(object expected, object actual);
void AreEqual(object expected, object actual, string message);
void AreEqual<T>(T expected, T actual) where T : class;
void AreEqual<T>(T expected, T actual, string message) where T : class;
void AreNotEqual(object expected, object actual);
void AreNotEqual(object expected, object actual, string message);
void AreNotEqual<T>(T expected, T actual) where T : class;
void AreNotEqual<T>(T expected, T actual, string message) where T : class;
void IsFalse(bool condition);
void IsFalse(bool condition, string message);
void IsTrue(bool condition);
void IsTrue(bool condition, string message);
void IsNull(object value);
void IsNull(object value, string message);
void IsNotNull(object value);
void IsNotNull(object value, string message);
void Fail(string message);
void IsInstanceOfType(object value, Type expectedType);
void IsInstanceOfType(object value, Type expectedType, string message);
}
Global Assert Wrapper
The second member of the HybridTestFramework.Core.Asserts
project is the static Assert
class. In general, it is a wrapper of the interface. It is going to use the last registration in the global Unity IoC Container for the IAssert
interface. In your page objects' asserts, you use this class because it doesn't depend on any unit test framework. This way, your core tests' projects do not rely on any particular framework. There are going to use the concrete implementation you register in your container, and only your tests' projects will carry the particular references.
public static class Assert
{
private static readonly IAssert assert;
static Assert()
{
assert = UnityContainerFactory.GetContainer().Resolve<IAssert>();
}
public static void AreEqual(object expected, object actual)
{
assert.AreEqual(expected, actual);
}
public static void AreEqual(object expected, object actual, string message)
{
assert.AreEqual(expected, actual, message);
}
public static void AreEqual<T>(T expected, T actual) where T : class
{
assert.AreEqual<T>(expected, actual);
}
public static void AreEqual<T>(T expected, T actual, string message) where T : class
{
assert.AreEqual<T>(expected, actual, message);
}
public static void AreNotEqual(object expected, object actual)
{
assert.AreNotEqual(expected, actual);
}
public static void AreNotEqual(object expected, object actual, string message)
{
assert.AreNotEqual(expected, actual, message);
}
public static void AreNotEqual<T>(T expected, T actual) where T : class
{
assert.AreNotEqual<T>(expected, actual);
}
public static void AreNotEqual<T>(T expected, T actual, string message) where T : class
{
assert.AreNotEqual<T>(expected, actual, message);
}
public static void IsFalse(bool condition)
{
assert.IsFalse(condition);
}
public static void IsFalse(bool condition, string message)
{
assert.IsFalse(condition, message);
}
public static void IsTrue(bool condition)
{
assert.IsTrue(condition);
}
public static void IsTrue(bool condition, string message)
{
assert.IsTrue(condition, message);
}
public static void IsNull(object value)
{
assert.IsNull(value);
}
public static void IsNull(object value, string message)
{
assert.IsNull(value, message);
}
public static void IsNotNull(object value)
{
assert.IsNotNull(value);
}
public static void IsNotNull(object value, string message)
{
assert.IsNotNull(value, message);
}
public static void Fail(string message)
{
assert.Fail(message);
}
public static void IsInstanceOfType(object value, Type expectedType)
{
assert.IsInstanceOfType(value, expectedType);
}
public static void IsInstanceOfType(object value, Type expectedType, string message)
{
assert.IsInstanceOfType(value, expectedType, message);
}
}
Concrete Asserts Implementations
MSTest Implementation
For the concrete MSTest implementation of the IAssert
interface, we create a separate project called HybridTestFramework.Core.MSTest.Asserts
where the MSTestAssert
class is situated. Of course, it should reference Microsoft.VisualStudio.QualityTools.UnitTestFramework
assembly. The methods only wrap the actual MSTest
's assert
methods.
public class MSTestAssert : IAssert
{
public void AreEqual(object expected, object actual)
{
VSU.Assert.AreEqual(expected, actual);
}
public void AreEqual(object expected, object actual, string message)
{
VSU.Assert.AreEqual(expected, actual, message);
}
public void AreEqual<T>(T expected, T actual) where T : class
{
VSU.Assert.AreEqual<T>(expected, actual);
}
public void AreEqual<T>(T expected, T actual, string message) where T : class
{
VSU.Assert.AreEqual<T>(expected, actual, message);
}
public void AreNotEqual(object expected, object actual)
{
VSU.Assert.AreNotEqual(expected, actual);
}
public void AreNotEqual(object expected, object actual, string message)
{
VSU.Assert.AreNotEqual(expected, actual, message);
}
public void AreNotEqual<T>(T expected, T actual) where T : class
{
VSU.Assert.AreNotEqual<T>(expected, actual);
}
public void AreNotEqual<T>(T expected, T actual, string message) where T : class
{
VSU.Assert.AreNotEqual<T>(expected, actual, message);
}
public void Fail(string message)
{
VSU.Assert.Fail(message);
}
public void IsFalse(bool condition)
{
VSU.Assert.IsFalse(condition);
}
public void IsFalse(bool condition, string message)
{
VSU.Assert.IsFalse(condition, message);
}
public void IsInstanceOfType(object value, Type expectedType)
{
VSU.Assert.IsInstanceOfType(value, expectedType);
}
public void IsInstanceOfType(object value, Type expectedType, string message)
{
VSU.Assert.IsInstanceOfType(value, expectedType, message);
}
public void IsNotNull(object value)
{
VSU.Assert.IsNotNull(value);
}
public void IsNotNull(object value, string message)
{
VSU.Assert.IsNotNull(value, message);
}
public void IsNull(object value)
{
VSU.Assert.IsNull(value);
}
public void IsNull(object value, string message)
{
VSU.Assert.IsNull(value, message);
}
public void IsTrue(bool condition)
{
VSU.Assert.IsTrue(condition);
}
public void IsTrue(bool condition, string message)
{
VSU.Assert.IsTrue(condition, message);
}
}
NUnit Implementation
For the concrete NUnit implementation of the IAssert
interface, we create a separate project called HybridTestFramework.Core.NUnit.Asserts
where the NunitAssert
class is present. You should install the NUnit NuGet. The class's methods only call the NUnit's assert
methods.
public class NunitAssert : IAssert
{
public void AreEqual(object expected, object actual)
{
NUF.Assert.That(actual, NUF.Is.EqualTo(expected));
}
public void AreEqual(object expected, object actual, string message)
{
NUF.Assert.That(actual, NUF.Is.EqualTo(expected), message);
}
public void AreEqual<T>(T expected, T actual) where T : class
{
NUF.Assert.That<T>(actual, NUF.Is.EqualTo(expected));
}
public void AreEqual<T>(T expected, T actual, string message) where T : class
{
NUF.Assert.That<T>(actual, NUF.Is.EqualTo(expected), message);
}
public void AreNotEqual(object expected, object actual)
{
NUF.Assert.That(actual, NUF.Is.Not.EqualTo(expected));
}
public void AreNotEqual(object expected, object actual, string message)
{
NUF.Assert.That(actual, NUF.Is.Not.EqualTo(expected), message);
}
public void AreNotEqual<T>(T expected, T actual) where T : class
{
NUF.Assert.That<T>(actual, NUF.Is.Not.EqualTo(expected));
}
public void AreNotEqual<T>(T expected, T actual, string message) where T : class
{
NUF.Assert.That<T>(actual, NUF.Is.Not.EqualTo(expected), message);
}
public void Fail(string message)
{
NUF.Assert.Fail(message);
}
public void IsFalse(bool condition)
{
NUF.Assert.That(condition, NUF.Is.False);
}
public void IsFalse(bool condition, string message)
{
NUF.Assert.That(condition, NUF.Is.False, message);
}
public void IsInstanceOfType(object value, Type expectedType)
{
NUF.Assert.That(value, NUF.Is.TypeOf(expectedType));
}
public void IsInstanceOfType(object value, Type expectedType, string message)
{
NUF.Assert.That(value, NUF.Is.TypeOf(expectedType), message);
}
public void IsNotNull(object value)
{
NUF.Assert.That(value, NUF.Is.Not.Null);
}
public void IsNotNull(object value, string message)
{
NUF.Assert.That(value, NUF.Is.Not.Null, message);
}
public void IsNull(object value)
{
NUF.Assert.That(value, NUF.Is.Null);
}
public void IsNull(object value, string message)
{
NUF.Assert.That(value, NUF.Is.Null, message);
}
public void IsTrue(bool condition)
{
NUF.Assert.That(condition, NUF.Is.True);
}
public void IsTrue(bool condition, string message)
{
NUF.Assert.That(condition, NUF.Is.True, message);
}
}
Abstract Unit Test Framework in Tests
Page Asserter
Your page asserter's project is no more obligated to reference the Microsoft.VisualStudio.QualityTools.UnitTestFramework
assembly. You only need to add a reference to the HybridTestFramework.Core.Asserts
. After that, exchange the using
statements as in the example.
using HybridTestFramework.Core.Asserts;
namespace AbstractUnitTestFramework.Pages.BingMain
{
public static class BingMainPageAsserter
{
public static void AssertResultsCountIsAsExpected(
this BingMainPage page,
string expectedResultCount)
{
Assert.AreEqual(
page.ResultsCountDiv.Content,
expectedResultCount,
"The results count is not as expected.");
}
}
}
MSTest Example
The only special thing that you need to do is the last registration in the global Unity container - UnityContainerFactory.GetContainer().RegisterType<IAssert, MSTestAssert>()
. This way, the asserts of your pages will start working with MSTest.
[TestClass]
public class BingTestsMsTest
{
private IDriver driver;
[TestInitialize]
public void SetupTest()
{
UnityContainerFactory.GetContainer().RegisterType
<IDriver, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<INavigationService, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IBrowser, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<ICookieService, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IDialogService, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IElementFinder, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IJavaScriptInvoker, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType<IInputSubmit, InputSubmit>();
UnityContainerFactory.GetContainer().RegisterType<ISearch, Search>();
UnityContainerFactory.GetContainer().RegisterType<IDiv, Div>();
UnityContainerFactory.GetContainer().RegisterType<BingMainPage>();
UnityContainerFactory.GetContainer().RegisterInstance
<IUnityContainer>(UnityContainerFactory.GetContainer());
UnityContainerFactory.GetContainer().RegisterInstance
<BrowserSettings>(BrowserSettings.DefaultChomeSettings);
this.driver = UnityContainerFactory.GetContainer().Resolve<IDriver>();
UnityContainerFactory.GetContainer().RegisterInstance<IDriver>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IBrowser>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<ICookieService>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IDialogService>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IJavaScriptInvoker>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<INavigationService>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IElementFinder>(this.driver);
UnityContainerFactory.GetContainer().RegisterType<IAssert, MSTestAssert>();
}
[TestMethod]
public void SearchForAutomateThePlanet()
{
var bingMainPage = UnityContainerFactory.GetContainer().Resolve<BingMainPage>();
bingMainPage.Navigate();
bingMainPage.Search("Automate The Planet");
bingMainPage.AssertResultsCountIsAsExpected("422,000 results");
}
}
NUnit Example
The examples are completely identical with the only difference that the second one uses NUnit unit test framework. Instead of registering MSTestAssert
class for the IAssert
interface, we use the NunitAssert
.
[TestFixture]
public class BingTestsNUnit
{
private IDriver driver;
[SetUp]
public void Init()
{
UnityContainerFactory.GetContainer().RegisterType
<IDriver, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<INavigationService, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IBrowser, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<ICookieService, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IDialogService, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IElementFinder, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType
<IJavaScriptInvoker, TestingFrameworkDriver>();
UnityContainerFactory.GetContainer().RegisterType<IInputSubmit, InputSubmit>();
UnityContainerFactory.GetContainer().RegisterType<ISearch, Search>();
UnityContainerFactory.GetContainer().RegisterType<IDiv, Div>();
UnityContainerFactory.GetContainer().RegisterType<BingMainPage>();
UnityContainerFactory.GetContainer().RegisterInstance
<IUnityContainer>(UnityContainerFactory.GetContainer());
UnityContainerFactory.GetContainer().RegisterInstance
<BrowserSettings>(BrowserSettings.DefaultChomeSettings);
this.driver = UnityContainerFactory.GetContainer().Resolve<IDriver>();
UnityContainerFactory.GetContainer().RegisterInstance<IDriver>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IBrowser>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<ICookieService>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IDialogService>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IJavaScriptInvoker>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<INavigationService>(this.driver);
UnityContainerFactory.GetContainer().RegisterInstance<IElementFinder>(this.driver);
UnityContainerFactory.GetContainer().RegisterType<IAssert, NunitAssert>();
}
[Test]
public void SearchForAutomateThePlanet()
{
var bingMainPage = UnityContainerFactory.GetContainer().Resolve<BingMainPage>();
bingMainPage.Navigate();
bingMainPage.Search("Automate The Planet");
bingMainPage.AssertResultsCountIsAsExpected("422,000 results");
}
}
Design & Architecture
The post Create Hybrid Test Framework- Abstract Unit Test Framework appeared first on Automate The Planet.
All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.
License Agreement