并行运行单元测试的启示

发表于:2012-3-08 13:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:捷道    来源:51Testing软件测试网采编

  在我们的单元测试中,大多数测试需要访问的资源都是在内存中进行,但有一部分单元测试必须与数据库通信,对数据表进行读写。除了极少数特殊的测试用例外,对数据表的操作都放在事务中进行,并在执行完毕后,通过回滚事务,避免对真实数据的提交,保证单元测试不会影响数据库。

  注:单元测试应该访问数据库吗?这其实还有待确认。在《修改代码的艺术》一书中,Feathers这样写道:

  单元测试运行得快。运行得不快的不是单元测试。

  有些测试容易跟单元测试混淆起来。譬如下面这些测试就不是单元测试:

  (1)跟数据库有交互;

  (2)进行了网络间通信;

  (3)调用了文件系统;

  (4)需要你对环境作特定的准备(如编辑配置文件)才能运行的。

  以上可以看到Feathers的态度是单元测试不应与外部资源进行交互。显然,如果出现了这些交互,就应该采用Mock的方式来模拟对外部资源的访问。然而,某些实现功能却是与外部资源息息相关,又或者我们测试的目的本身就是验证对外部资源的访问是否正确。从测试的范围来看,它们仍然算是单元测试,但因其特殊性,而应该将这些测试放到系统测试的范畴。在持续集成中,我们常常用金字塔来表示单元测试、系统测试和集成测试的数量。如下图所示:

  单元测试的数量最多,如果还需要访问外部资源,就会严重影响运行单元测试的速度。关于单元测试、Mock等内容,我希望在以后的文章里详细论述。

  在我们的项目中,是通过注入Fixture的形式生成测试数据。例如,我们可能希望注入Client、Associate等对象,从而完成对某些行为的测试。例如:

[Fixture(typeof(client_hastings))]
public Client client;

[Fixture(
typeof(Samuel))]
public Associate Samuel;

  通过Fixture准备数据时,如果采用了持久化方式,则意味着需要对数据表进行操作。如上代码就可能操作多张表,例如对Client表和Associate表进行写操作。由于单元测试采用并行方式进行。假设存在两个单元测试均需要对Client和Associate注入Fixture,生成测试数据;并且不幸的是,这两个测试用例准备数据的顺序刚好相反,即A测试用例的顺序为Client->Associate,B测试用例的顺序为Associate->Client,就可能发生死锁。

  为什么?让我们分析数据库发生死锁的情况。它必然是多个进程(或线程)对两个或两个以上的资源形成了交叉访问。例如进程A在占有了资源1的同时,还需要访问资源2;与此同时,进程B在占有了资源2的同时,需要访问资源1。由于资源1已经被进程A占用,无法释放,进程B就会等待;而进程A希望访问的资源2又被等待中的进程B持有;二者互不相让,最终产生死锁。这正是并行运行单元测试导致死锁的根本原因。我们可以运行SQL Server Profiler来监视数据库的执行。注意,倘若需要跟踪死锁的情况,需要在Trace Properties中勾选“Deadlock Graph”和“Lock: Deallock”选项,如下图所示:

32/3<123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号