使用不同的数据模型进行测试

本文关键字:测试 数据模型 | 更新日期: 2023-09-27 18:13:41

我的许多类级别单元测试加载数据模型并执行各种类级别测试。然而,大部分业务逻辑依赖于模型中的数据。因此,我的类级别测试看起来像这样:

 public class TestFoo
 {
     // Data model
     Model _myDataModel; 
     // Class under test
     Foo _foo;
     [Setup] 
     public void Initialize()
     {
         // Create data model
         _myDataModel = new Model();
         _myDataModel.Load();   // Loads the file
         // Create the class under test
         _foo = new Foo();
     }
     [TearDown]
     public void Dispose()
     {
     }
     [Test]
     public void TestFooCase1()
     {
         // Code for test case that tests _foo and uses the data model  
     }
 } 

然而,我想用两个或更多的数据模型运行我的大部分测试,即我需要在setup方法中调用_myDataModel.LoadModelX()_myDataModel.LoadModelY()

我想到的一种方法是在测试用例中实例化模型,如下所示,但是这需要在每个测试用例中调用load方法。

[Setup] 
public void Initialize()
{       
    // Create the class under test
    _foo = new Foo();
}
[TearDown]
public void Dispose()
{
}
// Use TestCase to specify the model as an argument for each test case  
[TestCase(modelX)]
[TestCase(modelY)]
public void TestFooCase1(string modelName)
{
    // Create data model
    _myDataModel = new Model();
    _myDataModel.Load(modelName);   // New method which loads the specific model 
    // Code for test case that tests _foo and uses the data model       
}   

我认为必须有一个更好的方法可能通过定义我自己的属性或扩展NUnitTestFixture。我对其他的想法很感兴趣。

使用不同的数据模型进行测试

您可以为您希望测试的每个模型组合设置一个属性,然后使用ValueSource属性传入已加载的模型。像这样

private static IEnumerable<Model> ModelsToTest
{
  get
  {
    Model x = new Model();
    x.Load("X");
    yield return x;
    Model y = new Model();
    y.Load("Y");
    yield return y;
  }
}
[Test]
public void TestFooCase1([ValueSource("ModelsToTest")] Model model)
{
  // Code for test case that tests _foo and uses the data model       
} 

很多业务逻辑依赖于模型中的数据

考虑到我建议为每个模型特定情况创建单独的测试,并且不要将不同的模型混合到单个测试夹具中。

BTW,将Dispose()方法重命名为TearDown(),因为Dispose直观地与Dispose模式实现(IDisposable)相关联,所以这把事情搞乱了,因为你只做常规的NUnit ЕearDown阶段,它清楚地由属性[TearDown]标识。

我不喜欢设置和拆卸,因为我想要测试方法中呈现的信息。因此,我更喜欢在测试中创建所有的testdata,并且我发现在测试方法中创建测试对象是必不可少的。

我喜欢的是用于创建testdata的构建器模式。

public class DataModelBuilder
{  
  string _modelName; 
  IDataModel _dataModel; 
  public DataModelBuilder WithModelName(string modelName)
  {
    _modelName = modelName; 
    return this; 
  }
  public IDataModel Build()
  {
    _dataModel = new DataModel(); 
    _datamodel.Load(_modelName); 
    return _dataModel; 
  }
}
在测试方法中,创建模型的语法将是:
IDataModel _model = new DataModelBuilder().WithNewName("modelY").Build(); 

在测试用例中显示与测试用例相关的所有信息的好处是,漂亮而清晰的一行创建复杂的测试数据。我不希望这些信息隐藏在setup方法中。

注意,与mock结合使用,构建器会变得更加强大。

我不喜欢[Setup], [TearDown]属性这样声明下一个类:

class DisposableList : List<IDisposable>, IDisposable
{
    public Dipose()
    {
        foreach (var x in this) x.Dispose();
    }
}

并使用它:

[Test...]
public void MyTest()
{
    using (NewContext(...))
    {
        // perform test here
    }
}
private static NewContext(...)
{
    var list = new DisposableList();
    // add anything here
    return list;
}

好处:

  • 您可以在单个测试或类中多次初始化测试状态(调用NewContext())
  • 你可以用不同的值初始化测试状态,例如NewContext((x) => x.LoadY())