【问题标题】:How can I tell that my program is under unit test environment我怎么知道我的程序在单元测试环境下
【发布时间】:2015-04-22 17:10:32
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    我相信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();
    }
    

    注意:这将被视为 hack,不会被视为最佳做法。

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

    【讨论】:

    • 这行得通。您甚至在 github 中包含 bin 和 obj 吗? :-)
    • 我并没有尝试这样做,而且我对将东西放在 github 上还很陌生。 :-)
    【解决方案2】:

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

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

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

    希望这会有所帮助...

    【讨论】:

    • 这会增加配置工作。我的期望是 100% 自动化。
    【解决方案3】:

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

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

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

    【讨论】:

    • [Conditional("DEBUG")] 与您的 Debugger.IsAttached 具有相同的目的
    • 不,不会。条件属性检查程序是否在调试模式下编译(即存在 DEBUG 符号)。我的检查是否附加了调试器。
    • 诚然,如果您调试单元测试,我的仍然会暂停!但对于正常运行,这工作正常。我在我的程序中使用它只是因为如果您使用调试器,控制台窗口默认关闭。
    【解决方案4】:

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

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

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

    简单的 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 :)";
    

    【讨论】:

      【解决方案5】:

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

      只要您要测试的类未密封,此方法效果很好。很简单:

      将这个类变量添加到你正在测试的类中:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-17
        • 1970-01-01
        相关资源
        最近更新 更多