该系统仅用PL / sql编写,由数千个表,数百个存储过程包组成,主要从表获取数据和/或插入/更新其他数据.
我们的扩展不是例外.大多数函数通过许多相互约束的表从相当复杂的SELECT语句返回数据(在返回它们之前有一点添加的逻辑),或者从一个复杂的数据结构转换到另一个复杂的数据结构.
现有代码库没有单元测试.为了使事情变得更糟,只有包,触发器和视图是源控制的,表结构(包括“alter table”的东西以及通过除版本控制之外的通道进行必要的数据转换).在项目范围内无法改变这一点.
维护测试数据集似乎是不可能的,因为每周都会部署到生产环境中的新代码,通常没有事先通知,通常会更改数据结构(在此添加一列,删除一个).
我很高兴有任何建议或参考来帮助我们.一些团队成员往往厌倦了解如何从单元测试开始我们的经验并不涵盖PL / sql数据密集型遗留系统(只有那些“从书本”的绿色Java项目).
QCTO带有GUI,这意味着像其他Quest产品即TOAD一样,它只是Windows.它并不能完全自动化测试数据生成,但它提供了一个支持它的接口.也像其他Quest产品一样,QCTO虽然有免费软件副本,但仍然获得许可.
史蒂文(披露,他是我的Oracle英雄之一)已经编写了所有PL / sql测试工具的功能比较.显然,QOTC出来了,但我认为比较是诚实的. Check it out.
关于测试仪器在utplsql的建议
管理单元测试的测试数据可能是颈部真正的痛苦.不幸的是,utplsql不能承担很大的负担.所以
>始终测试已知值:
>避免使用dbms_random;
>尝试将序列的使用限制在其值无关紧要的列中;
>日期也很棘手.避免硬编码日期:使用用sysdate填充的变量.学习欣赏add_months(),last_day(),interval,trunc(sysdate,’MM’)等
>隔离其他用户的测试数据.从头开始构建它.尽可能使用独特的值.
>只需要创建尽可能多的测试数据.体积测试是不同的责任.
>当测试程序更改数据时,为每个单元测试创建特定的记录.
>另外:不要依靠一个测试的成功输出来提供来自另一个测试的输入.
>当适当时,在单元测试之间简单地报告数据共享记录的测试程序.
>尽可能共享框架数据(例如引用的主键).
>使用自由文本字段(名称,描述,注释)来确定哪些测试或测试使用该记录.
>最小化创建新记录所涉及的工作:
>仅为测试套件和表的约束分配必需的值;
>尽可能使用默认值;
>尽可能地程序化.
其他事情要记住:
>设置测试夹具可能是一个耗时的练习.如果您有大量数据,请考虑构建一个过程来设置可以在每个会话中运行一次的静态数据,并在ut_setup本身中仅包含volatile数据.这在测试只读功能时特别有用.
>记住,创建测试数据是一个编程练习本身,并且容易出现错误.
>使用utplsql的所有功能.当推断出易失性数据的值时,utAssert.EqQuery,utAssert.EqQueryValue,utAssert.EqTable,utAssert.EqTabCount和utAssert.Eq_RefC_Query都是非常有用的功能.
>当诊断测试运行时,我们不希望使用这些数据是有用的.所以考虑在ut_setup开始时有一个空心的ut_teardown过程并清除测试数据.
处理遗留代码
评论加里的帖子让我想起了另一件你可能会觉得有用的事情. Steven F写了ulplsql作为JUnit的PL / sql实现,JUnit是Test First运动的Java先锋.然而,TDD的技术也可以应用于大量的遗留代码(在这种情况下,遗留代码是没有任何单元测试的任何程序集).
要牢记的关键是,您不必立即将所有内容都进行单元测试.逐步开始.构建新产品的单元测试,Test First.在应用更改之前,对要更改的位进行单元测试,以便您在进行更改后仍然可以工作.
在这方面有很多想法,但是(不可避免地,如果可耻),它主要来自OO程序员.迈克尔·羽毛是主要的章节.阅读他的文章Working Effectively With Legacy Code.如果你觉得有用,他随后写了一本同名的书.