基于模型开发测试

在 Microsoft Visual Studio 旗舰版 中,可以使用需求模型和体系结构模型来帮助组织系统及其组件的测试。这种做法有助于确保测试对用户和其他利益干系人非常重要的需求,且有助于您在需求发生更改时快速更新测试。如果使用 Microsoft 测试管理器,还可以维护模型与测试之间的链接。

系统和子系统测试

“系统测试”也称为“验收测试”,意即测试是否满足用户的需求。这种测试关注系统的外部可见行为而非内部设计。

扩展或重新设计系统时,进行系统测试非常重要。系统测试有助于您避免在更改代码时引入 Bug。

如果计划对系统进行任何更改或扩展,则从现有系统上运行的一组系统测试着手非常有帮助。然后可以扩展或调整测试以测试新需求,对代码进行更改,并重新运行完整的测试集。

如果要开发新系统,则在开始进行开发时就可以开始创建测试。通过在开发每项功能之前定义测试,您可以按照非常具体的方式捕获需求讨论。

子系统测试对系统的主要组件应用相同的原则。每个组件独立于其他组件进行测试。子系统测试关注组件的用户界面或 API 上的可见行为。

有关如何运行测试的更多信息,请参见测试应用程序

从需求模型派生系统测试

可以在系统测试和需求模型之间创建并维护一种关系。若要建立这种关系,您需要编写与需求模型的主要元素对应的测试。Visual Studio 旗舰版允许您在测试和模型部件之间创建链接,从而帮助您维护这种关系。有关需求模型的更多信息,请参见用户需求建模

Dd409381.collapse_all(zh-cn,VS.110).gif为每个用例编写测试

如果您使用的是 Microsoft 测试管理器,则可以为在需求模型中定义的每个用例创建一组测试。例如,如果您具有“订餐”用例(包括“创建订单”和“添加订单项”),则可以为这些用例创建总体测试和更详细的测试。有关用例的更多信息,请参见 UML 用例图:准则

以下准则可能会有所帮助:

  • 每个用例应具有多个测试,用于获得主要路径和异常结果。

  • 描述需求模型中的用例时,与详细描述用户为实现目标需遵循的过程相比,定义用例的后置条件(即实现的目标)更重要。例如,“订餐”的后置条件可以是餐馆正在为顾客准备餐点和顾客已付款。后置条件是测试应验证的条件。

  • 使单独测试基于后置条件的单独子句。例如,创建单独测试以在有订单时通知餐馆并向顾客收取款项。此分离具有以下好处:

    • 需求的不同方面通常独立发生更改。按这种方法将测试分成不同方面,可以在需求发生更改时更方便地更新测试。

    • 如果开发计划逐个实现用例的方面,则您可以随着开发的进展单独启用测试。

  • 设计测试时,请将测试数据的选择与确定是否已实现后置条件的代码或脚本分离。例如,一个简单算术函数的测试可能为:输入 4;验证输出为 2。实际上,设计的脚本如下:选择一个输入;将其本身乘以输出,然后验证结果为原始输入。此样式允许您在不更改测试主体的情况下改变测试输入。

Dd409381.collapse_all(zh-cn,VS.110).gif将测试链接到用例

如果您使用测试管理器设计并运行测试,则可以在需求、用例或用户情景工作项下组织测试。您可以将这些工作项链接到模型中的用例。这样您便可以快速跟踪测试的需求更改,并有助于您跟踪每个用例的进度。

将测试链接到用例

  1. 在 测试管理器 中,创建一个需求并使测试套件基于该需求。若要了解如何执行此操作,请参见针对产品积压工作项、用户情景或要求创建测试

    所创建的需求是 Team Foundation Server 中的工作项。它可以是用户情景、需求或用例工作项,具体取决于项目在 Team Foundation 中使用的过程模板。有关更多信息,请参见计划和跟踪项目

  2. 将需求工作项链接到模型中的一个或多个用例。

    在用例图中,右击一个用例,然后单击**“链接到工作项”**。有关更多信息,请参见链接模型元素和工作项

  3. 添加到测试套件(即验证用例的测试用例)。

