在处理类和查找测试方法时,扩展xUnit.NET以使用自定义代码

Dav*_*ert 5 c# xunit.net extending

我是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);
  }
}
Run Code Online (Sandbox Code Playgroud)

对于上面的测试类,我希望xUnit.NET能够看到2个测试用例,并在每个测试用例之前运行Since()方法.

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

我怎样才能告诉xUnit.NET我想要自定义如何在使用每个目标测试方法的自定义[Fact]类似属性的情况识别和执行此类的测试方法?

我知道我可以从BeforeAfterAttribute派生出来,在执行前后使用自定义装饰每个测试方法.我怎样才能在班级做到这一点?我必须写一个自定义跑步者吗?

Ben*_*enA 10

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

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

  public void Dispose()
  {
   //test tear down code
  }      
}
Run Code Online (Sandbox Code Playgroud)

然后,您的测试类可以实现此功能(需要实现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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

codeplex上的xUnit wiki有更多信息,包括如何实现IUseFixture来管理测试夹具的数据库连接的一个很好的例子.

  • 感谢您尝试提供帮助,但此回复并没有回答我提出的问题;我如何根据一些约定告诉 xUnit.NET 我想要执行哪些方法而不使用 [Fact] 属性。 (2认同)

Dav*_*ert 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)) {}
}
Run Code Online (Sandbox Code Playgroud)

然后我可以用以下内容装饰我上面的例子:

[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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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