使用嵌入式SQL的传统Delphi代码执行TDD的好方法是什么

use*_*264 4 sql delphi testing tdd bdd

我必须使用一些指向数据库的传统Delphi代码,并使其支持具有完全不同模式的新的,更好的数据库.更新的数据库具有相同的数据.它具有存储过程和嵌入式SQL的组合.

是否有一个良好的测试驱动开发技术,将有助于确保我不破坏任何东西?这段代码没有单元测试,我需要对很多硬编码的SQL进行更改.

只是在每次更改后运行听起来都容易出错且耗时.我喜欢做TDD或BDD的想法,只是不知道该怎么做.

Dis*_*ned 11

你想进入单元测试是件好事,但我想提醒你不要过度热心.

将单元测试添加到遗留代码是一项重大任务,并且为了添加测试用例而停止其他工作几乎总是完全不可行.此外,除非您已经拥有TDD经验,否则学习曲线本身可以证明是一个难以克服的障碍.

但是,如果你坚持不懈,一步一步,你的努力最终会得到回报.

您可能遇到的问题:

  • 传统应用程序通常很难与测试用例"重新适应".这是因为代码没有考虑可测试性.
    • 许多例程正在做太多事情,因此测试必须考虑大量的副作用.
    • 代码不是完全独立的,因此为测试设置前提条件是很多工作.
    • 测试/检查行为的入口点经常丢失,因为生产代码不需要它们; 因此,首先没有添加.
    • 代码通常依赖于某个地方的全局状态.直接或通过Singleton's.这个全局状态(无论它在哪里)对您的测试用例造成严重破坏.
  • 数据库的单元测试本质上比其他类型的单元测试更困难.原因是测试用例不喜欢全局状态 - 数据库实际上是全球状态的大量容器.问题在很多方面表现出来:
    • 如果您正在使用IDENTITY列,Auto Inc或任何形式的数字生成器:这些会导致每次测试运行之间产生特定差异,或者您需要一种方法在测试之间重置这些数字.
    • 数据库很慢.一旦构建了大量测试用例,在每次更改之间运行所有测试都是不切实际的.(我的一个Db测试套件需要大约10分钟才能运行.)
    • 如果您的数据库生成日期/时间值,这些也会使测试复杂化.特别是如果数据库在不同的机器上运行.
    • 数据库测试因数据库有两个方面而变得复杂:它的模式和数据.因此,如果您希望测试新的/更改的存储过程(模式的一部分),则需要对数据进行适当的更改,并可能更改模式的其他方面(例如表/视图).
  • 即使没有上述额外的复杂情况,也存在您需要处理的"正常问题".
    • 在一些尴尬的地方,全球国家经常意外地出现.考虑Now()哪个返回TDateTime.它使用全局状态:当前日期时间.如果系统中有基于时间/日期的规则,则这些规则可能会返回不同的结果,具体取决于运行测试的时间.除非你找到一种有效的方法来应对这一挑战,否则你将会遇到一些"不稳定"的测试用例.
    • 编写测试用例是与大多数开发人员习惯的编程范例根本不同的编程范例.打破旧习惯可能非常困难.测试用例代码的风格几乎是声明性的:鉴于,我这样做时,我预计会发生这种情况.测试用例需要简单明了,并且要了解他们想要实现的目标.
    • 学习曲线可能很棘手.如果不熟悉测试用例,最初您可能会发现自己花费3倍的时间来编写代码.即使它最终会有所改善(甚至可能会比以前更快地进行非结构化和随意测试) - 周围的其他人可能会表达挫败感.(如果这是你的老板,那就不酷了.)

希望我没有气馁你,我确实有一些实用的建议:

俗话说"不要咬你的东西,不要咀嚼."
准备开始慢.目前,以您熟悉的方式继续进行大部分工作.但强迫自己每天写1或2个测试用例.随着你越来越舒服,你可以增加这个数字.

尝试坚持"久经考验的原则"
TDD工作流程是:首先编写测试并确保测试失败.我知道很难坚持这个习惯,但这个原则是一个非常重要的目的.这是一个确认您的测试用例证明错误/缺失功能的程度.我经常看到测试用例代码会在有/无生产变化的情况下通过 - 使测试有点无用.

对于数据库测试,您需要建立一个适合您的框架.
首先,您需要一种将数据库置于"基态"的机制.所有测试都应该通过的测试 - 无论是什么顺序或运行多少次.通常,这将涉及测试之间的某种重置(但它需要非常快).其次,您需要一种简单的方法来将数据库的架构更新为生产代码所期望的.

最初,您只想测试新功能或错误修复.
避免测试一切的诱惑.随着时间的推移,您的测试用例覆盖率会增加 一旦您的框架和模式建立起来,那么您可能有机会开始添加测试以增加覆盖率.

重构现有代码.
随着您对测试的熟悉,您将了解使测试更加困难的编码习惯.您可能会在遗留代码中发现许多此类问题.这样的代码不会被测试.您甚至可以在测试之前重构代码.显然这并不理想,因为你宁愿总是通过测试来证明你的改变没有破坏任何东西.一本关于重构的好书将为您提供一些可以使用的技术,这些技术将改变代码的结构而不改变其行为.

测试现有代码.
在为现有例程编写测试时,请查看代码并确定可能影响不同行为的每个输入.例如,当有if语句时,某些东西会导致条件评估为True,而其他条件则为 False.至少,您需要对每个排列进行测试.


Ale*_*xSC 2

在你的位置,我将使用DUnit创建一个单元测试项目。对于每个实体,我都会编写测试方法来运行旧的和新的句子,然后编写方法来比较结果。

\n\n

我将编写一个名为 TTestCase 的类,让\xc2\xb4s 说TMyTestCase,并向其中添加一些辅助方法,然后将我的新测试类创建为TMyTestCase 的子类。

\n\n

祖先类的想法是提供通用功能,使编写测试(例如比较方法)变得更容易,以提高生产力和舒适度。

\n