VS2015: TraceSource Output in Test Explorer? - unit-testing

I've got a library that I'm trying to unit test. I use TraceSource to write out warning details, and as I have the unit tests set to run as part of the build, I'd like them to show up when the tests are run - particularly on failure.
I've tried the following code to register a trace listener, but my WriteLine stuff never gets called, despite the constructor being called. See code at the bottom [1].
How do I get my traces to show up as part of the test runner?
[1] Code for my testcontexttracelistener:
[TestClass]
public class TestContextTraceListener : TraceListener
{
TestContext testContext;
public TestContextTraceListener(TestContext testContext)
{
this.testContext = testContext;
}
public override void Write(string message)
{
// EP TODO: This is likely going to create newlines where they shouldn't be, but testContext doesn't have a .Write, and I'm too lazy to buffer.
this.WriteLine(message);
}
public override void WriteLine(string message)
{
this.testContext.WriteLine(message);
}
}
[TestClass]
public class TestAssemblyInitializeAndCleanup
{
static TraceListener traceListener;
[AssemblyInitialize]
public static void OnInitialize(TestContext testContext)
{
if (traceListener == null)
{
// This code is reached, but the listener never gets triggered.
traceListener = new TestContextTraceListener(testContext);
Trace.Listeners.Add(traceListener);
}
}
[AssemblyCleanup]
public static void OnCleanup()
{
Cleanup();
}
static void Cleanup()
{
if (traceListener != null)
{
traceListener.Flush();
Trace.Listeners.Remove(traceListener);
traceListener.Dispose();
}
}
}

Related

Mstest [ClassCleanup] not executed at all in VS 2019

[ClassInitialize]
public static void BeforeCls(TestContext tc)
{
Console.WriteLine("ClassInitialize - Before Class");
}
[ClassCleanup]
public static void AfterCls()
{
Console.WriteLine("ClassCleanup - After Class");
}
[TestInitialize]
public void BeforeMethod()
{
Console.WriteLine("TestInitialize - Before Method");
}
[TestCleanup]
public void AfterMethod()
{
Console.WriteLine("TestCleanup - After Method");
}
[TestMethod]
public void TestMethod1()
{
Console.WriteLine("Test Method - 1");
}
Class cleanup is never executed in this code.
here is the Output
ClassInitialize - Before Class
TestInitialize - Before Method
Test Method - 1
TestCleanup - After Method
Invested a bit more time and discovered that using this will work within a test class:
[ClassCleanup(InheritanceBehavior.None))]
public static void ClassCleanup()
{
// Your code goes here
}
And using that will work for a derived test class:
[ClassCleanup(InheritanceBehavior.BeforeEachDerivedClass)]
public static void ClassCleanup()
{
// Your code goes here
}
You can read more about it here.
If the solution is not working for you no matter what, you can define IDisposable. The code will look something like this:
[TestClass]
public class DisposableBaseTest : IDisposable
{
// Your initialize methods
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~DisposableUserBaseTest()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Your cleanup code
Console.WriteLine("ClassCleanup - After Class");
}
}
}
P.S. And according to carlin.scott from this post, if you receive an exception during ClassInitialize, you want to handle this separately.
ClassCleanup is executed - put a breakpoint inside your method and verify it yourself. Problem is, that this method is executed after all of your tests are completed, so you cannot write message from that method in test output report. This is similar to ClassInitialize method. If you have multiple tests in your file, your ClassInitialize will write a message to only one of them.

Mockito Mock log4j appender is not invoked while running unit test

