如何判断我的程序是否在单元测试环境下

时间:2015-04-22 17:10:33

标签: c# .net visual-studio unit-testing console

我有一个控制台应用程序。在发布环境中,它目前运行良好。在IDE调试环境中,我不希望控制台窗口关闭,所以我添加了这个函数,并在程序的最后调用它。

[Conditional("DEBUG")]
public static void DebugWaitAKey(string message = "Press any key")
{
    Console.WriteLine(message);
    Console.ReadKey();
}

当我调试程序时,它对我很有用。但是通过单元测试,它在退出之前仍然会等待一个键!

解决方法只是我的程序的单元测试发行版,或测试其他功能。但我确实希望能够识别当前会话正在进行单元测试,并在此函数中使用该标志。

5 个答案:

答案 0 :(得分:4)

我相信this应该回答你的问题。我从那里上了一堂课,并根据你的情况进行了调整。

/// <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; }
}

然后我在你的方法中添加了一行,如果它正在运行测试,它将不会命中Console.ReadKey();

[Conditional("DEBUG")]
public static void DebugWaitAKey(string message = "Press any key")
{
    Console.WriteLine(message);
    if(!UnitTestDetector.IsInUnitTest)
        Console.ReadKey();
}

注意:这将被视为黑客攻击,不会被视为最佳做法。

修改 我还在github上创建了一个示例项目来演示此代码。 https://github.com/jeffweiler8770/UnitTest

答案 1 :(得分:1)

不是查看程序是否在调试模式下编译,而是查看是否附加了调试器:

if (Debugger.IsAttached)
{
    Console.WriteLine(message);
    Console.ReadKey();
}

请注意,这只会检测您是从Visual Studio开始使用F5,而不是Ctrl-F5(即仅使用调试启动)

答案 2 :(得分:1)

如果您的测试从专用的UnitTest项目运行,那么这是一种简单的方法:在AppSettings中使用一个标志......

我不会为了这样的目的调查模式,我会在具有自己配置的专用UnitTest项目中运行测试。

如果您需要收集数据,可能只需使用跟踪(可以从.config文件中自定义)......?

希望这会有所帮助......

答案 3 :(得分:0)

我使用了Jeff的UnitTestDetector变体。我不想检查单元测试组件,并希望控制哪些单元测试会考虑这个。

所以我创建了一个简单的类,IsInUnitTest默认为false。 然后在我想要运行条件代码的单元测试类中,我添加了TestInitializer和TestCleanup,我相应地设置了bool。

然后在我的常规代码中,我可以使用UnitTestDetector.IsInUnitTest

Simple UnitTestDetector类:

/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
    static private bool _isInUnitTest = false;
    public static bool IsInUnitTest
    {
        get { return _isInUnitTest; }
        set { _isInUnitTest = value; }
    }
}

测试这个东西的单元测试:

[TestClass]
public class UnitTestDetectorTest_WithoutIsInUnitTest
{
    [TestMethod]
    public void IsInUnitTest_WithoutUnitTestAttribute_False()
    {
        bool expected = false;
        bool actual = UnitTestDetector.IsInUnitTest;
        Assert.AreEqual(expected, actual);
    }
}

[TestClass]
public class UnitTestDetectorTest_WithIsInUnitTest
{
    [TestInitialize()]
    public void Initialize()
    {
        UnitTestDetector.IsInUnitTest = true;
    }

    [TestCleanup()]
    public void Cleanup()
    {
        UnitTestDetector.IsInUnitTest = false;
    }

    [TestMethod]
    public void IsInUnitTest_WithUnitTestAttribute_True()
    {
        bool expected = true;
        bool actual = UnitTestDetector.IsInUnitTest;
        Assert.AreEqual(expected, actual);
    }
}

代码中的条件:

if (UnitTestDetector.IsInUnitTest)
            return "Hey I'm in the unit test :)";

答案 4 :(得分:0)

我知道这很旧,但是我真的不喜欢其中的许多答案,尤其是那些硬编码程序集名称或版本的答案。

这很好,只要您要测试的课程是非密封即可。很简单:

将此类变量添加到要测试的类中:

    protected Boolean IsInUnitTestMode = false;

我们默认将其设置为false,因此在生产中它将始终为false。

将类似这种包装的东西添加到测试类中

    class ProfileTest : Profiles
    {
        public ProfileTest() : base()
        {
            IsInUnitTestMode = true;
        }
    }

在此示例中, Profiles 是我们正在测试的类, ProfileTest 是测试项目名称空间中的包装器类。它将永远不会被部署。测试类使用它来创建要测试的类的实例:

    ProfileTest profiles = new ProfileTest();

与此相反:

    private Profiles profiles = new Profiles();

我们可以这样使用它:

    private string ProfilePath
    {
         get
         {
            if (IsInUnitTestMode) 
                return SafeStorage.EnsureFolderExists(Path.Combine(SafeStorage.UserPath, UNITTESTFOLDERNAME)).FullName;
            else
                return SafeStorage.EnsureFolderExists(Path.Combine(SafeStorage.UserPath, PROFILEFOLDERNAME)).FullName;
            }
        }

正如我所说,这不适用于密封类,也不适用于静态类。如此说来,我实际上选择测试单元测试条件的次数非常少。这对我来说非常好。