真实业务环境中的 TDD(C#,无 ASP.NET,SQL 服务器)
TDD in Real Business Environment (C#, NO ASP.NET, SQL Server)
我想让自己尽可能矮:
第一:我看了相关的帖子,但帮助不大。
参见:What is a quality real world example of TDD in action?
或:How do you do TDD in a non-trivial application?
或者:TDD in ASP.NET MVC: where to start?
背景:
- 我不是一个完全的 TDD 初学者,我知道原理
- 我读过 Rob C Martin 和 MC Feathers 等
- TDD 在保龄球和 TicTacToe 游戏中对我来说效果很好
但是当我想在我的工作场所进行 TDD 时,我有点迷茫。这与模拟无关,我有点知道如何模拟依赖项。
还有:
- 我什么时候编码什么?
- 我从哪里开始?
- 以及:何时以及如何实施 "database" 或 "file system" 代码。模拟它很酷,但在集成测试阶段我需要 id 作为真实代码。
想象一下(示例):
- 编写一个程序,从数据库中读取所有客户的列表。
- 与客户 ID 相关,它必须从 csv/Excel 文件中搜索数据。
- 然后业务逻辑对它施展魔法。
- 最后将结果写入数据库(不同table)。
我从未找到过这样的应用程序的 TDD 示例。
编辑:
作为程序员,您将如何以 TDD 风格实现此示例?
PS: 我不是在谈论 db 单元测试或 gui 单元测试。
想想你正在测试什么行为,并用它来驱动一个更高级别的测试。然后,当您实现此功能时,使用 TDD 在您需要实现此功能的 classes 中实现您想要的行为。
在您的示例中,我将从一个简单的无操作情况开始。 (我将用 BDD 语言编写它,但您可以类似地用代码实现它)
Given there are no customers in the database
When I read customers and process the related data from the csv file
Then no data should be written to the database
这种测试将允许您获得一些基本功能和接口,而无需在您的模拟中实现任何东西(除了可能检查您没有调用代码来完成最终写入)
然后我将继续讨论一个稍微宽泛的示例
Given there are some customers in the database
But none of these customers are in the CSV file
When I read customers and process the related data from the csv file
Then no data should be written to the database
而且我会不断增加并调整执行此操作所需的 classes,最初可能使用模拟,但最终会使用真实的数据库交互。
不过,我会谨慎地为每个 class 编写测试。这会使您的测试变得脆弱,并且每次您进行像更改这样的小重构时,它们都需要更改。关注行为,而不是实施
你的流程应该是这样的:
您完全可以在没有数据库的情况下开始。用最基本的方法编写一个接口来检索客户
public interface ICustomerHandler
{
List<Customer> GetCustomers(int customerId);
}
然后,使用您的模拟框架模拟该接口,同时为将使用和引用接口实现的方法编写测试。根据需要一路创建新的 classes(例如客户),这会让您考虑需要哪些属性。
[TestMethod()]
public void CreateCustomerRelationsTest()
{
var manager = new CustomerManager(MockRepository.GenerateMock<ICustomerHandler>());
var result = manager.CreateCustomerRelations();
Assert.AreEqual(1, result.HappyCustomers);
Assert.AreEqual(0, result.UnhappyCustomers);
}
编写这个虚假测试会告诉您需要什么 class,例如 CustomerManager class,它有一个方法 CreateCustomerRelations 和两个属性。该方法应引用接口中的 GetCustomer 方法,使用在 class 构造函数中注入的模拟实例。
只做足够的事情来构建项目并让您 运行 第一次测试,这将失败,因为被测试的方法中没有逻辑。但是,让测试决定您的方法应该采用哪个输入,以及它应该接收和断言什么输出,您已经有了一个良好的开端。首先定义测试条件有助于您创建良好的设计。很快您将编写足够的代码来确保测试确认您的方法设计良好并且按照您希望的方式运行。
我想让自己尽可能矮:
第一:我看了相关的帖子,但帮助不大。
参见:What is a quality real world example of TDD in action?
或:How do you do TDD in a non-trivial application?
或者:TDD in ASP.NET MVC: where to start?
背景:
- 我不是一个完全的 TDD 初学者,我知道原理
- 我读过 Rob C Martin 和 MC Feathers 等
- TDD 在保龄球和 TicTacToe 游戏中对我来说效果很好
但是当我想在我的工作场所进行 TDD 时,我有点迷茫。这与模拟无关,我有点知道如何模拟依赖项。
还有:
- 我什么时候编码什么?
- 我从哪里开始?
- 以及:何时以及如何实施 "database" 或 "file system" 代码。模拟它很酷,但在集成测试阶段我需要 id 作为真实代码。
想象一下(示例):
- 编写一个程序,从数据库中读取所有客户的列表。
- 与客户 ID 相关,它必须从 csv/Excel 文件中搜索数据。
- 然后业务逻辑对它施展魔法。
- 最后将结果写入数据库(不同table)。
我从未找到过这样的应用程序的 TDD 示例。
编辑: 作为程序员,您将如何以 TDD 风格实现此示例?
PS: 我不是在谈论 db 单元测试或 gui 单元测试。
想想你正在测试什么行为,并用它来驱动一个更高级别的测试。然后,当您实现此功能时,使用 TDD 在您需要实现此功能的 classes 中实现您想要的行为。
在您的示例中,我将从一个简单的无操作情况开始。 (我将用 BDD 语言编写它,但您可以类似地用代码实现它)
Given there are no customers in the database
When I read customers and process the related data from the csv file
Then no data should be written to the database
这种测试将允许您获得一些基本功能和接口,而无需在您的模拟中实现任何东西(除了可能检查您没有调用代码来完成最终写入)
然后我将继续讨论一个稍微宽泛的示例
Given there are some customers in the database
But none of these customers are in the CSV file
When I read customers and process the related data from the csv file
Then no data should be written to the database
而且我会不断增加并调整执行此操作所需的 classes,最初可能使用模拟,但最终会使用真实的数据库交互。
不过,我会谨慎地为每个 class 编写测试。这会使您的测试变得脆弱,并且每次您进行像更改这样的小重构时,它们都需要更改。关注行为,而不是实施
你的流程应该是这样的:
您完全可以在没有数据库的情况下开始。用最基本的方法编写一个接口来检索客户
public interface ICustomerHandler
{
List<Customer> GetCustomers(int customerId);
}
然后,使用您的模拟框架模拟该接口,同时为将使用和引用接口实现的方法编写测试。根据需要一路创建新的 classes(例如客户),这会让您考虑需要哪些属性。
[TestMethod()]
public void CreateCustomerRelationsTest()
{
var manager = new CustomerManager(MockRepository.GenerateMock<ICustomerHandler>());
var result = manager.CreateCustomerRelations();
Assert.AreEqual(1, result.HappyCustomers);
Assert.AreEqual(0, result.UnhappyCustomers);
}
编写这个虚假测试会告诉您需要什么 class,例如 CustomerManager class,它有一个方法 CreateCustomerRelations 和两个属性。该方法应引用接口中的 GetCustomer 方法,使用在 class 构造函数中注入的模拟实例。
只做足够的事情来构建项目并让您 运行 第一次测试,这将失败,因为被测试的方法中没有逻辑。但是,让测试决定您的方法应该采用哪个输入,以及它应该接收和断言什么输出,您已经有了一个良好的开端。首先定义测试条件有助于您创建良好的设计。很快您将编写足够的代码来确保测试确认您的方法设计良好并且按照您希望的方式运行。