基于TDD的领域对象层对象提取方法研究

2018-05-15 08:31姚远张樊黄玉兰
软件导刊 2018年4期
关键词:测试用例

姚远 张樊 黄玉兰

摘 要:目前云系统服务端存在着各类分层模型架构,尽管这些分层架构通常有所差异,但始终存在着领域对象层(Domain Object Layer)。领域对象层中的对象对真实世界里的业务及角色进行抽象与映射,封装了现实世界中的关键业务过程与实体状态。因此,如何建立云服务领域对象层是面向对象开发方法中的关键部分。测试驱动开发(Test Driven Development ,简称TDD)作为一种软件开发方法,使用一组单元测试用例作为软件开发的基础与手段,意在使软件开发过程始终不偏离软件的主要功能,以实现敏捷开发。提出一种基于TDD进行领域对象层的对象提取、构建领域对象层的方法,并通过实例对该方法进行验证。验证结果显示,构建的领域对象层粒度精细,识别准确、完整。

关键词:TDD;测试用例;领域对象层;对象识别;软件建模;云系统

DOI:10.11907/rjdk.172548

中图分类号:TP301

文献标识码:A 文章编号:1672-7800(2018)004-0036-03

Abstract:There are various layered model structures in the present cloud system server. Although in general these structures are different they all have domain object layer (DOL). The objects in DOL are the abstraction and reflection of operation and roles in the real world and they encapsulate the key operational process and entity status. Therefore how to establish DOL is the key part of the whole development. This paper uses test-driven development(TDD) as the software development method in which a group of unit test samples are employed as the basis to ensure basic users' needs to be met and agile development to be accomplished in the whole development process. It is proposed to do object extraction based on TDD and establish DOL. The test confirms that the logic objects in the established DOL are in very tiny particle size with accurate and complete recognition.

Key Words:TDD; test samples; domain object layer; object recognition; software model design; cloud system

1 TDD用于發现领域逻辑对象原理

软件开发过程由面向过程开发转向面向对象开发已有将近20年历史,面向对象开发方法已经走过了简单对象封装、分组对象域、按功能职责分层进行对象划分的历程[1-2]。软件组成部分不再是简单地按功能切分,而是按照业务领域的业务过程及角色识别出相应对象,通过这些对象独立使用或相互协作组成相应的软件功能模块。

面向对象分析、设计与开发已由最初的粗粒度简单对象封装,演化出几种成熟的分层对象设计模型。受C/S(客户/服务器)、N-Tier(多层架)、B/S架构、SOA(面向服务架构)等软件开发架构的影响,以及多种开发语言进化的推动,面向对象的软件一般可按3~5个逻辑层次划分[3-6]。以一般云系统提供的服务端软件架构为例,软件层次如图1所示。

其中领域实体层是层次架构中的核心层,业务领域的所有关键业务均由相应领域实体完成,同时由于领域实体是现实世界中人、物的抽象,只要是属于该业务领域的专家即能对领域实体进行问题分析,这就为现实需求理解和软件功能实现之间搭建了一座很好的桥梁。领域对象模型的建立也为软件功能实现带来了极大好处,由于领域内业务流程容易发生变化,但领域对象却相对变化较小,所以通过先识别领域对象层,进而构建整个软件层次对象模型,可以大大降低软件的升级和维护成本。

一般有两种方法实现领域实体层中的领域对象建模:①由UML统一建模过程提出的传统方法进行识别,这种方法要求在软件需求获取阶段使用用例图捕捉用户需求,并根据用例图中的名词、行为等进行领域实体识别;②由数据库的ER模型导出底层数据库结构,再由数据库的ER模型直接向上扩展为相应的领域实体模型。

在上述两种领域对象建模方法中,前者要求自顶向下进行面向对象设计,要求一开始就有一个宏大而全局的软件架构,这对于软件设计者把握架构与系统分析能力都提出了较高要求,而后者则由传统的CS架构体系转化而来,先做好数据库设计再由数据表映射出领域实体。这种方式实际上是一种由面向过程开发向面向对象的过渡方式,由于数据库先于领域实体设计出来,所以软件开发不得不向已经成形的数据库架构倾斜,使软件后续设计遭遇掣肘。因此,本文提出TDD构建领域对象的方法。

TDD全称为Test Driven Development,意即测试驱动开发。它是近几年根据软件开发体系极限编程(XP Programming)和敏捷开发(Agile Programming)发展而来的一种开发实践[7]。

TDD要求使用一组单元测试用例作为软件开发的起点。它实际上是一种迭代的软件开发过程,在每一次软件迭代开发过程中,开发者首先需要根据软件功能撰写一组测试用例,这组用例需要覆盖所有要求开发的功能。根据这组测试用例,即可确定所需开发的功能集合,而且必定也是能够满足用户需求的最小功能集合。同时,由于每次迭代开发均由测试用例先导,即使用户需求有大的变更,也可以根据需要重新编写测试用例,并进行功能开发。而这种重新编写所花费的人力与时间成本相比于上述两种传统方法开发,有效性大大提升[8-10]。

