【问题标题】:best way to run multi-threaded nunit tests运行多线程 nunit 测试的最佳方法
【发布时间】:2008-12-09 13:27:46
【问题描述】:

我目前正在尝试寻找解决方案,如果测试方法产生的线程中发生异常,如何确保测试失败。

我不想就单元测试中的多个线程展开讨论。 => "单元测试".Replace("unit","integration");

我已经在几个论坛上阅读了很多帖子,我知道CrossThreadTestRunner,但我正在寻找一个集成到nunit中的解决方案,并且不需要重写很多测试。

【问题讨论】:

    标签: multithreading unit-testing nunit


    【解决方案1】:

    非测试线程(即其他衍生线程)上的异常不会导致测试失败的原因是 NUnit 默认配置为使用legacyUnhandledExceptionPolicy,这是一个可以通过应用程序应用的 .Net 进程级别设置.config,即:

    <legacyUnhandledExceptionPolicy enabled="1"/>
    

    启用此设置(即设置为“1”)会导致主线程上未发生的异常被忽略

    我写了一篇文章,详细介绍了 ReSharper 测试运行程序的这个问题,但它同样适用于 NUnit 测试运行程序: https://web.archive.org/web/20101006004301/http://gojisoft.com/blog/2010/05/14/resharper-test-runner-hidden-thread-exceptions/)

    ReSharper 测试运行器 - 隐藏线程异常

    蒂姆·劳埃德,2010 年 5 月 14 日下午 4:31

    我们在 GojiSoft 使用 ReSharper 测试运行程序来运行 NUnit 测试 从 Visual Studio 中。这是一个很棒的测试跑步者,但不玩 与可能发生异常的多线程组件很好 非测试线程。非测试线程上未处理的异常被隐藏 和应该失败的测试,而不是通过。

    ...

    问题在于 ReSharper 测试运行器是 配置为与 .Net 1.0 和 1.1 应用程序的行为方式相同,其中 非主线程上未处理的异常被吞下。情况 从 .Net 2.0 改进,其中所有未处理的异常都变平了 过程。然而,微软不得不允许现有的 .Net 1.0 和 1.1 应用程序在新的 .Net 框架上表现得像以前一样的选项。他们 引入了 app.config 设置:legacyUnhandledExceptionPolicy。

    ReSharper 测试运行程序默认配置为使用 .Net 1.0 和 1.1 策略,所以如果有未处理的非测试线程异常 它不会冒泡并导致测试失败——测试通过, 而我们得到的是误报。

    如果非测试线程上的未处理异常导致测试失败,则 必须更新 ReSharper 测试运行器的 app.config。

    ...

    1. 通过编辑 legacyUnhandledExceptionPolicy 关闭旧的未处理异常策略:&lt;legacyUnhandledExceptionPolicy enabled="0" /&gt;

    2. 现在多线程测试在非测试线程上引发异常时会按预期失败:

    买家小心……

    对此有一个警告。非测试线程的异常现在将 扁平化测试运行器和测试套件执行将在以下情况下停止 他们发生了。这与失败的正常测试运行形成对比 测试被标记为失败,测试运行器继续。 ...

    【讨论】:

    • 这对我不起作用,测试仍然通过。但它确实像文章所说的那样扼杀了测试。
    【解决方案2】:

    我也遇到了同样的问题,我的解决方案是捕获异常并增加一个异常计数器,因此 Test 方法只需断言异常计数器为 0 以确认没有线程发生异常。

    删除特定环境内容后,我的测试代码的摘录:

        const int MaxThreads = 25;
        const int MaxWait = 10;
        const int Iterations = 10;
        private readonly Random random=new Random();
        private static int startedThreads=MaxThreads ;
        private static int exceptions = 0;
    

    [Test]
        public void testclass()
        {
            // Create n threads, each of them will be reading configuration while another one cleans up
    
            Thread thread = new Thread(Method1)
            {
                IsBackground = true,
                Name = "MyThread0"
            };
    
            thread.Start();
            for (int i = 1; i < MaxThreads; i++)
            {
                thread = new Thread(Method2)
                {
                    IsBackground = true,
                    Name = string.Format("MyThread{0}", i)
                };
    
                thread.Start();
            }
    
            // wait for all of them to finish
            while (startedThreads > 0 && exceptions==0)
            {
                Thread.Sleep(MaxWait);
            }
            Assert.AreEqual(0, exceptions, "Expected no exceptions on threads");
        }
    
        private void Method1()
        {
            try
            {
                for (int i = 0; i < Iterations; i++)
                {
                // Stuff being tested
                    Thread.Sleep(random.Next(MaxWait));
                }
            }
            catch (Exception exception)
            {
                Console.Out.WriteLine("Ërror in Method1 Thread {0}", exception);
                exceptions++;
            }
            finally
            {
                startedThreads--;
            }
        }
    
        private void Method2()
        {
            try
            {
                for (int i = 0; i < Iterations; i++)
                {
                    // Stuff being tested
                    Thread.Sleep(random.Next(MaxWait));
                }
            }
            catch (Exception exception)
            {
                Console.Out.WriteLine("Ërror in Method2 Thread {0}", exception);
                exceptions++;
            }
            finally
            {
                startedThreads--;
            }
        }
    

    【讨论】:

      【解决方案3】:

      我通过为 nunit 创建一个插件解决了这个问题,它“安装”了一个 ITestDecorator。

      【讨论】:

      • 答案如何?
      • 请提供一些信息,说明您为使其发挥作用所做的工作。这根本不是问题的答案。
      • @Martin Moser 请详细说明
      猜你喜欢
      • 2010-12-04
      • 2016-09-13
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 1970-01-01
      相关资源
      最近更新 更多