首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在执行集成测试时将坏COM组件( 10.0)与.Net应用程序隔离

如何在执行集成测试时将坏COM组件( 10.0)与.Net应用程序隔离
EN

Stack Overflow用户
提问于 2010-07-19 02:41:07
回答 1查看 1.8K关注 0票数 4

我目前正在开发一些基于.Net的软件(.Net Framework3.5 SP1),该软件通过其COM客户端API (通常称为TDApiOle80或TDApiOle80.TDConnection)与HP 10.0集成。

我们使用的是XUnit 1.6.1.1521和Gallio3.1.397.0(从msbuild文件调用)

我们经历了一个过程:

创建connection

  • Running的
  • --关闭connection
  • Disposing
  • Forcing a GC.Collection() / GC.AwaitingPendingFinalizers()

的测试

对于每个集成测试--而且每个集成测试都是在实际情况下配置的超时运行的。

我们的问题是,它出现在几个测试(大约10个左右)之后,质量中心无限期地阻止当调用-和整个加里奥冻结,并将不再作出反应。

最初,我们发现xunit.net只在事实中将超时应用于代码,因此它将无限期地等待构造函数或dispose方法的完成,因此我们将该逻辑移到测试的主体中,以确认.但这并没有解决问题(在运行一定数量的测试后仍将挂起)。

在使用TestDriven.Net时也会发生同样的情况--可以以交互方式运行1或几个测试,但超过10个测试和整个运行冻结--我们唯一的选择是终止TD.Net使用的ProcessInvoation86.exe进程。

有没有人有任何技巧/技巧来阻止这种情况的发生,或者至少让我的集成测试远离这类问题--这样QC API的测试就会无限期地阻塞,测试就会在超时的情况下失败,并允许Gallio转到下一个测试。

更新

使用STA线程的提示有助于将问题向前推进一点--通过自定义的XUnit.Net属性,我们现在在它自己的STA线程中启动测试。这阻止了Gallio/TestDriven.Net完全锁定,因此我们可以包括在hudson构建服务器上运行集成测试。

代码语言:javascript
运行
复制
    public class StaThreadFactAttribute : FactAttribute
    {
        const int DefaultTime = 30000; // 30 seconds

        public StaThreadFactAttribute()
        {
            Timeout = DefaultTime;
        }

        protected override System.Collections.Generic.IEnumerable<Xunit.Sdk.ITestCommand> EnumerateTestCommands(Xunit.Sdk.IMethodInfo method)
        {
            int timeout = Timeout;

            Timeout = 0;

            var commands = base.EnumerateTestCommands(method).ToList();

            Timeout = timeout;

            return commands.Select(command => new StaThreadTimeoutCommand(command, Timeout, method)).Cast<ITestCommand>();
        }
    }

    public class StaThreadTimeoutCommand : DelegatingTestCommand
    {
        readonly int _timeout;
        readonly IMethodInfo _testMethod;

        public StaThreadTimeoutCommand(ITestCommand innerComand, int timeout, IMethodInfo testMethod)
            : base(innerComand)
        {
            _timeout = timeout;
            _testMethod = testMethod;
        }

        public override MethodResult Execute(object testClass)
        {
            MethodResult result = null;

            ThreadStart work = delegate
                                                    {
                                                        try
                                                        {
                                                            result = InnerCommand.Execute(testClass);
                                                            var disposable = testClass as IDisposable;
                                                            if (disposable != null) disposable.Dispose();
                                                        }
                                                        catch (Exception ex)
                                                        {
                                                            result = new FailedResult(_testMethod, ex, this.DisplayName);
                                                        }
                                                    };

            var thread = new Thread(work);

            thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA

            thread.Start();

            if (!thread.Join(_timeout))
            {
                return new FailedResult(_testMethod, new Xunit.Sdk.TimeoutException((long)_timeout), base.DisplayName);
            }

            return result;
        }
    }

相反,在使用TestDriven.Net运行测试时,我们会看到这样的输出--顺便说一句,运行同一个套件会导致所有测试都通过,或者通常只有1到2个测试失败。在第一次故障之后,第二次故障导致了“卸载应用程序域时出错”的问题。

测试'IntegrationTests.Execute_Test1‘失败:测试执行时间超过:3000ms

测试'T:IntegrationTests.Execute_Test2‘失败:卸载应用程序域时出错。(来自HRESULT: 0x80131015的异常) System.CannotUnloadAppDomainException:在卸载appdomain时出错。( HRESULT: 0x80131015除外)在Xunit.Runner.TdNet.TdNetRunner.TestDriven.Framework.ITestRunner.RunMember(ITestListener侦听器、程序集、MemberInfo成员的Xunit.ExecutorWrapper.Dispose()的System.AppDomain.Unload(AppDomain域)上,在TestDriven.TestRunner.ThreadTestRunner.Runner.Run()上,ITraceListener traceListener,String assemblyPath,String testPath)

4次传球,2次失败,0次跳转,用了50.42秒(xunit)。

我还没有确定为什么Quality会被无限期地随机挂起--不久将进一步调查这个问题。

更新27/07/2010

我终于确定了绞刑的原因--以下是有问题的代码:

代码语言:javascript
运行
复制
connection = new TDConnection();
connection.InitConnectionEx(credentials.Host);
connection.Login(credentials.User, credentials.Password);
connection.Connect(credentials.Domain, credentials.Project);
connection.ConnectProjectEx(credentials.Domain, credentials.Project, credentials.User, credentials.Password);

显然,调用Connect后接ConnectProjectEx有可能阻塞(但它是不确定的)。删除冗余连接调用似乎极大地提高了测试的稳定性--正确的连接代码:

代码语言:javascript
运行
复制
connection = new TDConnection();
connection.InitConnectionEx(credentials.Host);
connection.ConnectProjectEx(credentials.Domain, credentials.Project, credentials.User, credentials.Password);

继承了代码基之后,我没有对连接代码进行过多的考虑。

有一件事我还没有弄清楚,为什么即使有上面包含的超时代码,Thread.Join(超时值)也不会返回。您可以附加调试器,它只显示测试线程处于连接/等待操作中。也许与STA线程中的执行有关吗?

EN

Stack Overflow用户

回答已采纳

发布于 2010-07-19 02:48:06

您可以尝试在单独的线程上运行代码,然后在新线程上使用超时调用Join,并在到达超时时中止它。

例如:

代码语言:javascript
运行
复制
static readonly TimeSpan Timeout = TimeSpan.FromSeconds(10);
public static void RunWithTimeout(ThreadStart method) {
    var thread = new Thread(method);
    thread.Start();
    if (!thread.Join(Timeout)) {
        thread.Abort();
        Assert.False(true, "Timeout!");
}
票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3278155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档