Nunit - TestContext.CurrentContext.Test not working - c#

I am using nunit 2.5.9.10348 and trying to extract the current test name in the TearDown event so I can assign a screengrab filename the test name however it is always null (see the attached image). The private _context variable does have the TestName however this is no use to me!
Has anyone had success using this new TestContext functionality (from 2.5.7).

From your screenshot I see that _context has keys "TestName" and "Properties". But TestAdapter looks for keys "Test.Name" for Name and "Test.Properties" for Properties. So, there is something wrong with TestContext initialization (I think wrong data was put to Remoting.Messaging.CallContext).
After a little investigation (see comments):
NUnit tests should run by NUnit testig environment for Context to be available.

I had the same issue. It occurred when in a TearDown method I executed method, which actually was to make the teardown
[TearDown]
public void CleanUp()
{
TestContext.CurrentContext.Test.FullName; //!=null
someClassInstance.DoTearDown();
}
class SomeClass
{
public void DoTearDown()
{
TestContext.CurrentContext.Test.FullName; //==null
}
}
I have no idea why, but it seemed so. Is it your case?
UPDATE: Now I looked at the screenshot, so it's not your case :)

Same issue with R# test runner. Just downloaded NUnit sources and added a workaround in TestAdapter to make it work with r#
public string Name
{
get
{
return (_context["Test.Name"] ?? _context["TestName"]) as string;
}
}

Related

.NET Problem removing TestContext from Unit tests

I have a c# unit test project (.NET 4.8).
My unit test are using a .testsetting file that I want to remove.
In my unit test I use TestContext too:
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
LoadSettings(testContext.DeploymentDirectory);
}
First I removed the .testsettings file, then I modified the unit test removing the TestContext:
[ClassInitialize]
public static void MyClassInitialize()
{
LoadSettings(Directory.GetCurrentDirectory());
}
My problem is when I run the unit test I got this error:
MyClassInitialize has wrong signature. The method must be static,
public, does not return a value and should take a single parameter of
type TestContext.
Looking at this issue, I changed the version of "Microsoft.VisualStudio.QualityTools.UnittestFramework" from 10.0.0.0 to 10.1.0.0 with no success.
Before run the tests I unchecked the .testsettings from "Test" menu and then I deleted it.
Currently use Visual Studio 2019 version 16.3.2.
I still got the same error. Do I need to reference another dll or another version? Do I need to install something?
UPDATE:
Here how I added the reference:
Here the row added by Visual Studio in the .csproj file:
Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework,Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,processorArchitecture=MSIL"
And It is how look the reference properties in Visual Studio:
I still got the error, but the strange thing is If I restart Visual Studio in the reference property I continue to see the old version (10.0.0.0)!!!
I tried also with Visual Studio 2017 version 15.9.16. Same result!
As the error message says, a method decorated with the ClassInitializeAttribute must take a TestContext parameter.
You can just ignore it if you don't ever indend to use a .testsettings file, but you cannot remove the parameter.

How to use ITestEventListener in NUnit 3?

