在UI中执行具有业务逻辑的单元测试数据库应用程序

时间:2010-04-09 16:38:36

标签: c# database unit-testing

我自己管理一个相当大的应用程序(50k +代码行),它管理一些相当重要的业务操作。为了简单描述这个程序,我想说它是一个花哨的UI,能够显示和更改数据库中的数据,它管理着大约1,000个租赁单元,大约3k租户和所有财务。

当我进行更改时,由于代码库太大,我有时会在其他地方破坏某些内容。我通常通过浏览我在功能级别更改的内容来测试它(即我运行程序并通过UI工作),但我无法测试每种情况。这就是我想开始进行单元测试的原因。

但是,这不是一个真正的三层程序,它具有数据库层,业务层和UI层。很多业务逻辑都是在UI类中执行的,很多事情都是在事件上完成的。更复杂的是,一切都是数据库驱动的,我还没有看到(到目前为止)关于如何对数据库交互进行单元测试的好建议。

如何开始使用此应用程序的单元测试是一种好方法。记住。我以前从未做过单元测试或TDD。我是否应该重写它以从UI类中删除业务逻辑(很多工作)?或者有更好的方法吗?

11 个答案:

答案 0 :(得分:16)

我首先要使用一些可以通过UI测试应用程序的工具。有许多工具可用于创建测试脚本,模拟用户点击应用程序。

我还建议您在添加新功能时开始添加单元测试。在开发应用程序后创建完整的覆盖范围非常耗时,但如果您逐步执行此操作,则需要分配工作量。

我们通过使用仅用于单元测试的单独数据库来测试数据库交互。这样,我们就拥有了一个静态和可控的数据集,因此可以保证请求和响应。然后我们创建c#代码来模拟各种场景。我们使用nUnit。

答案 1 :(得分:9)

我强烈建议您阅读文章Working Effectively With Legacy Code。它为您要完成的任务描述了一个可行的策略。

答案 2 :(得分:6)

一个选项是 - 每次出现错误时,编写一个测试来帮助您找到错误并解决问题。使bug在修复bug时通过。然后,一旦错误得到解决,您就有了一个工具,可以帮助您检测可能影响您刚修复的代码块的未来更改。随着时间的推移,您的测试覆盖范围将会得到改善,并且您可以在任何可能发生深远影响的变更时运行不断增长的测试套件。

答案 3 :(得分:6)

TDD意味着您在进行时构建(并运行)单元测试。对于您要做的事情 - 事后添加单元测试 - 您可以考虑使用类似Typemock(商业产品)之类的东西。 此外,您可能已经构建了一个不适合进行单元测试的系统,在这种情况下,可能需要进行一些(或很多)重构。

答案 4 :(得分:5)

首先,我建议您阅读一本关于单元测试的好书,例如The Art Of Unit Testing。在你的情况下,对现有代码执行测试驱动开发有点晚了,但如果你想围绕它编写单元测试,那么这就是我的建议:

  1. 将要测试的代码隔离到代码库中(如果它们尚未存在于库中)。
  2. 写出最常见的用例场景,并将它们转换为使用您的代码库的应用程序。
  3. 确保您的测试程序按预期工作。
  4. 使用测试框架将测试程序转换为单元测试。
  5. 获得绿灯。如果没有,那么你的单元测试是错误的(假设你的代码库工作),你应该做一些调试。
  6. 增加单元测试的代码和方案范围:如果输入意外结果会怎样?
  7. 再次获得绿灯。如果单元测试失败,那么你的代码库可能不支持扩展的场景覆盖,所以它是重构时间!
  8. 对于新代码,我建议你尝试使用测试驱动开发。

    祝你好运(你需要它!)

答案 5 :(得分:5)

我建议选择Michael Feathers的书Working Effectively with Legacy Code。这将向您展示许多技术,可以逐步增加代码库中的测试覆盖率(并在此过程中改进设计)。

答案 6 :(得分:3)

重构是更好的方法。尽管这个过程令人生畏,但您绝对应该将表示和业务逻辑分开。在进行分离之前,您将无法针对您的业务逻辑编写好的单元测试。就这么简单。

在重构过程中,您可能会发现一些您甚至不知道存在的错误,最终会成为一个更好的程序员!

此外,一旦您重构代码,您会发现测试数据库交互将变得更加容易。您将能够编写执行以下操作的测试:“添加新租户”,这将涉及创建模拟租户对象并将“他”保存到数据库。对于下一个测试,您将编写“GetTenant”并尝试从数据库中创建您刚创建的租户并进入内存中表示...然后比较您的第一个和第二个租户以确保所有字段都匹配值。等等。

答案 7 :(得分:0)

我认为将业务逻辑与UI分离始终是一个好主意。这有几个好处,包括更容易的单元测试和可扩展性。您可能还想参考基于模式的编程。这是一个链接http://en.wikipedia.org/wiki/Design_pattern_(computer_science),可以帮助您了解设计模式。

您现在可以做的一件事是,在您的UI类中隔离所有业务逻辑和不同的业务基础功能,而不是在每个UI构造函数或page_load中都有单元测试调用来测试每​​个业务功能。为了提高可读性,您可以在业务功能周围应用#region标记。

为了您的长远利益,您应该研究设计模式。选择适合您项目需求的模式,然后使用设计模式重新设计项目。

答案 8 :(得分:0)

这取决于您使用的语言。但总的来说,从一个简单的测试类开始,它使用一些组成的数据(但仍然是“真实的”)来测试你的代码。让它模拟应用程序中会发生什么。如果您在应用程序的特定部分进行更改,请在更改代码之前编写有效的内容。现在,因为您已经编写了代码,所以在尝试测试整个应用程序时,进行测试将是一个相当大的挑战。我建议从小开始。但是现在在编写代码时,首先编写单元测试然后编写代码。您可能还会考虑重构,但是在整个过程中进行单元测试时,我会权衡重构和重写的成本。

答案 9 :(得分:0)

没有更好的方法来开始单元测试而不是尝试 - 它不需要很长时间,它很有趣且令人上瘾。 但前提是您正在处理可测试的代码

但是,如果您尝试通过修改一个类似于您所描述的应用程序的单元测试来学习单元测试,那么您可能会感到沮丧和气馁 - 并且您很可能只是认为单元测试是一个浪费时间。

我建议下载单元测试框架,例如NUnitXUnit.Net。 这些框架中的大多数都有在线文档,提供了简短的介绍,如NUnit Quick Start。阅读,然后选择一个简单,自包含的类:

  • 对其他类很少或没有依赖 - 至少在复杂类上没有。
  • 有一些行为:一个带有一堆属性的简单容器对单元测试没有太多帮助。

尝试编写一些测试以获得对该类的良好覆盖,然后编译并运行测试。

一旦掌握了这一点,就开始寻找refactor your existing code的机会,特别是在添加新功能或修复错误时。当这些重构导致符合上述标准的类时,请为它们编写一些测试。一旦你习惯了它,you can start by writing tests

答案 10 :(得分:0)

我没有尝试为遗留应用程序添加测试,因为它真的是一项艰难的工作。如果您计划将某些业务逻辑移出UI并在单独的层中,您可以在此处添加初始测试单元(重构和TDD)。这样做将为您介绍如何为您的系统创建单元测试。这真的是很多工作,但我想这是最好的开始。由于它是一个数据库驱动的应用程序,我建议您在创建测试时使用一些模拟工具和DBunit工具来模拟与数据库相关的问题。