2 通过TDD提取领域对象层的方法

在实际开发中,使用TDD结合面向对象分层开发设计技术,取得了良好效果。首先将系统划分为服务层、业务逻辑层、领域对象层、持久化层、底层数据库等层次。在实际开发过程中,主要进行领域对象的创建,再由它向上扩展出业务逻辑层和服务层软件对象,向下借助O/R Mapping工具得到相应的持久化层对象及数据库表。在实际开发过程中,针对每个用户需求写出一个测试用例。使用Java的JUnit框架对生成的测试用例进行自动测试。测试用例的写法与普通Java类似,只是每个作为测试用例的方法加上[test]注记,以使该方法的JUnit框架可以进行自动调用。在测试用例中可以使用Assert类检查测试结果,比较实际结果与期望结果的差别。当每个测试方法的结果不符合预期时,该测试用例即被认为没有通过,此时开发者必须修改代码,以通过该测试用例。

2.1 领域对象基本结构识别

通过将需求分解为测试用例中的期望值与期望结果,可以很直观地找到相应的领域对象。通过需求功能编写测试用例,测试用例将直观表达出用户需求的各种数据,由這些数据发现领域对象。一般的领域对象都会有创建、修改、检索、删除的操作(一般被称为CRUD操作)。因此,对于一个已定义出的领域对象,可以创建4个测试用例,分别对应这4种操作。为了使这几个测试用例通过单元测试,它们的属性和方法必须满足测试用例中的调用。因此,根据测试用例获得的领域对象也可以获得所需定义的属性与方法,因而得到了相应领域对象的基本结构。

2.2 发现领域实体间的联系

当进行测试用例编写时,根据需求编写测试用例,会发现领域实体间有很强的联系。继续从测试用例中发现新的实体。

2.3 发现用于规则约束与取值范围的实体类

在定义领域实体时,对于规则约束与取值范围的考虑是一个重要内容,属于系统基础架构的一部分。通过撰写某一领域实体的CRUD测试用例,可以将一个类的属性上升为另一个独立的类。

根据对每个测试用例的相关操作,可以完整地定义出领域实体层中所有规则约束与取值范围的类。

2.4 领域实体层提取

通过撰写覆盖需求的测试用例代码,利用IDE的自动化测试工具和代码生成工具,可以很快构建出领域实体层的领域实体、由于在测试用例中已对需要的领域实体的属性和方法进行了定义,因此可以很快地构建出对应领域实体类的框架代码,然后直接实现领域实体类的属性,最后实现领域对象的方法体。由于针对每个领域实体,已经有对应的一组CRUD测试用例。因此,该领域对象的方法实现可以被立即验证其功能的正确性。

3 通过TDD提取领域实体层的方法验证

如用户的需求为:需要将一份合同保存下来,合同信息需要保存日期、签订甲方、签订乙方、合同款项、支付方式、标的物名称。则相应的测试用例为:

[test]

void canCreateContract(){

Contract newcontract = new Contract ();

newcontract.signdate = newdate;

newcontract.PartyA = “湖北晨星公司”;

newcontract.PartyB = “万琪公司”;

newcontract.TradeItem = “房屋装修”;

newcontract.Money = 2000000.00;

newcontract.PayMethod = ”银行转帐”;

Repository repos = Repository.getInstance();

int count = repos.getObjectCount(Contract.class);

repos.saveObject(newcontract);

Assert.assertNotEqual(newcontract.ID, null);

Assert.assertEqual(newcontract.SerialNo, 0);

Assert.assertEqual(count+1,repos,getObjectCount(Contract.class));

}

由该测试用例可得到两个领域实体类Contract与Repository,进一步设计CRUD测试用例,得到其属性与方法。可获得Contract与Repository类所需要定义的属性与方法,也因此得到相应领域对象的基本结构。

设计测试用例发现实体间的联系,比如需要满足需求“每份装修施工合同必须记录每个房间的面积、使用材质以及所需施工时间”,可发现新的领域实体类、合同明细类ContractItem。

根据规则约束与取值范围继续设计测试用例,则可以保证“银行转帐”、“现金”等之外不合法的数据被测试用例识别。得到新的实体类、交易方式类TradeMethod。

根据以上步骤,可以快速得出领域对象层的软件类,实现系统功能。图2是根据上述测试用例设计实现的领域对象层静态结构图。

猜你喜欢
测试用例
基于SmartUnit的安全通信系统单元测试用例自动生成
浅析基于因果图法软件测试用例的设计
基于MBD模型自动生成测试用例的软件测试方法
基于混合遗传算法的回归测试用例集最小化研究
基于需求模型的航天软件测试用例生成方法
基于依赖结构的测试用例优先级技术
电动汽车整车控制软件测试用例设计方法及应用
软件测试用例执行优化研究
浅析软件测试用例管理
软件回归测试用例选取方法研究