I want to add a custom test reporter to NUnit. I already did it with NUnit2, but I now need to use NUnit3.
To implement the reporter, I need to get various events from the framework, like start, end and failure of tests.
In NUnit2 I used NUnitHook to register my EventListener and it worked pretty good.
In NUnit3 I need to use the extension point mechanism, but when I add the extension point to the project, VisualStudio (2012 ultimate) immediately fails to discover the NUnit tests.
[TypeExtensionPoint(Description = "Test Reporter Extension")]
public class MyTestEventListener : ITestEventListener
{
public void OnTestEvent(string report)
{
Console.WriteLine(report);
}
}
If I remove the ITestEventListener implementation declaration from the class, it rediscovers the tests perfectly.
[TypeExtensionPoint(Description = "Test Reporter Extension")]
public class MyTestEventListener //: ITestEventListener
{
public void OnTestEvent(string report)
{
Console.WriteLine(report);
}
}
Am I doing something wrong? is there a better way to achieve it?
You don't say where you are putting this code, but I am suspecting it's in your test assembly. If so, that's not where it belongs. NUnit engine extensions get installed into the NUnit engine, so they need to be in a separate assembly. Once you have a separate assembly, you need to tell the engine where it is. Currently, you do this by creating a file of type .addins in the same directory as the engine. (You could modify the existing file, but that introduces maintenance problems in the future)
A future release will have an easier way to install addins, but they will continue to be entirely separate from your tests.
A further problem is that you are using TypeExtensionPointAttribute. I didn't notice this originally in your code and it's probably the biggest error so I'm adding this info now.
An "ExtensionPoint" is the thing you are extending. NUnit defines ExtensionPoints, while you create Extenisons to extend them. TypeExtensionPointAttribute is used inside NUnit to define extension points. It's not used by you. You use the ExtensionAttribute to define your extension.
Your extension should be defined something like this:
[Extension(Description = "Test Reporter Extension", EngineVersion="3.4")]
public class MyTestEventListener : ITestEventListener
{
public void OnTestEvent(string report)
{
Console.WriteLine(report);
}
}
You don't say what version of NUnit you are running. Test Listeners are only supported beginning with version 3.4. The EngineVersion property above is purely documentary at this point, because 3.4 is also the first version to recognize it.
There is a new writeup in the NUnit docs that may be helpful: https://github.com/nunit/docs/wiki/Writing-Engine-Extensions

Logging with Specflow and xUnit 2 (ITestOutputHelper)