I am trying to unit test the log statements generated in my code. I am using slfj, log4j and Mockito. I am using the similar code as below from the blog at
http://bloodredsun.com/2010/12/09/checking-logging-in-unit-tests/
When I run the test it throws exception saying that there are 0 invocations at line:
verify(mockAppender).doAppend(captorLoggingEvent.capture());
Error Message:
Wanted but not invoked: mockAppender.doAppend();
-> at testClass.testLogAdviceAfterReturning(DpsOpsLoggerTest2.java:94) Actually, there were zero interactions with this mock.
I see the logs printed on the console though. Request you to kindly help.
#RunWith(MockitoJUnitRunner.class)
public class ExampleThatLogsTest {
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor captorLoggingEvent;
#Before
public void setup() {
LogManager.getRootLogger().addAppender(mockAppender);
}
#After
public void teardown() {
LogManager.getRootLogger().removeAppender(mockAppender);
}
#Test
public void shouldConcatAndLog() {
//given
ExampleThatLogs example = new ExampleThatLogs();
//when
String result = example.concat("foo", "bar");
//then
assertEquals("foobar", result);
verify(mockAppender).doAppend(captorLoggingEvent.capture());
LoggingEvent loggingEvent = captorLoggingEvent.getValue();
//Check log level
assertThat(loggingEvent.getLevel(), is(Level.INFO));
//Check the message being logged
assertThat(loggingEvent.getRenderedMessage(),
is("String a:foo, String b:bar"));
}
}
I tried to emulate your case ,At my end it is working fine
//Log Util
public class LogUtil{
final static Logger logger = Logger.getLogger(LogUtil.class);
public static Log`enter code here`ger getLogger()
{
return logger;
}
//class
public class RunMe {
public String runMe(String parameter) {
LogUtil.getLogger().info("This is info : " + parameter);
return "In runner " + parameter;
}
}
// Unit Test
#RunWith(MockitoJUnitRunner.class)
public class LoggerTest {
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor captorLoggingEvent;
#Before
public void setup() {
LogUtil.getLogger().addAppender(mockAppender);
}
#Test
public void shouldConcatAndLog() {
RunMe runner=new RunMe();
String result=runner.runMe("XYZ");
assertEquals("In runner XYZ",result);
verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture());
LoggingEvent logevent= (LoggingEvent) captorLoggingEvent.getValue();
assertThat(logevent.getLevel(), is(Level.INFO));
}
#After
public void tearDown() {
LogUtil.getLogger().removeAllAppenders();
}
}
I know this is a little bit outdated, but I was struggling with this too. I was logging statements at DEBUG level in the class under test. My configuration in logback.xml for the class under test was set to INFO. Changing my logging statement to INFO allowed the test to pass. In addition, I also read this Github post that is really concise and a clean implementation of testing log output. Hope others will find it useful.

ClassCleanup Method Runs Too Late (or After All ClassInitialize methods)

When running multiple [TestClass]es at the same time, why do the [ClassCleanup()] methods only get called at the very end?
File: UnitTest1.cs
[TestClass]
public class UnitTest1
{
[ClassInitialize()]
public static void ClassInit(TestContext context)
{
}
[ClassCleanup()]
public static void ClassCleanup()
{
}
[TestMethod]
public void TestMethod1()
{
}
}
File: UnitTest2.cs
[TestClass]
public class UnitTest2
{
[ClassInitialize()]
public static void ClassInit(TestContext context)
{
}
[ClassCleanup()]
public static void ClassCleanup()
{
}
[TestMethod]
public void TestMethod1()
{
}
}
The execution order is the following:
UnitTest2.ClassInit()
UnitTest2.TestMethod1()
UnitTest1.ClassInit()
UnitTest1.TestMethod1()
UnitTest2.ClassCleanup()
UnitTest1.ClassCleanup()
Notice that both [ClassCleanup] methods are executed at the end of the set; not after each TestClass is "done".
But I expected a different behavior:
UnitTest2.ClassInit()
UnitTest2.TestMethod1()
UnitTest2.ClassCleanup() - Expected
UnitTest1.ClassInit()
UnitTest1.TestMethod1()
UnitTest1.ClassCleanup() - Expected
Microsoft's Documentation - ClassCleanupAttribute Class says, "Identifies a method that contains code to be used after all the tests in the test class have run and to free resources obtained by the test class. "
But it appears to be run/executed late!
How do I fix this? Or find a way to execute a method from the same TestClass right before the next ClassInitialize method.

Gallio unit test startup code

This is going to be an amateur level question. Is there a way to add start up code to a test project that uses MBUnit 3.4.0.0? I tried adding [TestFixture] and [FixtureSetUp] attributes to code that I wanted to run first, but unfortunately that didnt help.
The [FixtureSetUp] should be executed once before any test of the tests contained within the [TestFixture], but the two cannot be used interchangeably.
Here's a quick example. Admittedly the class doesn't have to be decorated with the [TestFixture] attribute, but it's good practice.
[TestFixture]
public class SimpelTest
{
private string value = "1";
[FixtureSetUp]
public void FixtureSetUp()
{
// Will run once before any test case is executed.
value = "2";
}
[SetUp]
public void SetUp()
{
// Will run before each test
}
[Test]
public void Test()
{
// Test code here
Assert.AreEqual("2", value);
}
[TearDown]
public void TearDown()
{
// Will run after the execution of each test
}
[FixtureTearDown]
public void FixtureTearDown()
{
// Will run once after every test has been executed
}
}

NUnit Conditional Teardown?

