【问题标题】:NUnit global initialization - bad idea?NUnit 全局初始化 - 坏主意?
【发布时间】:2011-04-06 21:24:16
【问题描述】:

我们的测试套件中需要一些全局一次性设置代码。我们可以做不止一次,但这需要相当长的时间。

  • 所有灯具都需要它,所以[TestFixtureSetUp] 不起作用。它必须在所有[TestFixtureSetUp] 代码之前运行。

  • 把它放在Main() 中,因为我们将测试程序集保存为可执行文件。但是Main 不会在 GUI 客户端下执行。

  • 仅当您引用我们不赞成在每个类中都这样做的类时,才能使用静态构造函数创建单独的类进行初始化。

  • 从基类继承所有测试夹具并向其添加静态构造函数会导致对初始化代码的多次调用。

现在鉴于情况,我有两个问题:

1) NUnit 不支持“全局设置”是不是一个非常糟糕的主意?

2) 实现这一目标最不痛苦、最常见的方法是什么?

【问题讨论】:

  • 顺便说一句,对于那些想知道的人,MBUnit 支持“AssemblyFixture”类,其夹具设置代码在每个程序集中运行一次。我知道我的问题是关于 NUnit,但任何正在考虑切换的人也应该考虑这一点。

标签: .net unit-testing nunit


【解决方案1】:

[设置夹具]

这是标记一个类的属性,该类包含给定命名空间下所有测试装置的一次性设置或拆卸方法。

SetUpFixture 中的 SetUp 方法在其命名空间中包含的任何固定装置之前执行一次。 TearDown 方法在所有夹具执行完毕后执行一次。

程序集范围的初始化。如果您不将类放在任何命名空间中,它将应用于程序集中的所有测试。

例如。

// using statements

[SetUpFixture]
public class GlobalSetup {
  [SetUp]
  public void ShowSomeTrace() {
    Trace.WriteLine("It works..."); // won't actually trace
  }
}

http://www.nunit.org/index.php?p=setupFixture&r=2.4

【讨论】:

  • 哦,我以为 SetUpFixtureTestFixtureSetUp 是同一个东西,一个被弃用了。这就是答案,谢谢!
  • 它在文档中说明了这一点,但要明确指出......如果您根本不将此类放入命名空间,它将用于“程序集范围”设置/拆卸。
  • @GregB 我已将您的评论添加到实际答案中,干杯。
  • @GregB 非常感谢!您的小评论比我为解决我的问题而阅读的几十个线程/文章更有帮助:)
  • 从 nUnit 3 开始,SetUpFixture 中没有使用 [SetUp] 属性,上面的代码会抛出异常。而是使用 [OneTimeSetUp] 和 [OneTimeTearDown]。 github.com/nunit/docs/wiki/SetUpFixture-Attribute
【解决方案2】:

从 NUnit 3.0 开始,Setup 属性在标有 SetUpFixture 属性的类中不再受支持。当前有效的语法是:

  [SetUpFixture]
  public class MySetUpClass
  {
    [OneTimeSetUp]
    public void RunBeforeAnyTests()
    {
      // ...
    }

    [OneTimeTearDown]
    public void RunAfterAnyTests()
    {
      // ...
    }
  }

SetUpFixture 中的 OneTimeSetUp 方法在任何操作之前执行一次 包含在其命名空间中的固定装置。 OneTimeTearDown 方法 在所有的fixture执行完毕后执行一次。

Current SetUpFixture documentation page

【讨论】:

  • 感谢加博!将已接受的答案更改为您的答案,以便其他人可以轻松找到它。
【解决方案3】:

正如我的评论中所述,您可以通过使用位于程序集级别的 SetUpFixture 来实现程序集范围的初始化。我需要这个来关闭默认跟踪侦听器上的 UI:

[SetUpFixture]
public class AssemblySetup
{
    [SetUp]
    public void Setup()
    {
        var traceListener = Debug.Listeners.Cast<TraceListener>().FirstOrDefault(listener => listener is DefaultTraceListener) as DefaultTraceListener;

        if (traceListener != null)
            traceListener.AssertUiEnabled = false;
    }
}

有关程序集或命名空间设置的更多信息:http://www.nunit.org/index.php?p=setupFixture&r=2.4

注意:正如其他人所指出的,不要使用它来破坏测试之间的隔离。

【讨论】:

    【解决方案4】:

    不幸的是,我认为没有一种好的内置方式来实现它 - 可能是因为 NUnit 主要用于单元测试,并且您不需要任何全局设置来进行单元测试(一切都应该是在每个测试夹具中本地模拟)。

    然而,使用 NUnit 进行集成测试是很常见的,并且有一个全局设置是很常见的 - 就像你的情况一样。这里有一些合理的选择:

    1. 在我当前的项目中,我们通常在运行测试的 msbuild 脚本中进行。好处是您在编写新测试时不需要记住任何特殊设置。缺点 - 从 IDE 运行测试时,您必须确保所有内容都已设置好。

    2. 如果以上不是一个选项,您可以使用最后一个想法 - 从公共基类继承测试。然后,基类可以引用一个单例类(您可以找到即 Jon Skeets 关于如何实现单例的文章),这将进行设置。这样它只会运行一次。

    【讨论】:

    • 我想在默认跟踪侦听器上将“AssertUIEnabled”设置为 false,这样如果代码堆栈中某处的断言失败,我就不会收到弹出窗口。这是我想做一次的事情,我希望它在所有测试中都发生。
    • 我正在测试一个使用 ActiveRecord 的 MVC3 应用程序,我需要在运行所有测试之前对其进行一次初始化——这对于一个好的用例来说怎么样? :)
    【解决方案5】:

    1) 我想这取决于上下文。我从来不需要在任何项目上进行全局设置,但我可以想象场景,例如一个只读取数据的应用,以及一个通用的全局数据设置。

    2) 您可以进行全局设置,例如在您提到的夹具基础中,有状态。 IE。在执行之前检查 HasRun 属性等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-18
      • 1970-01-01
      • 2017-06-17
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多