我怎么知道我的程序在单元测试环境下

How can I tell that my program is under unit test environment

我有一个控制台应用程序。在发布环境中,此时它可以完美运行。在 IDE 调试环境中,我不想关闭控制台 window,所以我添加了这个函数,并在程序的最后调用它。

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

当我调试我的程序时,它对我来说效果很好。但是通过单元测试,它仍然在退出之前等待一个键!

变通方法只是对我的程序的发布版本进行单元测试,或者测试其他功能。但我确实想要一些东西可以识别当前会话正在单元测试中,并在此函数中使用该标志。

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

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

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

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

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

如果您需要收集数据,也许您应该简单地使用跟踪(它们可以从您的 .config 文件中自定义)...?

希望这对您有所帮助...

我相信 this 应该可以回答您的问题。我从那里拿了一个 class 并根据你的情况进行了调整。

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

注意:这将被视为 hack,不会被视为最佳实践。

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

我使用了 Jeff 的 UnitTestDetector 的变体。我不想检查单元测试程序集,而是想控制哪些单元测试会考虑这个问题。

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

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

简单的 UnitTestDetector class:

/// <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 :)";

我知道这已经过时了,但我真的不喜欢其中的许多答案,尤其是任何对程序集名称或版本进行硬编码的答案。

只要您正在测试的 class 是 未密封的 ,此方法就可以正常工作。这很简单:

将此 class 变量添加到您正在测试的 class:

    protected Boolean IsInUnitTestMode = false;

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

在你的测试中添加类似这个包装器的东西class

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

在这个例子中 Profiles 是我们正在测试的 class,ProfileTest 是一个包装器 class测试项目的命名空间。它永远不会被部署。测试 class 使用它来创建要测试的 class 的实例:

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

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