Is there a way to do a conditional TearDown in NUnit?
I have a TestFixture which has a need to run cleanup code for just a few tests, and I don't really want to:
Run the TearDown method on every test
Create a private helper method and call it from the tests requiring cleanup if I can avoid it
There isn't unfortunately.
Can you not do the cleanup in the [TestFixtureTearDown] instead, so once all the tests have finished? I guess that depends on whether the cleanup has to be done before the next test runs.
Alternatively, put those tests that require a cleanup in another class/TextFixture together, away from the other tests. Then you can use a TearDown in there which doesn't need to be conditional.
Edit:
One thing I've just thought of, which could be done to achieve the aim though probably isn't actually worth it for this particular need, is that you can extend NUnit - create your own custom attributes which you could handle however you wanted. This is mentioned here. Like I say, I don't think really you should go down that route for this, but is useful to know none-the-less
You can have the main TearDown in a base class:
[TearDown]
public virtual void TearDown()
{
// Tear down things here
}
and then override it in the class where you have the tests that should not run the tear down code:
[TearDown]
public override void TearDown()
{
// By not calling base.TearDown() here you avoid tearing down
}
Extend all you classes with test from BaseTest
public class BaseTest
{
[SetUp]
public void BeforeTest()
{
GetService<NUnitHooksController>().ExecuteBeforeTestHooks(this);
}
[TearDown]
public void AfterTest()
{
GetService<NUnitHooksController>().ExecuteAfterTestHooks(this);
}
}
Use AfterTest and BeforeTest hooks. Works both with and without category.
public class ExampleTest : BaseTest
{
[Test, Category("asdasd")]
public void Test01()
{
...
}
[AfterTest("asdasd")]
public void ExampleHook()
{
...
}
}
public class NUnitHooksController
{
private readonly ILogger _log;
public NUnitHooksController(ILogger log)
{
_log = log;
}
public void ExecuteBeforeTestHooks(object testClass)
{
ExecuteHooks(testClass, typeof(BeforeTestAttribute));
}
public void ExecuteAfterTestHooks(object testClass)
{
ExecuteHooks(testClass, typeof(AfterTestAttribute));
}
private MethodInfo[] GetHookMethods(object currentTestClass, Type attributeType)
{
return currentTestClass
.GetType()
.GetMethods()
.Where(m => m.GetCustomAttributes(attributeType, false).Length > 0)
.ToArray();
}
private void ExecuteHooks(object testClass, Type requiredAttributeType)
{
var hooks = GetHookMethods(testClass, requiredAttributeType);
var testCategories = GetTestCategories();
foreach (var hook in hooks)
{
var allAttributes = hook.GetCustomAttributes(requiredAttributeType, true);
foreach (var attribute in allAttributes)
{
if (!attribute.GetType().IsEquivalentTo(requiredAttributeType))
{
continue;
}
var hookCategories = GetCategoriesFromAttribute(attribute);
// if we do not have specific category on hook
// or we have at least one same category on hook and test
if (!hookCategories.Any() || hookCategories.Intersect(testCategories).Any())
{
ExecuteHookMethod(testClass, hook);
}
}
}
}
private object[] GetTestCategories()
{
return TestContext.CurrentContext.Test.Properties["Category"].ToArray();
}
private void ExecuteHookMethod(object testClass, MethodInfo method)
{
var hookName = method.Name;
_log.Information($"Executing - '{hookName}' hook");
try
{
method.Invoke(testClass, Array.Empty<object>());
}
catch (Exception e)
{
_log.Error($"Executing of - '{hookName}' hook failed - {e}");
}
}
private string[] GetCategoriesFromAttribute(object attribute)
{
if (attribute is BeforeTestAttribute beforeTestAttribute)
{
return beforeTestAttribute.Categories;
}
if (attribute is AfterTestAttribute afterTestAttribute)
{
return afterTestAttribute.Categories;
}
throw new ArgumentException($"{attribute.GetType().FullName} - does not have categories");
}
}
I have solved this using the name of the test:
namespace TestProject
{
public class TestClass
{
// Test without TearDown
[Test]
public void Test1()
{
Assert.Pass("Test1 passed");
}
// Test with TearDown
[Test]
public void Test2()
{
Assert.Pass("Test2 passed");
}
[TearDown]
public void TearDown()
{
// Execute only after Test2
if (TestContext.CurrentContext.Test.Name.Equals(nameof(this.Test2)))
{
// Execute Test2 TearDown...
}
}
}
}
Or if you want to use the full name of Test2 (TestProject.TestClass.Test2) you can replace the line
if (TestContext.CurrentContext.Test.Name.Equals(nameof(this.Test2)))
by
if (TestContext.CurrentContext.Test.FullName.Equals(typeof(TestClass).FullName + "." nameof(this.Test2)))