我来自Java世界,并且主要使用JUnit,现在在表达使用NUnit 3进行测试的某些方面时遇到了一些问题。在JUnit中,每个测试都创建自己的测试类实例,因此完全可以创建一些测试类。测试类中的实例变量,在@Before
方法中进行设置,测试方法和帮助者可以自由访问这些变量,而不必担心它们会被并行运行的其他测试所覆盖,并且@After
会破坏测试数据很好。使用NUnit时,它无效,并且SetUp
和TearDown
方法在这种情况下似乎没有用,因为在测试方法调用之间重用了测试治具实例,因此测试治具类的字段可以(并被测试方法的每次调用所覆盖(我的类有几个测试方法,并且每个方法都会生成多个测试用例,因此在一次测试运行中有数十个调用)。
我不知道如何解决此问题。在我的场景中,设置将创建一个临时文件夹,该文件夹将用作以下测试用例的工作文件夹。拆除后将删除临时文件夹,并清除通过测试方法创建的所有中间文件。但是现在,当SetUp
在实例字段中创建并存储一个临时文件夹路径(以便可以由测试逻辑以及一些比较复杂的断言和验证器读取)时,此类字段的值将被并行运行的测试用例覆盖。我考虑了几种方法:
实现一个IDisposable
,它代表每个测试的上下文,并在每个测试方法中用using
括起来-我不喜欢这个主意,因为我不喜欢这个主意IDisposable
用作资源管理工具之外的其他工具,并将IDisposable
与using
组合起来,就像对这种特定语言功能的滥用一样,模拟了对我的设置/清除气味,
创建一个方法,该方法接受代表实际测试逻辑的委托,并调用自定义SetUpTestCase
/ TearDownTestCase
方法。该方法将调用设置,然后测试委托,然后将其删除。我对这种方法不满意的是,它不能与接受参数的测试方法配合使用-以特定方式参数化的每组测试方法都需要相应的委托类型。同样,这似乎与NUnit的精神以及使用属性描述测试方法的方式背道而驰-毕竟,为什么要将测试的主要逻辑委托给任何东西? [Test]
或[TestCase]
方法不是实际测试吗?
也许有某种方法可以使用NUnit的更高级方面,例如动作或某些回调/触发器/等等,我实在是太无经验了。我特别想念的是将数据从设置方法(例如,由它创建的临时文件夹的路径)传输到随后的测试方法的方法。我不能为此使用实例字段,并且我不知道是否存在任何“标记”结构可以在测试生命周期的不同阶段调用的方法之间传递特定于测试的数据?
通常,SetUp
和TearDown
属性对我来说似乎毫无用处,如果它们不能在没有立即被另一个并行运行的测试用例立即覆盖其结果的情况下设置测试用例。我在这里想念什么?
如何使用NUnit来实现这种基于测试的案例,范围内的设置/拆卸行为?我做错了什么,或者我想念什么?
答案 0 :(得分:0)
正如您所建立的,在调用OneTimeSetUp
之前,实例化了一次TestFixture类。然后针对每个测试运行一组SetUp
,Test
和TearDown
;最后是OneTimeTearDown
。
如果要并行运行测试(这不是默认设置),则必须指定Parallelizable Attribute。无论是否执行此操作,独立编写测试都是一个好主意,因此它们不会彼此冲突-它们需要结构化。
AAA(排列,行为,声明)模式是构造被测方法的单元测试的常用方法。如果您的测试要并行运行,则TestFixture字段不适合保存在并行测试之间可能会冲突的信息,就像在多线程类中不适合使用这种方式一样。
我建议在TestFixture中使用私有方法来设置临时文件夹-它需要某种方式来提供唯一的文件夹名称,以便并行测试不会相互作用-也许使用Guid或CallerMemberName作为文件夹名称的一部分,然后返回文件夹名称。
应从测试的“安排”部分调用此方法。然后,您需要尝试一下...最后包装其余的Test,以确保文件夹被拆除。或者,您也可以采用IDisposable的想法-我认为这没有什么问题:这样做的全部目的是确保在超出范围时确保整理资源(包括托管和非托管资源)。
如果您使用lambda表达式而不是严格定义的委托,那么您对代理的第二建议也可以-lambda表达式可以从包含范围中捕获变量。