Unfortunately I have a Specflow test passing locally, but it fails on the VSO Build vNext server, and I really need to see verbose information during the test run so I can figure out what is going on.
But I'm struggling to try to inject ITestOutputHelper into a Specflow binding like so
public SomeSteps(ITestOutputHelper outputHelper)
but Specflow complains with the message
BoDi.ObjectContainerException Interface cannot be resolved: Xunit.Abstractions.ITestOutputHelper (resolution path: ...)
How on earth can view log and view output during a Specflow test?
not sure if I'm using a newer version and it's easier now, but this seems to work for me:
ScenarioContext.Current.ScenarioContainer.Resolve<ITestOutputHelper>().WriteLine("Hello");
This is the best I could come up with, it's not ideal but it does accomplish what you want.
You create a new class that implements your generated xunit class. In my example, the generated class is called YourNormalFeatureClass
public class SpecialTest : YourNormalFeatureClass
{
private Xunit.Abstractions.ITestOutputHelper helper;
public SpecialTest(ITestOutputHelper helper) : base()
{
this.helper = helper;
}
public override void ScenarioSetup(ScenarioInfo scenarioInfo)
{
base.ScenarioSetup(scenarioInfo);
// you'd want a better way to keep track of this string
TechTalk.SpecFlow.TestRunnerManager.GetTestRunner().ScenarioContext.Set(this.helper, "helper");
}
}
Now, you're able to access your XUnit ITestOutputHelper from within your steps file via
var helper = this._scenarioContext.Get<Xunit.Abstractions.ITestOutputHelper>("helper");
helper.WriteLine("output from within the steps file that will be written to xunit!");
You'd need to be defensive with that helper variable to make sure that you don't get any NullReferenceException's
The downside to this is that you now have 2 copies of the same test because you inherited the old test. So in this case you have the tests from SpecialTest and YourNormalFeatureClass. This means that you'd need to not run YourNormalFeatureClass tests and only run the SpecialTest tests.
All of this would be easily solved if SpecFlow allowed you to customize the code generation process. That way you could expose the ITestOutputHelper via the generated code. The consumption of it from within the steps would be the same.
This may be a new addition to SpecFlow since this question was asked (6 years ago), but TechTalk.SpecFlow.Infrastructure.ISpecFlowOutputHelper should solve your problem. Inject it and use it in much the same way you would with xUnit's ITestOutputHelper, e.g.
[Binding]
public class SomeSteps
{
private readonly ISpecFlowOutputHelper output;
public SomeSteps(ISpecFlowOutputHelper output)
{
this.output = output;
}
[When(#"I write some debug info")]
public void WhenIWriteSomeDebugInfo()
{
this.output.WriteLine("Hello world!");
}
}

Visual Studio: Revoke reading permission of test file for Unit Testing

I am working on a Visual Studio (Community 2015) project in C# that reads metadata from video files. Therefore I want to write a Unit Test that tests if the program handles an inaccessible file the right way. So I want to add a test file to my test data for which the Unit Test does not have read permissions.
But what is the best way to do this? I didn't find any option to set permissions in Visual Studio. The only idea I have at the moment is to revoke reading permissions directly in the properties of the file. Through the Windows File Explorer, thus outside of Visual Studio. But then I wouldn't be able to read the file myself. Also, it doesn't seem to be the right way and I think there should be a more clean way to solve this problem directly in Visual Studio.
Any ideas?
If you are writing a unit test then it should just check if your code is written correcly and not about the external issues which are difficult to replicate or may not be available on other machines. So I think you should read about Dependency Injection and how to do mock dependencies in your test. I can give you an easy to understand example but please do write it in your words.
public interface IFileReader
{
string ReadFile( string filePath );
}
public class FileReader : IFileReader
{
public string ReadFile( string filePath )
{
return System.IO.File.ReadAllText( filePath );
}
}
So Suppose you have a class VideoMetaDataReader then in that class you will inject the interface as a dependency and use the ReadFile method to read. And then in your test
[TestFixture]
public class FileReaderTests
{
[Test]
public void ShouldDisplayANiceMessage_WhenFileIsInaccessible()
{
var moq = new Moq.Mock<IFileReader>();
moq
.Setup( x => x.ReadFile( Moq.It.IsAny<string>() ) )
.Throws<Exception>();
var metaDataReader = new MetaDataReader( moq.Object );
metaDataReader.ReadVideoFile( "video.mp4" );
Assert.AreEqual( 1, meaDataReader.Errors.Count );
}
}
I am assuming there will be a errors property which will return encountered errors but it depends how you want to do it (I didn't think too much on this).
Anyways, the point is don't test what is not covered by your code. What your code needs to do is to display a nice message if there is an exception and that you can do if you mock the interface (which means don't call the actual implementation and instead do something which I want in this test) and then check if your code can handle that. btw i used nunit and moq for test and mocking.

nunit TestContext throws NullReferenceException

I have the following code:
[TestFixture]
public class LexicalTests
{
[Test]
public void LexicalTest1()
{
TestContext.CurrentContext.TestDirectory;
}
}
CurrentContext throws an exception while attempting to get TestDirectory or WorkingDirectory property.
How can I solve this problem?
P.S.: On my home PC tests work perfectly (without strange exceptions).
It seems that some applications that offer the functionality to run NUnit unit tests have a problem with the TestContext class.
The test in class below should pass:
using NUnit.Framework;
namespace UnitTests
{
[TestFixture]
public class UnitTests
{
[Test]
public void CurrentContextTest()
{
Assert.IsNotNull(TestContext.CurrentContext);
Assert.IsNotNull(TestContext.CurrentContext.TestDirectory);
Assert.IsNotNull(TestContext.CurrentContext.WorkDirectory);
}
}
}
If the test doesn't pass then, as Dmitry wrote in his comment above, change the NUnit version in the ReSharper menu. From within Visual Studio, go to ReSharper -> Options -> Tools -> NUnit. Click the Specified NUnit installation radio button and ensure that a folder with nunit.core.dll, nunit.core.interfaces.dll and nunit.util.dll is specified. An error will be displayed if the listed files cannot be found.
Once the NUnit version has been changed, re-run the test and it should pass.

Categories

Resources