【问题标题】:Can I force MSTest to use a new process for each test run?我可以强制 MSTest 为每次测试运行使用一个新进程吗?
【发布时间】:2011-11-18 21:55:59
【问题描述】:

我们正在使用 VS 2010 测试运行程序 (MSTest) 进行自动化功能测试。当我们从 Visual Studio 运行测试时,VS 会创建一个名为 QTAgent32.exe 的进程,并在该进程中运行测试。

我们发现,当我们进行多次测试运行时,MSTest 将重用同一个 QTAgent32 进程——进程 ID 不会改变。这对我们来说是个问题,因为我们正在测试的代码是 P/Invoking 到非托管 DLL。 DLL 在进程的生命周期内只需要初始化一次。我们有一个 [AssemblyInitialize] 方法,但每次测试运行都会执行一次。如果我们执行多次测试运行,它将在同一个进程中执行多次。

每次我们进行测试运行时,MSTest 都会创建一个新的 appdomain;但是这些appdomains都在同一个进程中。

所以我想知道:有没有办法告诉 Visual Studio 测试运行器在我们每次运行测试时使用新进程?我查看了“.testsettings”配置,但没有看到任何相关内容。

【问题讨论】:

  • 只是出于我的好奇 - 是否有可能在使用 FreeLibrary 进行每次连续测试后卸载非托管 DLL?
  • 感谢 Wiktor - 好建议。现在,代码只是静态引用非托管 API,在 C# extern 函数声明上使用 [DllImport] 属性。我假设当 appdomain 被拆除时,.NET 不会自动释放库,因为我们遇到了错误。我实际上不知道如何从 C# 代码调用动态加载的 DLL - 你可以调用 LoadLibrary() 和 GetProcAddress(),然后以某种方式将返回的函数指针转换为委托类型吗?无论如何,我会调查它 - 谢谢!我刚刚发现这可能会有所帮助:codeproject.com/KB/cs/dyninvok.aspx
  • 我正在测试一些 C++ 代码,我可以确认 MSTest 确实在测试之间卸载 DLL。它也不调用全局变量析构函数,所以这让我觉得它始终是同一个可执行文件。

标签: .net visual-studio pinvoke mstest


【解决方案1】:

不知道你想用它走多远,但一种解决方案可能是创建你的单元测试主机

http://technet.microsoft.com/fr-fr/query/bb166558

此链接显示了如何创建适配器,您也可以为 evertest 启动一个新进程,创建管道通信并在测试后将其拆除。

我知道 MS 本身使用不同的主机在 moles 下运行测试

http://research.microsoft.com/en-us/projects/pex/molestutorial.pdf

【讨论】:

  • 谢谢!我会检查一下。我没有意识到您可以创建自定义主机。现在我们正在寻找是否有不同的测试运行程序(例如 Gallio Icarus)可以每次在新进程中运行测试。这实际上只是交互式开发和测试时的问题 - 在构建服务器上,我们在一个测试过程中只运行一个测试。
【解决方案2】:

在阅读了 Wiktor 关于 FreeLibrary() 的评论后,我得以完成这项工作。

我使用了由 Mike Stall 创建的 this class,它提供了 LoadLibrary、GetProcAddress 和 FreeLibrary 的包装器。这样,我可以在每次测试运行时加载一次库,调用必要的方法,然后在测试运行结束时释放库。

Mike Stall 的代码使用Marshal.GetDelegateForFunctionPointer,它将非托管函数指针转换为托管委托类型。

我不得不将 [DllImport] 外部声明替换为委托类型的声明。所以我转换了这个:

[DllImport("asesignal.dll")]
public static extern bool ASESDK_Initialize(string licenseCode);

到这里:

public delegate bool ASESDK_Initialize(string licenseCode);

Mike Stall 的代码包含带有泛型委托的示例(Action 等)。但我无法让它工作,所以我创建了自己的委托类型。

我可以像这样动态加载 DLL:

_ht = new UnmanagedLibrary(@"c:\windows\system32\asesignal.dll");

要调用一个函数,我这样做:

var function = _ht.GetUnmanagedFunction<ASESDK_Initialize>("ASESDK_Initialize");
function(licenseCode);

感谢 Wiktor 和 np-hard 的帮助!

【讨论】:

    【解决方案3】:

    VS 2013 及更高版本现在在“测试”>“测试设置”>“保持测试执行引擎运行”下对此进行了设置。取消选中此选项将在每次运行时启动一个新引擎。

    【讨论】:

    • 这似乎没有效果,它仍在 Visual Studio 2013 中为我在同一进程中运行所有测试
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2014-02-06
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多