通常,每个用户情景或需求工作项将链接到模型中的多个用例,且每个用例将链接到多个用户情景或需求。这是因为,每个用户情景或需求包括一组开发多个用例的任务。例如,您可以在项目的早期迭代中开发基本用户情景,客户可以从用户情景的目录中选择项并进行提交。在后期迭代中,情景可以是用户在完成订单时支付的款项以及供应商在发送货物后收到的金额。每个情景都向“订货”用例的后置条件中添加一个子句。

可以将后置条件的子句写入用例图上的单独注释,从而创建从需求到这些子句的单独链接。可以将每个注释链接到需求工作项,并将注释链接到关系图上的用例。

Dd409381.collapse_all(zh-cn,VS.110).gif使测试基于需求类型

需求模型的类型(即类、接口和枚举)依据用户对其业务的考虑和传达方式来描述概念和关系。不包括仅与系统的内部设计有关的类型。

根据这些需求类型设计您的测试。这种做法有助于确保在讨论需求更改时,可以容易地将这些更改与测试中的必要更改相关。这样,能够与最终用户和其他利益干系人直接讨论测试及其预期结果。这意味着可以在开发过程外部维护用户的需求,并避免无意中围绕设计中的可能缺陷设计测试。

对于手动测试,此做法包括遵循测试脚本中的需求模型的词汇。对于自动测试,此做法包括使用需求类图作为测试代码的基础,以及创建取值函数和 updater 函数以将需求模型链接到代码。

例如,需求模型可能包括“菜单”、“菜单项”、“订单”类型以及这些类型之间的关联。此模型表示由订餐系统存储和处理的信息,不表示实现该信息的复杂性。在工作系统中,数据库、用户界面和 API 中的每个类型都可能有数种不同的实现。在分布式系统中,每个实例的多种变体可能同时存储在系统的不同部件中。

若要测试用例(例如“添加订单项”),测试方法可能包括类似下面的代码:

Order order = … ; // set up an order
// Store prior state:
int countBefore = order.MenuItems.Count; 
// Perform use case:
MenuItem chosenItem = …; // choose an item
AddItemToOrder (chosenItem, order); 
// Verify part of postcondition:
int countAfter = order.MenuItems.Count;
Assert (countAfter == countBefore = 1); 

请注意,此测试方法使用需求模型的类。关联和特性作为 .NET 属性实现。

若要实现此目的,必须将类的属性定义为只读函数或取值函数,这些函数访问系统以检索有关其当前状态的信息。模拟用例的方法(例如 AddItemToOrder)必须通过其 API 或通过其用户界面下的层驱动系统。测试对象(例如订单和菜单项)的构造函数也必须驱动系统,以在系统内部创建相应项。

可以通过应用程序的正常 API 使用多个取值函数和 updater 函数。但是可能需要编写一些附加函数才能启用测试。这些附加取值函数和 updater 函数有时称为“测试检测”。由于这些函数依赖于系统的内部设计,因此,系统开发人员的职责就是提供这些函数,而测试人员则根据需求模型编写测试代码。

编写自动测试时,可以使用一般测试包装取值函数和 updater 函数。有关更多信息,请参见创建使用一般测试运行可执行文件的自动测试

Dd409381.collapse_all(zh-cn,VS.110).gif业务规则测试

某些需求不与任何一个用例直接相关。例如,DinnerNow 业务允许顾客从多个菜单中选择,但要求每个订单中所有选择的项都应来自一个菜单。可以将此业务规则表示为有关需求类模型中的订单、菜单和项之间的关联的固定规则。

此类型的固定规则不仅控制当前定义的所有用例,而且控制将在以后定义的任何其他用例。因此,独立于任何用例编写此规则并独立于用例单独进行测试非常有用。

可以作为类图中的注释编写固定业务规则。有关更多信息,请参见 UML 类图:准则

通过将注释链接到需求或用户情景工作项(可将该工作项链接到 测试管理器 中的测试套件),可以将测试链接到业务规则。有关更多信息,请参见将测试用例附加到模型元素。

