C# - Apply attribute to method conditionally from app.config - c#

TLDR;
How can I create a pre-processing directive in C# based on values from an app.config file?
I am using Selenium to do integration testing. I have two test method classes which are responsible for testing different areas of my application. My test classes are identified as such with a [TestClass] attribute, and my test methods are identified using a [TestMethod] attribute like so:
[TestClass]
public class TestsForAreaX
{
[TestMethod]
public void TestFoo()
{
//Do test logic here
}
[TestMethod]
public void TestBar()
{
//Do test logic here
}
}
When I rebuild my solution all methods that have had the [TestMethod] applied will appear in the test explorer.
What I would now like to do is add some flags to my app.config to conditionally apply [TestMethod] attributes so that I can specify which tests I want run. The reason for this is that some tests are taking very long and I would like to exclude them without having to fiddle with method attributes directly.
I am aware of pre-processing directives like:
#if DEBUG
//debug mode
#elif
//release mode
#endif
but that only works for build configurations and not values in app config files, unless I am mistaken?

You cannot remove the attributes of the assembly after compilation. Maybe you are looking for Categories:
[TestClass]
public class TestsForAreaX
{
[TestCategory("LongRunning"), TestMethod]
public void TestFoo()
{
//Do test logic here
}
[TestCategory("ShortRunning"), TestMethod]
public void TestBar()
{
//Do test logic here
}
} enter code here
Then you can run tests for different categories at least from the command line, this site explains how:
http://msdn.microsoft.com/en-us/library/dd286683.aspx

Related

Configuration Manager NameValueCollections returning null or empty collection from Unit Test

I have two projects in Visual Studio, the core project which is a Windows Service Executable, and the Unit Test Project.
The core project has two original files broken out like this
File1.cs:
using static Proj.ConfigHelper;
namespace Proj
{
class MyClass
{
(lots of code)
}
}
File2.cs looks something like this.
namespace Proj
{
static class ConfigHelper
{
public static NameValueCollection AppSettings { get { return ConfigurationManager.AppSettings; } }
public static NameValueCollection CustomSection { get { return ConfigurationManager.GetSection("CustomSection") as NameValueCollection; } }
}
}
Both of those classes are internal and made visible to the unit test project via InternalsVisibleToAttribute.
Inside of the UnitTest project which is a discrete project within the same solution (and so it has its own app.config), calling ConfigHelper.AppSettings results in a 0-item collection, and calling ConfigHelper.CustomSection results in null. If I attempt to unit test a method within File1.cs that depends on those settings, they run as default values as if they were not configured at all. I don't quite understand why this is happening. Can anyone help me understand what I did wrong? It seems as though the ConfigHelper is not loading the App.Config for its own project.
The app.config for the Windows Service Project is set to "always copy" and the app.config for the unit test project is set to "never copy"
The test will use its own config so you need to mirror it. There are work runarounds: Can a unit test project load the target application's app.config file?

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!");
}
}

How do you make internals visible to nCrunch

MyProject has an internal class and method as such.
namespace MyProject
{
internal class InboundMailAlertParser
{
internal InboundMailAlert ParseMessageBody(string body)
{
...
}
}
}
I'm using InternalsVisibleTo in my MyProject AssemblyInfo.cs to expose internal classes/methods to a unit test assembly.
[assembly: InternalsVisibleTo("MyProject.Tests")]
My Test looks like this
namespace MyProject.Tests
{
[TestClass]
public class InboundMailAlertParserTests
{
[TestMethod]
public void ParsesBody()
{
InboundMailAlertParser parser = new InboundMailAlertParser();
parser.ParseMessageBody(messageBody.ToString());
}
}
}
My test passes fine when run in Visual Studio, but nCrunch is failing to build the unit test project due to not being able to see the internal InboundMailAlertParser of the MyProject assembly under test. Is there another nCrunch assembly I have to indicate should have internal visiblity to allow nCrunch to be able to build the test assembly?
Turns out I had ignored a component (project) in the nCrunch config. Once I enabled that, the project could build correctly and I got my lovely green dots.

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