6

我是 xUnit.NET 框架的忠实粉丝。我发现它轻巧、简单、干净且可扩展。

现在假设我有这样的课程:

public class AdditionSpecification
{
  static int result;

  public void Because()
  {
    result = 2 + 2;
  }

  public void Result_is_non_zero()
  {
    Assert.True(result <> 0);
  }

  public void Result_is_correct()
  {
    Assert.Equal(4, result);
  }
}

对于上面的测试类,我希望 xUnit.NET 查看 2 个测试用例并在每个测试用例之前运行因为()方法。

撇开您可能对我的类或方法名称、此测试/规范的结构、xUnit.NET 框架或 BDD 有任何问题,这是我的问题:

如何告诉 xUnit.NET 我想自定义它如何识别和执行此类之外的测试方法,而不在每个目标测试方法上使用自定义 [Fact] 类属性?

我知道我可以从 BeforeAfterAttribute 派生来用自定义的执行前后装饰每个测试方法。我怎样才能在课堂上做到这一点?我必须编写自定义跑步者吗?

4

2 回答 2

10

xUnit.net 的 IUseFixture 允许您进行每个夹具设置。因此,您可以定义自己的夹具类:

public class AdditionFixture : IDisposable
{
  public int Because() 
  {
    return 2 + 2;
  }

  public void Dispose()
  {
   //test tear down code
  }      
}

然后您的测试类可以实现它(使用 setFixture 需要实现):

public class AdditionSpecification : IUseFixture<AdditionFixture>
{
  int result;

  public void SetFixture(AdditionFixture Fixture)
  {
   result = Fixture.Because();
  }

  [Fact]
  public void Result_is_non_zero()
  {
   Assert.True(result <> 0);
  }

  [Fact]
  public void Result_is_correct()
  {
   Assert.Equal(4, result);
  }
}

xUnit 运行器将创建一个夹具实例,并在运行每个测试之前将其传递给 SetFixture。运行所有测试后,如果它实现了 IDisposable,则运行器将处理该夹具。我希望这会有所帮助!

codeplex 上的 xUnit wiki 提供了更多信息,包括一个很好的示例,说明如何实现 IUseFixture 来为您的测试装置管理数据库连接。

于 2009-06-01T21:27:15.367 回答
10

所以事实证明我正在寻找 ITestClassCommand.EnumerateTestMethods() 方法。

  1. 默认的 xUnit.NET 测试运行程序将遍历测试程序集中的所有类。
  2. 对于每一个,它将检查一个 RunWithAttribute;这是您覆盖用于识别包含测试的方法的 ITestClassCommand 实现的机会。(RunWithNUnit 就是一个很好的例子)
  3. 调用 ITestClassCommand.EnumerateTestMethods() 来处理测试类并返回测试方法的 IEnumerable。
  4. 然后将每个测试 IMethodInfo 传递给 ITestClassCommand.EnumerateTestCommands(IMethodInfo testMethod) 以获取 ITestCommands 的 IEnumerable
  5. 然后执行每个 ITestCommand 并有机会返回结果。

在我上面的例子中,我需要类似的东西:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RunWithMyTestClassCommandAttribute : RunWithAttribute
{
   public RunWithMyTestClassCommandAttribute()
               : base(typeof(MyTestClassCommand)) {}
}

然后我可以装饰我上面的例子:

[RunWithMyTestClassCommand]
public class AdditionSpecification
{
  static int result;

  public void Because()
  {
    result = 2 + 2;
  }

  public void Result_is_non_zero()
  {
    Assert.True(result <> 0);
  }

  public void Result_is_correct()
  {
    Assert.Equal(4, result);
  }
}

最后,在 MyTestClassCommand 中,我有机会在 EnumerateTestMethods() 和 EnumerateTestCommands(IMethodInfo testMethod) 之间使用我想要定位的任何逻辑并构造 ITestCommand 实例,这些实例作为单独的测试执行。

顺便说一句,在研究这个问题的过程中,我在 xUnit.NET 框架中遇到了一个小错误,其中由 EnumerateTestMethods() 生成的自定义 IMethodInfo 从未出现在 EnumerateTestCommands(..) 中,因为它正在被测试解包和重新包装亚军或它的工厂之一。

将此问题提交给 codeplex 上的 xUnit 项目,并于2009年 5 月 30 日更正了 xUnit.NET 1.5 CTP 2

于 2009-06-08T20:13:17.860 回答