Initialize log4Net as early as possible with NUnit - c#

I'm wondering what is the best way to initialize log4Net in a NUnit project. Of course I want to call the init code (ie. XmlConfigurator.Configure()) as soon as I can to get as many early log output as I can. But since my project is run through NUnit, I have little control on its entry point.
According to NUnit documentation, it should call some constructors first, then a method marked with the [SetUp] attribute in a class marked with [TestFixtureSetup].
So, First, I created a static helper class which I can call several times without trouble.
public static class LoggingFacility
{
private static bool _loggerIsUp = false;
public static void InitLogger()
{
if (_loggerIsUp == false)
XmlConfigurator.ConfigureAndWatch(f);
_loggerIsUp = true;
}
}
Then, I made all my [TestFixtureSetup] inherit a single one that does pretty much nothing else than calling LoggingFacility.initLogger(). But that still leaves all constructors that are run earlier, in an order I can only assume random. And moreover, it will probably do some static initializations before I am even able to execute some code.
In fact, as I can see in my log, the first 4 seconds or so of execution are completely unrecorded.
Does it mean I will have to call my InitLogger() in every constructor and forbid the use of any static initializer? That's tough job!
Does somebody know a magic trick with this?

For single initialization point you should use class marked with [SetUpFixture] attribute and method marked with [SetUp], for example:
[SetUpFixture]
public class TestsInitializer
{
[SetUp]
public void InitializeLogger()
{
LoggingFacility.InitLogger();
}
}
Now, this method ([SetUp] InitializeLogger) will run before any test is run, same as one marked with [TearDown] will run once all tests are run. But here's the catch - what does any and all mean in this context? Tests from classes declared in the same namespace as class marked with [SetUpFixture].
For example, assuming hierarchy like this:
- Tests
--- Business
----- TestsInitializer.cs // SetUpFixture class
----- FirstBusinessTests.cs
----- SecondBusinesTests.cs
--- ComplexLogic
----- VeryComplexLogicTests.cs
First and SecondBusinessTests will run after SetUp from TestsInitializer, however VeryComplexLogicTests might run in random order.
According to linked documentation, if you declare SetUpFixture class outside of any namespace, setup and teardown will apply for entire assembly:
Only one SetUpFixture should be created in a given namespace. A SetUpFixture outside of any namespace provides SetUp and TearDown for the entire assembly.

