This question already has answers here:
How to stop evaluation of parameters in calls to debug functions when in Release build (C#)
(3 answers)
Closed 4 years ago.
Please note that I am aware of Debug.Print - the Console.WriteLine is a very simplified example of what I'm trying to do.
Is there a way to have a single line of code which exists only in Debug mode, which does not appear in Release at all?
I have some commands which help me debug the execution of a performance-critical section of code, and I have placed a large number of them all over the function in key places.
Here is an example of what I've done:
using System;
public class C {
public Object _obj = new object();
public void M()
{
Alpha("This goes away in Release");
Alpha(_obj.GetHashCode() + "...but this doesn't");
#if DEBUG
//But I don't want this three line deal.
Alpha(_obj.GetHashCode() + "...of course this does get removed");
#endif
}
public static void Alpha(String s)
{
#if DEBUG
Console.WriteLine(s);
#endif
}
}
The issue is that in release mode, the compiler recognizes that the first call does nothing in release mode, and removes it. But it does not do that in the second call. I know this because I have tested it in SharpLab: https://sharplab.io/#v2:EYLgHgbALANALiAhgZwLYB8CQBXZBLAOwHMACAZQE9k4BTVAbgFgAoTAB22ABs8BjE3lxTISAYRIBvFpnace/APLAAVjV5wSAfQD2KkgF4SBGgHcSu1eoAUASiatZ3PiQBu2vABMSAWVslpmFIOmACCXGwAFohWAEQAKhF4IkTaNCKIJogUJIQkAEo0XDQoNDF2AaHhUVY6KgB0AOI0cAASKBGi2h40fgDUJDF1Q8DYGnCJIh6pyAQAAgC0AIxwZfYymBUAxHgAZiQAIgCiAEIAqg3+wZgA9NfHoyQAkiRTc0samQRjEyTjAE40GgkHjGF7FLh1CqVSLRWrKRrNNrIDpdHo2Ej9QZDbR7XjabB/ZBA8ZJF7TEhEZokAGobQuGgeVZbGgEDy7KEBAC+AQCHCc/GoiDgzjcnhIYRhVjIcD+hFIyBsASC622eyOZwaUM6BGQ2iKdQA6rLaAAZQg9BVrGSbFlsnZc6ScoA==
Is there any way of avoiding the three-line version?
Yes, just put a [Conditional(...)] attribute on the method that you need to "not exist" unless you are using the Debug configuration:
[System.Diagnostics.Conditional("DEBUG")]
public static void Alpha(String s)
{
Console.WriteLine(s);
}
All calls to such methods are effectively removed (not compiled) unless the specified symbol is present.
Note that a restriction applies: [Conditional(...)] can only be used for void methods.
You probably desire ConditionalAttribute:
using System;
using System.Diagnostics;
public class C {
public Object _obj = new object();
public void M()
{
Alpha("This goes away in Release");
Alpha(_obj.GetHashCode() + "...this is ommited");
}
[Conditional("DEBUG")]
public static void Alpha(String s)
{
Console.WriteLine(s);
}
}
See SharpLab for results.
A neat trick you could use for void methods is the ConditionalAttribute, used like this:
[Conditional("DEBUG")]
public static void Alpha(String s)
{
/***/
}
The compiler would remove all calls to those methods if the symbol is not defined.
Also there's this monstrosity:
if (System.Diagnostics.Debugger.IsAttached) /* your debug */
Works in one line, but requires an attached debugger and also is not "removing" the code.
In other words, is there an Attribute that marks a segment of code as not too old, but too new and therefore not quite ready for widespread use?
If I'd have to create a custom Attribute to accomplish this, that's fine. I just wanted to make sure first.
No, there's nothing standardized around this. You might want to consider just not exposing code like that though - or only exposing it in beta builds etc.
Not an attribute, but there are preprocessor directives (https://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx) which we can use to mark a region of code as "too new" to run. Basically you can define a flag to indicate that piece of code is ready.
Here is an example:
#define FOREST_CAN_RUN
//undef FOREST_CAN_RUN --> disable that feature
using System;
namespace Test
{
public class Forest
{
public void Run()
{
#if FOREST_CAN_RUN
Console.Write("Run Forest, Run !");
#else
Console.Write("Sorry, Jenny");
#endif
}
}
public class Program
{
static void Main(string[] args)
{
Forest f= new Forest ();
f.Run();
}
}
}
How does one assert that assertions are enabled in C#?
Here's a link to a related answer for Java, that does not work in C#.
The purpose of this would be to prevent the use of release-type assemblies because where efficiency is of no concern I might as well be running with all the assertions working, so there is in some places a preference for debug-type assemblies.
Use of Debug.Assert(false) was not satisfactory because it creates a dialog and requires user interaction. It would be good to know assertions work without the "noise". The Java solution is noiseless.
EDIT: This is taken from a comment under the accepted answer.
public static class CompileTimeInformation
{
public static void AssertAssertionsEnabled()
{
// Recall that assertions work only in the debug version of an assembly.
// Thus the assertion that assertions work relies upon detecting that the assembly was compiled as a debug version.
if (IsReleaseTypeAssembly())
throw new ApplicationException("Assertions are not enabled.");
}
public static bool IsReleaseTypeAssembly()
{
return ! IsDebugTypeAssembly();
}
public static bool IsDebugTypeAssembly()
{
return
#if DEBUG
true
#else
false
#endif
;
}
}
Update: There's a simpler solution. The other one is still below for the curious.
public static bool AreAssertionsEnabled =
#if DEBUG
true
#else
false
#endif
;
Looks nasty but is quite simple.
Let's first look at what causes Debug.Assert to disappear in non-DEBUG builds:
[Conditional("DEBUG"), __DynamicallyInvokable]
public static void Assert(bool condition)
{
TraceInternal.Assert(condition);
}
It's [Conditional("DEBUG")]. That inspires the following solution:
public static bool AreAssertionsEnabled = false;
static MyClassName() { MaybeSetEnabled(); /* call deleted in RELEASE builds */ }
[Conditional("DEBUG")]
static void MaybeSetEnabled()
{
AreAssertionsEnabled = true;
}
You can probably refactor this so that AreAssertionsEnabled can be readonly. I just can't think of a way right now.
You can now check the boolean value AreAssertionsEnabled and perform any logic you like based on it.
I need a way to show this C# 3.0 code:
[TestMethod]
#if NUNIT
[Moled]
#else
[HostType("Moles")]
#endif
public void TestSomething()
With out using/needing the pre-processor commands on each method.
Is this possible?
Talking with a co-worker, we theorized that there may be a way to create an attribute class that has 2 constructors (one with zero params and one with 1 string). Then in the top of the file we do our conditional there like this:
#if NUNIT
Moled = MyNamespace.MyNewAttribute;
#else
HostType = MyNamespace.MyNewAttribute;
#endif
The MyNewAttribute class would be setup to do nothing, so that I can compile with this:
[TestMethod]
[Moled]
[HostType("Moles")]
public void TestSomething()
Would this work? How would I write this class?
Your updated question provides an interesting and (in my opinion) viable solution.
All you need to do to finish it is to declare MyNewAttribute, which should be simple:
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public sealed class MyNewAttribute : Attribute
{
public MyNewAttribute() { }
public MyNewAttribute(string dummy) { }
}
In your #if trick, you will have to use the full class names:
#if NUNIT
using MoledAttribute = MyNamespace.MyNewAttribute;
#else
using HostTypeAttribute = MyNamespace.MyNewAttribute;
#endif
Note: I don’t know which way around these should be — your question contradicts itself on this. Remember you need to redefine the one that you want to disable, not the one you want to enable.
Also, these using statements need to be first within the namespace, before all type declarations. I tried this and it works even if MyNewAttribute is declared further down in the same file.
Since this is quite an unusual trick, I strongly recommend to put an explanatory comment on the #if construct so that future readers of your code can understand what it means, why it’s there, and how it works.
By the way, with custom attribute names as short as these, and with few or no constructor arguments, personally I find it more readable to put them in one line:
[TestMethod, Moled, HostType("Moles")]
public void TestSomething()
I don't see why you need aliases at all. Just do this in one single file:
#if NUNIT
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public sealed class HostTypeAttribute : Attribute
{
public HostTypeAttribute(string dummy) { }
}
#else
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public sealed class MoledAttribute : Attribute
{
public MoledAttribute() { }
}
#endif
Then you can use both, in any file, with no preprocessor defines anywhere except here.
You are close to the right track. You just need to create a dummy attribute class that can take the place of the attributes that you are trying to switch:
public sealed class DummyAttribute : Attribute
{
public DummyAttribute()
{}
pulic DummyAttribute(string dummy)
{}
}
The two constructors are necessary because one of the attributes that you are trying to replace accepts a string as a parameter. Setting up the dummy constructors allows you to ignore the actual behavior of the attributes that you are replacing.
Then your preprocessor block at the top of the file should look something like this:
#if !NUNIT
using Moled = MyNameSpace.DummyAttribute;
#else
using HostType = MyNameSpace.DummyAttribute;
#endif
Sure, split it into two files:
File1:
[TestMethod]
[Moled]
public void TestSomething()
File2:
[TestMethod]
[HostType("Moles")]
public void TestSomething()
Use whichever file is appropriate.
UPDATE:
Ah, I think I finally understand what you're after.
You don't really want to "eliminate the preprocessor directives" as your original question requested, what you actually want to do is unify the attributes on your methods based on a preprocessor directive.
Yes, that can be done via the magic of a using class alias!
You rename the two attribute classes you're interested in swapping to the same name like this:
#if NUNIT
using MyAttrib = System.Diagnostics.ConditionalAttribute;
#else
using MyAttrib = System.ObsoleteAttribute;
#endif
And then you decorate all your methods like this:
[MyAttrib( "attrib arg" )]
public void TestSomething()
I've done the exact same thing myself for when a project was going to be unit tested via the Microsoft way but not until we had the version of Visual Studio that supported it.
I have a unit test (nUnit). Many layers down the call stack a method will fail if it is running via a unit test.
Ideally you would use something like mocking to setup the object that this method is depending on but this is 3rd party code and I can't do that without a lot of work.
I don't want setup nUnit specific methods - there are too many levels here and its a poor way of doing unit test.
Instead what I would like to do is to add something like this deep down in the call stack
#IF DEBUG // Unit tests only included in debug build
if (IsRunningInUnitTest)
{
// Do some setup to avoid error
}
#endif
So any ideas about how to write IsRunningInUnitTest?
P.S. I am fully aware that this is not great design, but I think its better than the alternatives.
I've done this before - I had to hold my nose while I did it, but I did it. Pragmatism beats dogmatism every time. Of course, if there is a nice way you can refactor to avoid it, that would be great.
Basically I had a "UnitTestDetector" class which checked whether the NUnit framework assembly was loaded in the current AppDomain. It only needed to do this once, then cache the result. Ugly, but simple and effective.
Taking Jon's idea this is what I came up with -
using System;
using System.Reflection;
/// <summary>
/// Detect if we are running as part of a nUnit unit test.
/// This is DIRTY and should only be used if absolutely necessary
/// as its usually a sign of bad design.
/// </summary>
static class UnitTestDetector
{
private static bool _runningFromNUnit = false;
static UnitTestDetector()
{
foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
{
// Can't do something like this as it will load the nUnit assembly
// if (assem == typeof(NUnit.Framework.Assert))
if (assem.FullName.ToLowerInvariant().StartsWith("nunit.framework"))
{
_runningFromNUnit = true;
break;
}
}
}
public static bool IsRunningFromNUnit
{
get { return _runningFromNUnit; }
}
}
Pipe down at the back we're all big enough boys to recognise when we're doing something we probably shouldn't ;)
Adapted from Ryan's answer. This one is for the MS unit test framework.
The reason I need this is because I show a MessageBox on errors. But my unit tests also test the error handling code, and I don't want a MessageBox to pop up when running unit tests.
/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
static UnitTestDetector()
{
string testAssemblyName = "Microsoft.VisualStudio.QualityTools.UnitTestFramework";
UnitTestDetector.IsInUnitTest = AppDomain.CurrentDomain.GetAssemblies()
.Any(a => a.FullName.StartsWith(testAssemblyName));
}
public static bool IsInUnitTest { get; private set; }
}
And here's a unit test for it:
[TestMethod]
public void IsInUnitTest()
{
Assert.IsTrue(UnitTestDetector.IsInUnitTest,
"Should detect that we are running inside a unit test."); // lol
}
Simplifying Ryan's solution, you can just add the following static property to any class:
public static readonly bool IsRunningFromNUnit =
AppDomain.CurrentDomain.GetAssemblies().Any(
a => a.FullName.ToLowerInvariant().StartsWith("nunit.framework"));
I use a similar approach as tallseth
This is the basic code which could be easily modified to include caching.
Another good idea would be to add a setter to IsRunningInUnitTest and call UnitTestDetector.IsRunningInUnitTest = false to your projects main entry point to avoid the code execution.
public static class UnitTestDetector
{
public static readonly HashSet<string> UnitTestAttributes = new HashSet<string>
{
"Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute",
"NUnit.Framework.TestFixtureAttribute",
};
public static bool IsRunningInUnitTest
{
get
{
foreach (var f in new StackTrace().GetFrames())
if (f.GetMethod().DeclaringType.GetCustomAttributes(false).Any(x => UnitTestAttributes.Contains(x.GetType().FullName)))
return true;
return false;
}
}
}
Maybe useful, checking current ProcessName:
public static bool UnitTestMode
{
get
{
string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
return processName == "VSTestHost"
|| processName.StartsWith("vstest.executionengine") //it can be vstest.executionengine.x86 or vstest.executionengine.x86.clr20
|| processName.StartsWith("QTAgent"); //QTAgent32 or QTAgent32_35
}
}
And this function should be also check by unittest:
[TestClass]
public class TestUnittestRunning
{
[TestMethod]
public void UnitTestRunningTest()
{
Assert.IsTrue(MyTools.UnitTestMode);
}
}
References:
Matthew Watson in http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/11e68468-c95e-4c43-b02b-7045a52b407e/
Somewhere in the project being tested:
public static class Startup
{
public static bool IsRunningInUnitTest { get; set; }
}
Somewhere in your unit test project:
[TestClass]
public static class AssemblyInitializer
{
[AssemblyInitialize]
public static void Initialize(TestContext context)
{
Startup.IsRunningInUnitTest = true;
}
}
Elegant, no. But straightforward and fast. AssemblyInitializer is for MS Test. I would expect other test frameworks to have equivalents.
In test mode, Assembly.GetEntryAssembly() seems to be null.
#IF DEBUG // Unit tests only included in debug build
if (Assembly.GetEntryAssembly() == null)
{
// Do some setup to avoid error
}
#endif
Note that if Assembly.GetEntryAssembly() is null, Assembly.GetExecutingAssembly() isn't.
The documentation says: The GetEntryAssembly method can return null when a managed assembly has been loaded from an unmanaged application.
Just use this:
AppDomain.CurrentDomain.IsDefaultAppDomain()
In test mode, it will return false.
I use this only for skipping logic that disables all TraceAppenders in log4net during startup when no debugger is attached. This allows unit tests to log to the Resharper results window even when running in non-debug mode.
The method that uses this function is either called on startup of the application or when beginning a test fixture.
It is similar to Ryan's post but uses LINQ, drops the System.Reflection requirement, does not cache the result, and is private to prevent (accidental) misuse.
private static bool IsNUnitRunning()
{
return AppDomain.CurrentDomain.GetAssemblies().Any(assembly => assembly.FullName.ToLowerInvariant().StartsWith("nunit.framework"));
}
Having a reference to nunit framework doesn't mean that test is actually running. For example in Unity when you activate play mode tests the nunit references are added to the project. And when you run a game the references are exist, so UnitTestDetector would not work correctly.
Instead of checking for nunit assembly we can ask nunit api to check is code under executing test now or not.
using NUnit.Framework;
// ...
if (TestContext.CurrentContext != null)
{
// nunit test detected
// Do some setup to avoid error
}
Edit:
Beware that the TestContext may be automatically generated if it's required.
I have a solution that's closer to what the original poster wanted. The issue is how to set the test flag to indicate the code is executing as part of a test. This can be implemented with 2 lines of code.
I have added an internal variable called RunningNunitTest at the top of the class. Be sure to make this an internal variable and not public. We don't want to export this variable when we build the project. Also this is how we're going to allow NUnit to set it to true.
NUnit does not have access to private variables or methods in our code. This is an easy fix. In between the using statements and the namespace add a [assembly: InternalsVisibleTo("NUnitTest")] decoration. This allows NUint access to any internal variable or method. My NUnit test project is named "NUintTest." Replace this name with the name of your NUint test Project.
That's it! Set RunningNunitTest to true in your NUnit tests.
using NetworkDeviceScanner;
[assembly: InternalsVisibleTo("NUnitTest")] // Add this decoration to your class
namespace NetworkDeviceScannerLibrary
{
public class DetectDevice
{
internal bool RunningNunitTest = false; // Add this variable to your class
public ulong TotalAddressesFound;
public ulong ScanCount;
NUnit Code
var startIp = IPAddress.Parse("191.168.1.1");
var endIp = IPAddress.Parse("192.168.1.128");
var detectDevice = new DetectDevice
{
RunningNunitTest = true
};
Assert.Throws<ArgumentOutOfRangeException>(() => detectDevice.DetectIpRange(startIp, endIp, null));
works like a charm
if (AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName.ToLowerInvariant().StartsWith("nunit.framework")) != null)
{
fileName = #"C:\Users\blabla\xxx.txt";
}
else
{
var sfd = new SaveFileDialog
{ ... };
var dialogResult = sfd.ShowDialog();
if (dialogResult != DialogResult.OK)
return;
fileName = sfd.FileName;
}
.
Unit tests will skip application entry point. At least for wpf, winforms and console application main() is not being called.
If main method is called than we are in run-time, otherwise we are in unit test mode:
public static bool IsUnitTest { get; private set; } = true;
[STAThread]
public static void main()
{
IsUnitTest = false;
...
}
I was unhappy to have this problem recently. I solved it in a slightly different way. First, I was unwilling to make the assumption that nunit framework would never be loaded outside a test environment; I was particularly worried about developers running the app on their machines. So I walked the call stack instead. Second, I was able to make the assumption that test code would never be run against release binaries, so I made sure this code did not exist in a release system.
internal abstract class TestModeDetector
{
internal abstract bool RunningInUnitTest();
internal static TestModeDetector GetInstance()
{
#if DEBUG
return new DebugImplementation();
#else
return new ReleaseImplementation();
#endif
}
private class ReleaseImplementation : TestModeDetector
{
internal override bool RunningInUnitTest()
{
return false;
}
}
private class DebugImplementation : TestModeDetector
{
private Mode mode_;
internal override bool RunningInUnitTest()
{
if (mode_ == Mode.Unknown)
{
mode_ = DetectMode();
}
return mode_ == Mode.Test;
}
private Mode DetectMode()
{
return HasUnitTestInStack(new StackTrace()) ? Mode.Test : Mode.Regular;
}
private static bool HasUnitTestInStack(StackTrace callStack)
{
return GetStackFrames(callStack).SelectMany(stackFrame => stackFrame.GetMethod().GetCustomAttributes(false)).Any(NunitAttribute);
}
private static IEnumerable<StackFrame> GetStackFrames(StackTrace callStack)
{
return callStack.GetFrames() ?? new StackFrame[0];
}
private static bool NunitAttribute(object attr)
{
var type = attr.GetType();
if (type.FullName != null)
{
return type.FullName.StartsWith("nunit.framework", StringComparison.OrdinalIgnoreCase);
}
return false;
}
private enum Mode
{
Unknown,
Test,
Regular
}
Application.Current is null when running under the unit tester. At least for my WPF app using MS Unit tester. That's an easy test to make if needed. Also, something to keep in mind when using Application.Current in your code.
if (string.IsNullOrEmpty(System.Web.Hosting.HostingEnvironment.MapPath("~")))
{
// Running not as a web app (unit tests)
}
// Running as a web app
There is a really simple solution as well when you are testing a class...
Simply give the class you are testing a property like this:
// For testing purposes to avoid running certain code in unit tests.
public bool thisIsUnitTest { get; set; }
Now your unit test can set the "thisIsUnitTest" boolean to true, so in the code you want to skip, add:
if (thisIsUnitTest)
{
return;
}
Its easier and faster than inspecting the assemblies. Reminds me of Ruby On Rails where you'd look to see if you are in the TEST environment.
Considering your code is normaly run in the main (gui) thread of an windows forms application and you want it to behave different while running in a test you can check for
if (SynchronizationContext.Current == null)
{
// code running in a background thread or from within a unit test
DoSomething();
}
else
{
// code running in the main thread or any other thread where
// a SynchronizationContext has been set with
// SynchronizationContext.SetSynchronizationContext(synchronizationContext);
DoSomethingAsync();
}
I am using this for code that I want to fire and forgot in a gui application but in the unit tests I might need the computed result for an assertation and I don't want to mess with multiple threads running.
Works for MSTest. The advantage it that my code does not need to check for the testing framework itself and if I really need the async behaviour in a certain test I can set my own SynchronizationContext.
Be aware that this is not a reliable method to Determine if code is running as part of a unit test as requested by OP since code could be running inside a thread but for certain scenarios this could be a good solution (also: If I am already running from a background thread, it might not be necessary to start a new one).
I've used the following in VB in my code to check if we ae in a unit test. spifically i didn't want the test to open Word
If Not Application.ProductName.ToLower().Contains("test") then
' Do something
End If
How about using reflection and something like this:
var underTest = Assembly.GetCallingAssembly() != typeof(MainForm).Assembly;
The calling assembly will be where your test cases are and just substitute for MainForm some type that's in your code being tested.