Is it possible to skip the AssemblyInitialize attribute for special tests? - c#

I have two tests: BooUnitTest and BooIntegrationTest.
Within the same testing project I'm holding a method with the AssemblyInitialize attribute decorator:
AssemblyTestsHandler.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class AssemblyTestsHandler
{
[AssemblyInitialize]
public static async Task Bootstrap()
{
//Do complex stuff...
}
}
Is it possible to make the Bootstrap method that works only for BooIntegrationTest and not for FooUnitTest?
For example
FooTests.cs:
[TestClass]
public class FooTests
{
[TestMethod]
public async Task FooUnitTest()
{
//Skip Bootstrap()!!
}
}
BooTests.cs
[TestClass]
public class BooTests
{
[TestMethod]
public async Task BooIntegrationTest()
{
//Do Not Skip Bootstrap()!!
}
}
Here is the project structure:
TestingProject
-AssemblyTestsHandler.cs
-BooTests.cs
-FooTests.cs

No, you can't. AssemblyInitialize will be called once per assembly and it will be called before all other methods (AssemblyInitializeAttribute Class):
The method marked with this attribute will be run before methods
marked with the ClassInitializeAttribute, TestInitializeAttribute, and
TestMethodAttribute attributes. Only one method in an assembly may be
decorated with this attribute.
Actually unit tests should be executed in random order:
FooUnitTest1
BooIntegrationTest2
FooUnitTest2
BooIntegrationTest1
in this case any static initialization will affect all other unit-tests.
I think, there are two possibilities:
You can use TestInitialize and TestCleanup attributes for FooTests. But this will affect performance
You can use ClassInitialize for BooTests, but in this case, you have to trigger integration tests separately from unit tests. Integration- and unit tests can be distinguished by TestCathegory attribute.

Related

Init mock database before all tests

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

Can I perform action before/after all tests

I know, that in Coded UI there are two methods (MyTestInitialize and MyTestCleanup) which can perform action before and after each tests. I need add some action which launch before and after all tests. For example, if you familiar with rspec there are two methods before() and after(), which take parameter :each (will call before/after each tests) or :all (will call before/after all test).
Create your methods with the [ClassInitialize] and [ClassCleanup] attributes as necessary. This should be within your Test Class. Example:
[CodedUITest]
public class MyTestClass
{
[ClassInitialize]
public void DoSomethingFirst()
{
// your code here that will run at the beginning of each test run.
}
[TestInitialize]
public void RunBeforeEachTest()
{
// your test initialization here
}
[TestMethod]
public void MyTestMethod()
{
}
}
And you would do the same for your [TestCleanup] and [ClassCleanup].
More on this attribute can be found here.

How tear down integration tests

I want to do some integration tests on my project. Now I am looking for a mechanism that allow me execute some code before all tests begin and execute some code after all tests ends.
Note that I can have set up methods and tear down method for each tests but I need the same functionality for all tests as a whole.
Note that I using Visual Studio, C# and NUnit.
Annotate your test class with the NUnit.Framework.TestFixture attribute, and annotate you all tests setup and all tests teardown methods with NUnit.Framework.TestFixtureSetUp and NUnit.Framework.TestFixtureTearDown.
These attributes function like SetUp and TearDown but only run their methods once per fixture rather than before and after every test.
EDIT in response to comments:
In order to have a method run after ALL tests have finished, consider the following (not the cleanest but I'm not sure of a better way to do it):
internal static class ListOfIntegrationTests {
// finds all integration tests
public static readonly IList<Type> IntegrationTestTypes = typeof(MyBaseIntegrationTest).Assembly
.GetTypes()
.Where(t => !t.IsAbstract && t.IsSubclassOf(typeof(MyBaseIntegrationTest)))
.ToList()
.AsReadOnly();
// keeps all tests that haven't run yet
public static readonly IList<Type> TestsThatHaventRunYet = IntegrationTestTypes.ToList();
}
// all relevant tests extend this class
[TestFixture]
public abstract class MyBaseIntegrationTest {
[TestFixtureSetUp]
public void TestFixtureSetUp() { }
[TestFixtureTearDown]
public void TestFixtureTearDown() {
ListOfIntegrationTests.TestsThatHaventRunYet.Remove(this.GetType());
if (ListOfIntegrationTests.TestsThatHaventRunYet.Count == 0) {
// do your cleanup logic here
}
}
}

How to run setup code only once in an xUnit.net test

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.

ClassInitialize attribute in unit test based class not called

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

Categories

Resources