A work mate provided me with the following workaround, that does the job:
In all my classes that require logging, I had the following logger initialization
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
I simply changed it to a singleton initializer
private static readonly ILog Log = LoggingFacility.GetLoggerWithInit(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/*** ... ***/
public static class LoggingFacility
{
private static bool _loggerIsUp = false;
public static ILog GetLoggerWithInit(Type declaringType)
{
if (_loggerIsUp == false)
XmlConfigurator.Configure(_log4NetCfgFile);
_loggerIsUp = true;
return LogManager.GetLogger(declaringType);
}
}
Because I have this code in every class, this static initializer has to be called very early by NUnit wile instantiating my test classes.
Next step is to make that thread safe :(

Related

C# How to hit a method in debug

Probably not a good title, and this question might be stupid, but I really have no idea how to do this.
I've created a project that connects to a DB with EF Core . I've created my DbContext class and my Repository class that does the actual querying .
Then I created another class , maybe I created it wrong, but I made it similar to a controller of an MVC project . This is my class:
public class ExtractCustomersToBeMarked
{
private ICampaignRepository _repository;
private ILogger<ExtractCustomersToBeMarked> _logger;
public ExtractCustomersToBeMarked(ILogger<ExtractCustomersToBeMarked> logger, ICampaignRepository repository)
{
_repository = repository;
_logger = logger;
}
public async Task ExtractCustomers()
{
IEnumerable<CampaignKnownCustomers> result = _repository.getCustomersGUID();
... I want to debug this code
}
}
Now I want to debug my program . I tried calling the method from my Main program , but with no success as I don't know what to pass to the constructor (MVC does that on its own) . That's what I tried :
public static void Main(string[] args)
{
var p = new Program();
p.Run().Wait();
}
private async Task Run()
{
ExtractCustomersToBeMarked ectm = new ExtractCustomersToBeMarked(?,?);
await ExtractCustomersToBeMarked.ExtractCustomers();
}
I know it doesn't look good, this structure is simply for debugging . If theres another way I'm open to hear about it..
How can I hit the debugger on ExtractCustomers?
I guess you have implemented a CampaignRepository class. Provided that you want to use this implementation when debugging the ExtractCustomers() method, you should simply create an instance of it and pass to the method:
static void Main(string[] args)
{
ExtractCustomersToBeMarked ectm = new ExtractCustomersToBeMarked(null, new CampaignRepository());
ectm.ExtractCustomers().Wait();
}
The same goes for the logger. Create an instance of a class that implements the ILogger<ExtractCustomersToBeMarked> if you use the logger in the method that you want to debug. Don't forget to pass it to the constructor of the ExtractCustomersToBeMarked class when you create an instance of it.
You may want to implement an integration test instead of modifying the Main() method of the application itself though but that's another story.
Summary I'd suggest writing Unit Tests against the code you want to debug.
Detail When you have Unit Tests in place you can run each individual test under Debug, allowing you to step through the code exactly like you do when debugging the application; but with the benefit that you get to define the scope and context of the test, for example you can test isolated parts of your system independently of others.
Once a test is in place, it can shorten the time taken by the code+debug iteration cycle, making you more productive. It achieves that because the test fires you straight into the relevant code with the test scenario already set up, rather than the whole application having to start up, and you navigating through to the relevant parts each time to get into the scenario you want.
Another benefit of these tests (if they are written the right way) is that you can make them run as part of an automated build which is triggered whenever someone changes some code. This means that if anyone breaks that code, the test will fail, and the build will fail.

How to perform global setup/teardown in xUnit and run tests in parallel?

Here is what I want to achieve with xUnit:
Run initialization code.
Run tests in parallel.
Perform teardown.
I have tried [CollectionDefinition]/[Collection]/ICollectionFixture
approach described here but it has disabled the parallel execution, which is critical for me.
Are there any way to run tests in parallel and be able to write global setup/tear-down code in xUnit?
If it is not possible with xUnit, does NUnit or MSUnit support this scenario?
NUnit supports this scenario. For global setup, create a class in one of your root namespaces and add the [SetupFixture] attribute to it. Then add a [OneTimeSetUp] method to that class. This method will get run once for all tests in that namespace and in child namespaces. This allows you to have additional namespace specific onetime setups.
[SetUpFixture]
public class MySetUpClass
{
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
// ...
}
[OneTimeTearDown]
public void RunAfterAnyTests()
{
// ...
}
}
Then to run your tests in parallel, add the [Parallelizable] attribute at the assembly level with the ParallelScope.All. If you have tests that should not be run in parallel with others, you can use the NonParallelizable attribute at lower levels.
[assembly: Parallelizable(ParallelScope.All)]
Running test methods in parallel in NUnit is supported in NUnit 3.7 and later. Prior to that, it only supported running test classes in parallel. I would recommend starting any project with the most recent version of NUnit to take advantages of bug fixes, new features and improvements.
A somewhat basic solution would be static class with a static constructor and subscribing to the AppDomain.CurrentDomain.ProcessExit event.
public static class StaticFixture
{
static StaticFixture()
{
AppDomain.CurrentDomain.ProcessExit += (o, e) => Dispose();
// Initialization code here
}
private static void Dispose()
{
// Teardown code here
}
}
There's no guarantee when the static constructor gets called though, other than at or before first use.

Load testing Visual Studio, start up script / setup

I was wondering if it was possible to have a start-up script before running any load tests? For example, perhaps to seed some data or clear anything down prior to the tests executing.
In my instance I have a mixed bag of designer and coded tests. Put it simply, I have:
Two coded tests
A designer created web test which points to these coded tests
A load test which runs the designer
I have tried adding a class and decorating with the attributes [TestInitialize()], [ClassInitialize()] but this code doesn't seem to get run.
Some basic code to show this in practice (see below). Is there a way of doing this whereby I can have something run only the once before test run?
[TestClass]
public class Setup : WebTest
{
[TestInitialize()]
public static void Hello()
{
// Run some code
}
public override IEnumerator<WebTestRequest> GetRequestEnumerator()
{
return null;
}
}
Probably should also mention that on my coded tests I have added these attributes and they get ignored. I have come across a workaround which is to create a Plugin.
EDIT
Having done a little more browsing around I found this article on SO which shows how to implement a LoadTestPlugin.
Visual Studio provides a way of running a script before and also after a test run. They are intended for use in deploying data for a test and cleaning up after a test. The scripts are specified on the "Setup and cleanup" page in the ".testsettings" file.
A load test plugin can contain code to run before and after any test cases are executed, also at various stages during test execution. The interface is that events are raised at various points during the execution of a load test. User code can be called when these events occur. The LoadTestStarting event is raised before any test cases run. See here for more info.
If you are willing to use NUnit you have SetUp/TearDown for a per test scope and TestFixtureSetUp/TestFixtureTearDown to do something similar for a class (TestFixture)
Maybe a bit of a hack, but you can place your code inside the static constructor of your test class as it will automatically run exactly once before the first instance is created or any static members are referenced:
[TestClass]
public class Setup : WebTest
{
static Setup()
{
// prepare data for test
}
public override IEnumerator<WebTestRequest> GetRequestEnumerator()
{
return null;
}
}

How can I isolate unit tests by class?

I have a number of 'unit tests' (they're really integration tests) in several classes that access a shared resource, and I want each test class to only acquire the resource once (for performance reasons).
However, I'm getting issues when I release the resource in [ClassCleanup], because that isn't running until all tests are completed.
Here's a simplified example:
using Microsoft.VisualStudio.TestTools.UnitTesting;
static class State
{
public static string Thing;
}
[TestClass]
public class ClassA
{
[ClassInitialize]
public static void Initialize(TestContext ctx)
{
State.Thing = "Hello, World!";
}
[ClassCleanup]
public static void Cleanup()
{
State.Thing = null;
}
[TestMethod]
public void TestA()
{
Assert.IsNotNull(State.Thing); // Verify we have a good state
}
}
[TestClass]
public class ClassB
{
[TestMethod]
public void TestB()
{
Assert.IsNull(State.Thing); // Verify we have an uninitialized state
// Initialize state, do stuff with it
}
}
On my machine at least, TestB fails because it runs before ClassA has been cleaned up.
I read ClassCleanup May Run Later Than You Think, but that doesn't explain any way to change the behaviour. And I realize I shouldn't depend on test ordering, but it's too expensive to re-acquire the resource for every test, so I want to group them by class.
How can I fix this? Is there a way to force each test class to run as a unit, and make the cleanup occur immediately?
Although ClassCleanup might be unreliable in terms of when it is run, ClassInitialize is not; why not give each testclass that relies on this shared resource a ClassInitialize that cleans up the shared resource of the previous test class (if any), right before acquiring the resource itself?
The only time the shared resource isn't released is for the last test class, but you could handle that with the ClassCleanup because then it doesn't matter anymore when it is run (since there won't be any more test classes following it).
Is there any reason that you cannot make this resource shared by the entire assembly all at once? Make it an internal or public static variable in one of the test classes (or a separate designated class), and refer to it directly from all the test classes. The initialization of the resource will take place in the [AssemblyInitialize] method and the cleanup will take place at the [AssemblyCleanup].

What is the scope of a test class when running unit tests?

When Visual Studio is running unit tests, it runs many tests simultaneously. What exactly is the scope of the test class while these are running. Are they all run in separate app domains or is data shared at all?
For instance if I have the following test class:
[TestClass]
public class FooTests
{
Mock<ISomeInterface1> _complexMock1;
Mock<ISomeInterface2> _complexMock2;
public void CreateComplexMocks()
{
//set up _complexMock1 & _complexMock2
}
[TestMethod]
public void Test1()
{
CreateComplexMocks();
//use _complexMock1 & _complexMock2 in test
}
[TestMethod]
public void Test2()
{
CreateComplexMocks();
//use _complexMock1 & _complexMock2 in test
}
}
The tests utilise the CreateComplexMocks() helper to construct some mocks. These are exposed as members rather than being passed back to the test (there would probably be many more in a real world example)
My question is, if both tests run at the same time, will they be sharing the state of _complexMock1 and _complexMock2?
What if the complexMocks were static?
Having found this blog, it would appear that a separate test class is instantiated for every test, on a different thread.
So instance members will not be shared, but static members will.
In your example you should create your mocks in the [TestInitialize] method.
By this every time a test would run your mocks would be created again.
[TestInitialize]
public void TestInit()
{
CreateComplexMocks();
}

Categories