我怎么知道我的程序在单元测试环境下
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,也不适用于静态的。话虽如此,我实际选择测试单元测试条件的次数非常少。这对我来说非常有效。
我有一个控制台应用程序。在发布环境中,此时它可以完美运行。在 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,也不适用于静态的。话虽如此,我实际选择测试单元测试条件的次数非常少。这对我来说非常有效。