2011-08-09 46 views
3

作为一名BDD和MSpec初学者,我仍然不太确定与BDD有关的最佳实践和良好习惯,特别是MSpec。MSpec测试可以改进吗?

下面的例子可以改进吗?它是否遵循最佳实践和良好习惯?

  1. 是我的规范类和行为的命名行吗?
  2. 我应该在这种情况下使用行为,还是应该为规范类使用公共基类?
  3. 可以在这里没有Establish吗?
  4. 我应该使用静态工厂方法(TestData方法)来获取测试数据还是应该在规范本身中创建数据?
  5. 而不是测试行为中的每个属性我可以使用result.Equals()但我会测试两件事情,这是不好的,对不对?

请随意重构这个例子,你会说更好。

[Subject(typeof(DataItemReader))] 
public class When_reading_a_DataItem_from_stream 
{ 
    Because of =() => 
    { 
     using (var reader = new DataItemReader(
      new MemoryStream(TestData.GetNormalDataItemAsByteArray()), Encryption.None)) 
     { 
      result = reader.ReadItem(); 
     } 
    }; 

    Behaves_like<DataItemReader_that_reads_correctly> behavior; 

    protected static DataItem result; 
} 

[Subject(typeof(DataItemReader))] 
public class When_reading_a_DataItem_from_encrypted_stream 
{ 
    Because of =() => 
    { 
     using (var reader = new DataItemReader(
      new MemoryStream(TestData.GetNormalDataItemAsByteArrayEncyrpted()), Encryption.Default)) 
     { 
      result = reader.ReadItem(); 
     } 
    }; 

    Behaves_like<DataItemReader_that_reads_correctly> behavior; 

    protected static DataItem result; 
} 

[Behaviors] 
public class DataItemReader_that_reads_correctly 
{ 
    protected static DataItem result; 

    It should_read_the_correct_DataItem =() => 
    { 
     var testItem = TestData.GetNormalDataItem(); 
     result.Property1.ShouldEqual(testItem.Property1); 
     result.Property2.ShouldEqual(testItem.Property2); 
     result.Property3.ShouldEqual(testItem.Property3); 
    }; 
} 

回答

6

这也许少了些什么这个世界的看法的规格和更多的你和你的团队/同行/“人谁也读这个代码后,你”可以从中获益。

从一个开发的角度来看:

  1. 我的外壳和命名遵循什么在代码的可读性。 HTML提取的好处在于最终可以获得可读的规格。我读过的很多内容都着重于全部小写或者类似的内容;不过,我把我的文字描述得非常像你的:适当的,可读的外壳。

  2. 对于这样的一对一行为,行为对于可读性来说是很好的。我使用基类来建立上下文并为重复的常见断言设置期望和行为。

  3. Establish一直意味着“在测试前设置环境”。在你有两个例子,我可能把它改写喜欢:

    Establish context =() => var reader = 
         new DataItemReader(new MemoryStream(  
         TestData.GetNormalDataItemAsByteArray()),        
         Encryption.None)); 
    
    Because of =() => result = reader.ReadItem(); 
    
    Cleanup after =() => reader.Dispose(); 
    

    由于该规范的重点是一个DataItem的“读取”,动作或Because就是这样。再次,优先事项。

  4. 我使用可重复使用的静态工厂,我已经手工创建了存根或者有一个存根/模拟引擎(如FakeItEasy http://code.google.com/p/fakeiteasy/)。在我看来,存根(stub)的内容/创建与实际测试几乎没有关系,应该将存根视为黑匣子(这就是为什么我们要编写测试,对吧?)。

  5. 我专注于每个房​​产单独(如你所知),以确保它们符合我的期望。如果您超过Equals,您可能会检查不属于规范或不相关的属性的平等性。

我不知道有任何管辖“最佳实践”(也有在github上网站的一些技巧:https://github.com/machine/machine.specifications#readme)。我发现通过使用MSpec查看其他项目并观察他们如何处理规范,我的编码风格发生了一些变化。

+0

你可以推荐一些使用MSpec的项目,我可以学习吗? – bitbonk

+0

对于3.我需要在某处调用'reader.Dispose()'。我应该这样做:'因为=()=> try {result = reader.ReadItem(); } finally {reader.Dispose(); }' – bitbonk

+1

关于我的头顶,Fluent NHibernate(https://github.com/jagregory/fluent-nhibernate)使用MSpec。寻找项目的一个好方法可能是打开github并搜索Code/C#和“使用Machine.Specifications”;通过参考找到所有项目。 :) –

相关问题