I have a project where multiple test classes share a base class fixture.
As expected, the fixture's constructor runs before any test in the test class is run.
Is there a way for this class fixture's constructor to know the name of the test class that is about to run?
Background: My project is not doing unit testing, but rather I'm using xUnit.net to run an alternate type of testing. All the classes and tests will run in order, so a class is guaranteed to run completely before another class tries to run.
Here is an example of what I'd like to be able to do:
using Xunit;
using Xunit.Abstractions;
namespace TestingProject
{
// In my project, the classes are guaranteed to run in order, one after the other. Tests won't randomly execute between classes.
// This fixture is used by multiple test classes. It handles logging test class starts and stops to the db.
public class SharedTestingClassFixture : IDisposable
{
// This will run at the start of every testing class.
public SharedTestingClassFixture()
{
// Need to get name of class that is about to execute, i.e. "TestingClassName"
var nameOfTestingClass = "";
// Log name of class that is about to start to the db BEFORE any tests run.
var logMessage = $"{nameOfTestingClass} class starting";
}
// This will run at the end of every testing class.
public void Dispose()
{
// Log class ending to db after all tests in this class have finished.
}
}
public class TestingClassName : TestClassBase, IDisposable, IClassFixture<SharedTestingClassFixture>
{
// This will run before each individual test.
public TestingClassName(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
// At this point, I need to already have written the class name to the db; BEFORE this constructor is called.
// The TestClassBase (not shown) constructor then extracts the test name from testOutputHelper and logs to db.
}
// This will run after each individual test.
public void Dispose()
{
}
[Fact]
public void Test1()
{
// Testing code here
}
[Fact]
public void Test2()
{
// Testing code here
}
}
}
Related
i've got an issue with ExtentReport, i have few classes with tests and i want to generate a report with all the tests included in it. I have created a BaseTest class with extent report initialization the the test classes has inhertied it and using the static variables to create test, my issue is the BaseTest class test has an [OneTimeTearDown] method in it with extent.Flush() and it called after each of the classes is finished the tests in it and then the result is the last class has overrides the classes before it. Thank you in advance !
Base Class:
[SetUpFixture]
public class BaseClass
{
public static ExtentReports extent;
public static ExtentHtmlReporter htmlReporter;
public static ExtentTest extentTest;
private string path = ""
[OneTimeSetUp]
public void SetUp()
{
htmlReporter = new ExtentHtmlReporter(path);
extent = new ExtentReports();
extent.AttachReporter(htmlReporter);
htmlReporter.Config.DocumentTitle = "Tests Report";
htmlReporter.Config.ReportName = "Issta Tests Report";
extent.AddSystemInfo("OS", "Windows 10");
extent.AddSystemInfo("Environment", "QA");
extent.AddSystemInfo("User Name", "Valeri Rozenberg");
}
[OneTimeTearDown]
public void TearDown()
{
extent.Flush();
// Email.sendEmail(path);
}
}
Test class:
namespace AutomationTests
{
[TestFixture]
public class AutomaticDeals: BaseClass
{
DriverManager driverManager;
public IWebDriver driver;
public string url = ""
[SetUp]
public void SetUpTests()
{
driverManager =
DriverManagerFactory.GetDriverManager(DriverType.Chrome);
driver = driverManager.GetWebDriver();
driver.Url = url;
}
[Test]
public void TestLinks()
{
extentTest = extent.CreateTest("TestLinks");
AutomaticDealsPage aDeals = new AutomaticDealsPage(driver);
Assert.IsTrue(aDeals.CheckEqualUrls(1));
extentTest.Log(Status.Pass, "Url's in the automatic deals
page are equal.");
}
[Test]
public void TestPrices()
{
extentTest = extent.CreateTest("TestPrices");
AutomaticDealsPage aDeals = new AutomaticDealsPage(driver);
Assert.IsTrue(aDeals.allPricesEqual());
extentTest.Log(Status.Pass, "Prices in the automatic deals
page are equal.");
}
}
}
Simplifying the problem statement:
You have an action (initializing the extent report), which you want to perform before any tests run.
You have another action (flushing the extent report), which you want to perform after all the tests have run.
If these actions are made part of a base class, the code is run repeatedly, either once for each test method if you use '[SetUp]and[TearDown]or once for each test fixture class using[OneTimeSetUp]` and '[OneTimeTearDown]'. So what you want to do can't be accomplished in a base class.
Actually, the first part (initialization) can be done in the base class, using a static flag so that you only initialize the first time. However, there's no way for your code to know that it is being called for the last time, so the second part is impossible.
This kind of situation is what SetUpFixtureAttribute is intended to deal with.
Create a new class marked as a [SetUpFixture]. Place the class either in a top-level namespace, which contains all your tests, or (simpler) outside of any namespace.
Give that class [OneTimeSetUp] and [OneTimeTearDown] methods. Move the actions you want to perform before and after running tests into those methods, respectively.
Defined in a SetUpFixture outside of any namespace, the initialization actions will happen before any tests in the assembly are run and the teardown after all of them have completed.
If the one-time initialization leaves behind any info for your tests to use, save that info in static properties of the class.
I use HttpSelfHostServer to build a RESTful API that uses SQLite database.
I use Moq assembly to mock my database.
Using Nunit I write a TestFixture with SetUp method, which construct MockDatabaseContext. And I have couple tests, that use this MockDatabaseContext.
Now I want to use MockDatabaseContext in all my tests in the test project.
I read article that says:
"...A SetUpFixture outside of any namespace provides SetUp and
TearDown for the entire assembly..."
I moved my SetUp method to another class Init, which is placed in no-namespace, and changed attribute to OneTimeSetUp. That setup's method worked perfectly only one time before running all tests in the assembly as I want.
But the OneTimeSetUp method construct MockDatabaseContext inside not static Init class. How can i pass created MockDatabaseContext to all other tests, which all started after OneTimeSetUp?
[SetUpFixture]
public class Init
{
public Mock<MyDBContext> MockDatabaseContext
[OneTimeSetUp]
public void OneTimeSetUpMethod()
{
MockDatabaseContext = SomeFunctionConstructsMockedContext();
}
}
namespace All.My.Tests
{
[TestFixture]
public class TestFixture1
{
[TestCase]
public void Test1() {/* Here i want to be able using MockDatabaseContext */}
public void Test2() {/* Here i want to be able using MockDatabaseContext */}
public void Test3() {/* Here i want to be able using MockDatabaseContext */}
}
/* Some other fixtures with tests that must have MockDatabaseContext */
}
Thanx
What i want to do is this :
Create a bunch of Unit Tests.
Create a variety of different permutations/combinations of initialization of mocks, input variables etc.
Run each given unit test with a against a set of such initializations based on some parameters.
How would i go about doing something like this?
Is there already any framework to handle this (I.e. run a given test multiple times while changing initialization)? Can you suggest any design or ideas with which i could make something to do this?
I am aware of unit testing frame works. i use NUnit and Rhino mocks myself.
Shown below is an example of what i need.
[Test Initialize]
Setup( <-possible parameter-> )
[Test Method]
TestA()
now i want TestA() to be run multiple times. Each time the Test initialize would pick another initialization combination.
More clarification
Lets suppose a test would require variables A, B, C. Each of them are very complex objects with the end result that the a large number of combinations can be formed. So i'm hoping that somehow i could create a test initialize that could possible iterate through a list of such combinations, so it would initialize them, run the TESTA, go back to next initialization in the list, run TESTA again and so on until the list runs out. Next it picks another list for TESTB and once again follows this process.
At the least im hoping for some ability to be able to run a given TEST function n times. The rest i know i can build once this is possible
In nUnit you can use the [TestCase] attribute for simple types:
[Test]
[TestCase("a", "b")]
[TestCase("c", "b")]
[TestCase("a", "d")]
public void TestMethod(string param1, string param2){
// run your test with those parameters
}
Or you can use a TestCaseSource method for complex types:
[Test]
[TestCaseSource("GetTestCases")]
public void TestMethod(MyObject1 param1, MyObject2 param2){
// run your test with those parameters
}
private IEnumerable GetTestCases(){
yield return new TestCaseData( new MyObject1("first test args"),
new MyObject2("first test args"))
.SetName("SomeMeaningfulNameForThisTestCase" );
yield return new TestCaseData( new MyObject1("2nd test args"),
new MyObject2("2nd test args"))
.SetName("SomeMeaningfulNameForThisTestCase2" );
}
You can do something similar in MS-Test using a DataSource:
http://codeclimber.net.nz/archive/2008/01/18/How-to-simulate-RowTest-with-MS-Test.aspx
You might be able to do this without needing any framework-specific addons by creating an abstract base class that contains all your test functions, then inheriting that base class with multiple classes, each with their own setup function.
public abstract class MyTests
{
[Test]
public void TestOne()
{
...
}
[Test]
public void TestTwo()
{
...
}
}
[TestFixture]
public class FirstSetup : MyTests
{
[Setup]
public void Setup()
{
...
}
}
[TestFixture]
public class SecondSetup : MyTests
{
[Setup]
public void Setup()
{
...
}
}
I have done this in other languages, but not sure how the various C# frameworks will handle it.
I'm trying to setup my tests using Xunit. I have a requirement to delete all images in a folder start of the tests, and then each method does some image resizing and saves a copy of it's output to the folder. The folder should only be emptied once, and then each method will save their own image into the folder.
When I use IUseFixture<T>, the ClearVisualTestResultFolder function is still being called before every test, so I only end up with one image in the folder.
public class Fixture
{
public void Setup()
{
ImageHelperTest.ClearVisualTestResultFolder();
}
}
public class ImageHelperTest : IUseFixture<EngDev.Test.Fixture>
{
public void SetFixture(EngDev.Test.Fixture data)
{
data.Setup();
}
public static void ClearVisualTestResultFolder()
{
// Logic to clear folder
}
}
If I put the ClearVisualTestResultFolder in the constructor, it is also being called once for every test method. I need this just run once before all test methods are executed, how can I achieve this?
If it matters, I use the ReSharper test runner.
Following the guidance in this xUnit discussion topic, it looks like you need to implement a constructor on the Fixture and also implement IDisposable. Here's a complete sample that behaves the way you want:
using System;
using System.Diagnostics;
using Xunit;
using Xunit.Sdk;
namespace xUnitSample
{
public class SomeFixture : IDisposable
{
public SomeFixture()
{
Console.WriteLine("SomeFixture ctor: This should only be run once");
}
public void SomeMethod()
{
Console.WriteLine("SomeFixture::SomeMethod()");
}
public void Dispose()
{
Console.WriteLine("SomeFixture: Disposing SomeFixture");
}
}
public class TestSample : IUseFixture<SomeFixture>, IDisposable
{
public void SetFixture(SomeFixture data)
{
Console.WriteLine("TestSample::SetFixture(): Calling SomeMethod");
data.SomeMethod();
}
public TestSample()
{
Console.WriteLine("This should be run once before every test " + DateTime.Now.Ticks);
}
[Fact]
public void Test1()
{
Console.WriteLine("This is test one.");
}
[Fact]
public void Test2()
{
Console.WriteLine("This is test two.");
}
public void Dispose()
{
Console.WriteLine("Disposing");
}
}
}
When running this from the console runner, you'll see the following output:
D:\xUnit>xunit.console.clr4.exe test.dll /html foo.htm xUnit.net
console test runner (64-bit .NET 4.0.30319.17929) Copyright (C)
2007-11 Microsoft Corporation.
xunit.dll: Version 1.9.1.1600 Test assembly: test.dll
SomeFixture ctor: This should only be run once
Tests complete: 2 of 2
SomeFixture: Disposing SomeFixture
2 total, 0 failed, 0 skipped, took 0.686 seconds
Then, when you crack open the test output file foo.htm, you'll see the other test output.
The old IUseFixture<T> interface in xUnit.net v1.x has been replaced
by two new interfaces: IClassFixture<T> and ICollectionFixture<T>. In
addition, the mechanism for injecting fixture values into your tests
has changed from property setters to constructor arguments. Class
fixtures are created once and shared amongst all tests in the same
class (much like the old IUseFixture). Collection fixtures work the
same way, except that the single instance is shared amongst all tests
in the same test collection.
NOTE this applies only to xUnit.net v1 - see the accepted answer unless that's your case
IUseFixture<T>.SetFixture gets called once for each test. The Fixture itself is only created once.
In other words, you shouldnt be doing anything in your SetFixture method, but you should be instead be triggering it in the Fixture constructor.
For one-time cleanup, implement an IDisposable.Dispose on the Fixture (it's not required though)
Note that it's a bad idea to be (even potentially) sharing state between tests. Best to use a TemporaryDirectoryFixture like this one.
I added these method in a TestBase class :
[ClassInitialize]
public static void InitializBeforeAllTests()
{
}
But when I run in Debug an unit test Test1() :
[TestClass]
public class TestMapping : TestBase
{
[TestMethod]
public void Test1()
{
}
The TestBase.InitializBeforeAllTests() method is never called.
Why?
When declaring ClassInitialize attribute on a method, the method has to be static, public, void and should take a single parameter of type TestContext.
If you're having also other method with the AssemblyInitialize attribute on the same unit test, the test will run but will skip on all test methods and will go directly to AssemblyCleanup or just quit.
Try the example on ClassInitialize attribute in MSDN.
You can setup an assembly initialize method in your base class. Not quite the same as ClassInitialize, but it's a viable option. Source:The Workaround mentioned here.
[TestClass]
public abstract class TestBase
{
[AssemblyInitializeAttribute]
public static void Initialize(TestContext context)
{
// put your initialize code here
}
}
You can also add a Cleanup method:
[AssemblyCleanup]
public static void Cleanup()
{
//clean up stuff here
}
for whatever reason, the unit test framework's UnitTestExecuter only allows one ClassInitialize and one ClassCleanup method to be defined per test class... unlike TestInitialize and TestCleanup methods, which get called in both the derived and base test class...
i know this is a very old question, but its the first to popup in google search when looking for a similar problem, anyhow, here is an update for the answer:
[ClassInitialize(InheritanceBehavior.BeforeEachDerivedClass)]
public static void YOUR_INIT_METHOD_NAME(TestContext context)
Note: you need MSTest.TestFramework-Version 2.0.0 package or newer for this to work.
The MS link is not working anymore.
Anyway, one way to work around this issue is to simply move your initialization code into the constructor of the base class. This will ensure that it gets called from any descendant classes whenever they are instantiated.
[TestClass]
public class TestBase
{
public TestBase()
{
// Initialization Code
}
}
[TestClass]
public class TestMapping : TestBase
{
[TestMethod]
public void Test1()
{
// At this point the base constructor should have been called
}
}
In my case, I had the[Ignore] attribute applied (test is ran manually)
This caused [AssemblyInitialize] to never be called
If I removed the [Ignore] attribute [AssemblyInitialize] was called as expected.
Oddly, [AssemblyCleanup] is still called with or without the [Ignore] applied to my test