可以在用例图、活动图或序列图的注释中说明性能和其他服务质量要求。您也可以将这些注释链接到需求工作项及其测试套件。

Dd409381.collapse_all(zh-cn,VS.110).gif测试的序列图和活动图

如果需求模型或体系结构模型包括序列图或活动图,则您可以编写密切遵守这些关系图的测试。

设计这样的测试有时很有用:通过关系图中的分支和循环动态选择不同路径。

尝试在验证每个消息或操作之后验证系统的状态。这可能需要进行其他检测。

从模型派生子系统测试

在大型系统的高级设计中,可以标识组件或子系统。这些组件或子系统表示可以单独设计、或位于不同计算机上或者是可通过多种方式重新组合的可重用模块的部件。有关更多信息,请参见 UML 组件图:准则

您可以对每个主要组件与完整系统应用相同的原则。在大型项目中,每个组件都可以具有其自己的需求模型。在较小的项目中,可以创建体系结构模型或高级设计以显示主要组件及其交互。有关更多信息,请参见建立软件系统体系结构模型

在任何一种情况下,您都可以按照将在需求模型和系统测试之间建立关系的相同方式,在模型元素和子系统测试之间建立一种关系。

Dd409381.collapse_all(zh-cn,VS.110).gif使用提供的接口和所需的接口隔离各个组件

标识组件对系统的其他部件或外部服务具有的所有依赖项,并将这些依赖项表示为所需的接口非常有用。此练习通常导致需要重新进行某些设计,这可使组件更易于分离,且可以与设计的其余部分轻松分离。

此分离的一个优点是,可以通过将 mock 对象替换为组件通常使用的服务来执行组件以进行测试。这些组件是为实现测试目的而设置的组件。mock 组件提供您的组件所需的接口,以响应使用模拟数据的查询。mock 组件构成完整测试工具的部件,您可以将测试工具连接到组件的所有接口。

mock 测试的优点是您可以在自己的组件将使用其服务的其他组件仍在开发时,开发自己的组件。

维护测试与模型之间的关系

在每隔几周执行一次迭代的典型项目中,在每次迭代快开始时都要检查需求。会议讨论将在下一次迭代中提交的功能。可以使用需求模型帮助讨论概念、方案和将要开发的操作序列。业务利益干系人设置优先级,开发人员进行估算,测试人员确保正确实现每项功能的预期行为。

编写测试是定义需求的最有效方法,也是确保人员明确所需内容的有效方法。但是,虽然在具体研讨会期间需要很长时间才能编写测试,但是可以更快速地创建模型。

从测试的角度来看,可以将需求模型看做是测试的简略形式。因此,在整个项目中维护测试和模型之间的关系非常重要。

将测试用例附加到模型元素

如果您的项目使用 测试管理器,则您可以将测试链接到模型中的元素。这样您便可以快速找到受需求中的更改影响的测试,并且可帮助您跟踪需求的实现程度。

您可以将测试链接到所有类型的元素。下面是一些示例:

  • 将用例链接到执行它的测试。

  • 在链接到用例的注释上编写用例后置条件或目标的子句,然后将测试链接到每个注释。

  • 在类图或活动图上的注释中编写固定规则,然后将这些注释链接到测试。

  • 将测试链接到活动图或单个活动。

  • 将测试套件链接到它测试的组件或子系统。

将测试链接到模型元素或关系

  1. 在 测试管理器 中,创建一个需求并使测试套件基于该需求。若要了解如何执行此操作,请参见针对产品积压工作项、用户情景或要求创建测试

    所创建的需求是 Team Foundation Server 中的工作项。它可以是用户情景、需求或用例工作项,具体取决于项目在 Team Foundation 中使用的过程模板。有关更多信息,请参见计划和跟踪项目

  2. 将需求工作项链接到模型中的一个或多个元素。

    在建模图中,右击一个元素、注释或关系,然后单击**“链接到工作项”**。有关更多信息,请参见链接模型元素和工作项

  3. 添加到测试套件(即验证模型元素中表示的需求的测试用例)。

请参见

概念

开发软件设计模型

用户需求建模

建立软件系统体系结构模型

建立应用程序模型