3、一次测试太多的项目
看看下面的单元测试,请在不使用“和”这个词的情况下描述它:
01.[TestMethod]
02.public void ProductPriceTests()
03.{
04. // Arrange
05. var product = new Product()
06. {
07. BasePrice = 10m
08. };
09.
10. // Act
11. decimal basePrice = product.CalculatePrice(CalculationRules.None);
12. decimal discountPrice = product.CalculatePrice(CalculationRules.Discounted);
13. decimal standardPrice = product.CalculatePrice(CalculationRules.Standard);
14.
15. // Assert
16. Assert.AreEqual(10m, basePrice);
17. Assert.AreEqual(11m, discountPrice);
18. Assert.AreEqual(12m, standardPrice);
19.}
我只能这样描述这个方法:
“测试中计算基价,打折价和标准价是都能否返回正确的值。”
这是一个简单的方法来判断你是否一次测试了过多的内容。上面这个测试会有三种情况导致它失败。如果测试失败,我们需要去找到那个/哪些出了错。
理想情况下,每一个方法都应该有它自己的测试,例如:
01.[TestMethod]
02.public void CalculateDiscountedPriceReturnsAmountOf11()
03.{
04. // Arrange
05. var product = new Product()
06. {
07. BasePrice = 10m
08. };
09.
10. // Act
11. decimal discountPrice = product.CalculatePrice(CalculationRules.Discounted);
12.
13. // Assert
14. Assert.AreEqual(11m, discountPrice);
15.}
16.
17.[TestMethod]
18.public void CalculateStandardPriceReturnsAmountOf12()
19.{
20. // Arrange
21. var product = new Product()
22. {
23. BasePrice = 10m
24. };
25.
26. // Act
27. decimal standardPrice = product.CalculatePrice(CalculationRules.Standard);
28.
29. // Assert
30. Assert.AreEqual(12m, standardPrice);
31.}
32.
33.[TestMethod]
34.public void NoDiscountRuleReturnsBasePrice()
35.{
36. // Arrange
37. var product = new Product()
38. {
39. BasePrice = 10m
40. };
41.
42. // Act
43. decimal basePrice = product.CalculatePrice(CalculationRules.None);
44.
45. // Assert
46. Assert.AreEqual(10m, basePrice);
47.}
注意这些非常具有描述性的测试名称。如果一个项目里有500个测试,其中一个失败了,你能根据名称就能知道哪个测试应该为此承担责任。
这样我们可能会有更多的方法,但换来的好处是清晰。我在《代码大全(第2版)》里看到了这句经验之谈:
为方法里的每个IF,And,Or,Case,For,While等条件写出独立的测试方法。
驱动测试开发纯粹主义者可能会说每个测试里只应该有一个断言。我想这个原则有时候可以灵活处理,就像下面测试一个对象的属性值时:
01.public Product Map(ProductDto productDto)
02.{
03. var product = new Product()
04. {
05. ID = productDto.ID,
06. Name = productDto.ProductName,
07. BasePrice = productDto.Price
08. };
09.
10. return product;
11.}
我不认为为每个属性写一个独立的测试方法进行断言是有必要的。下面是我如何写这个测试方法的:
01.[TestMethod]
02.public void ProductMapperMapsToExpectedProperties()
03.{
04. // Arrange
05. var mapper = new ProductMapper();
06. var productDto = new ProductDto()
07. {
08. ID = "sp-001",
09. Price = 10m,
10. ProductName = "Super Product"
11. };
12.
13. // Act
14. Product product = mapper.Map(productDto);
15.
16. // Assert
17. Assert.AreEqual(10m, product.BasePrice);
原文转自:http://www.vaikan.com/top-5-tdd-mistakes/