为服务虚拟化增添生命力:有状态和状态转换测试
在服务虚拟化中,创建现实的虚拟服务的关键部分是确保服务具有状态行为,以便可以在测试运行之间保留其状态。但是极限是什么?模拟何时会成为过多的模拟?在这篇文章中,了解状态转换测试以及如何知道何时需要它。
为了加速功能测试,至关重要的是必须不受限制地访问可信赖的现实测试环境。完整的测试环境包括被测应用程序(AUT)及其所有相关组件(例如API、第三方服务、数据库、应用程序和其他端点)。
服务虚拟化使团队能够(1)访问所需的完整测试环境,包括所有关键的从属系统组件,以及(2)以分阶段的测试环境无法实现的方式更改这些从属组件的行为。从而使团队能够更快、更完整地进行测试。
状态测试
创建现实的虚拟化依赖项的关键部分是有状态行为。换句话说,虚拟化依赖项可以在测试运行之间保留其状态。考虑一个模拟虚拟购物车组件的示例。一个简单的API允许从购物车中搜索、添加、检索和删除商品。采用无状态行为,模拟搜索并将商品保存到购物车不会改变购物车的状态。测试从购物车中检索和删除数据的过程将失败,因为购物车将保持其初始状态(空),如下所示:
但是,如果为虚拟购物车提供了有状态行为,则在测试之间保留其状态(空或其中有多个项目),并且还根据被测试应用程序的输入进行更改,您可以开始有意义地测试过程。
使用状态测试,虚拟化服务现在可以将状态从空更改为“已添加项目”,并返回适当的信息。如果将商品添加到购物车,并且AUT查询购物车,则返回适当的数据。使用状态测试可以进行更实际的测试,现在查询购物车将返回添加的项目,如下所示:
总而言之,要拥有可信赖且可重用的虚拟服务,至关重要的是,它们必须充分模仿真实的服务,以将有意义的结果返回给被测应用程序,这可能需要状态测试。
除了虚拟服务本身的状态之外,您可能还需要根据不同的潜在输入来模拟状态变化,这称为状态转换测试。
什么是状态转换测试?
状态转换是有限状态机的动作组件,定义为:
“……一个抽象机器,在任何给定时间都可以恰好处于有限数量的状态之一。 FSM可以响应某些外部输入而从一种状态更改为另一种状态。从一种状态到另一种状态的变化称为过渡。FSM由其状态、其初始状态和每个过渡的条件的列表定义。”——维基百科
状态机是描述对象的有用方法,通常被明确用作编程模型。在其他情况下,例如我们的购物车,可能会有一个隐式状态机来描述其行为。对于上面的购物车示例,请考虑以下状态机:
购物车的初始状态为空,并且在将商品添加到购物车时,状态从“空”转换为“购物车中的商品”。根据事件(在这种情况下,从购物车中添加或删除商品)启动转换。
过渡通常需要先确定条件,例如,仅当项目数再次为零时,才发生过渡回“空”状态的情况。在此示例中,转换通常会执行操作,例如增加购物车中的物品计数。尽管不太可能将购物车编程为状态机,但是有一个隐式的购物车可用于定义其行为。
考虑另一个简单的用户登录组件示例,该组件在重试一定次数后将用户锁定:
在登录组件中,初始状态已注销。只有输入正确的PIN才能登录用户。在定义次数的登录尝试(MAX_RETRIES)之后,该帐户将被阻止。在这种情况下,帐户阻止可以被视为最终状态,因为现在有从其转移的方法。
使用Parasoft Virtualize模拟状态
那么,这对测试和虚拟服务有何帮助?好吧,可以使用Parasoft Virtualize模拟状态行为,以便服务在测试运行之间返回适当的响应,以表示AUT期望的实际值。
虚拟化服务对测试的输入做出反应,并根据需要保留值,从而扩展了捕获和模拟的测试数据的有用性,除非通过有状态行为加以增强,否则这些数据将保持静态。在Parasoft Virtualize中,服务被虚拟化为“CRUD”(创建、读取、更新、删除),以指示其测试数据源是持久性的,并且可以在测试过程中根据需要进行操作。请参见下面的屏幕截图:
Parasoft Virtualize支持与每个虚拟服务关联的测试数据源(或引擎)中的状态行为,该状态行为不仅存储测试数据,而且还提供CRUD工具以根据对收到的API请求的反应来操纵数据。测试日期源中数据的这些更新基于输入事件(如上面状态转换图中讨论的那些更新——输入事件到达,状态转换发生,操作发生)。
为了支持所有这些,Parasoft Virtualize中的测试数据管理工具被配置为基于数据源和到达事件执行更新:
测试日期源的更新可以是单个数据项,也可以是整个对象。该工具还允许您根据所需的业务规则创建和删除记录。实际上,它足够强大,可以模拟复杂的行为,这就引出了一个问题:何时进行过多的模拟,过多的模拟?
有状态虚拟化的利与弊
使用纯虚拟化在测试中非常有帮助,因为它消除了处理真实服务的复杂性并隔离了受测应用程序。此外,删除实时服务意味着可以在多个桌面上同时并行运行测试,而不会影响生产系统或对服务的专用副本的需求。但是,纯虚拟服务器仅返回确认,如“是,已调用此API”。在很多情况下,这是足够的,当然,直到事实并非如此。随着越来越复杂的用例的出现,我们需要虚拟化的服务器来“提高智能”。
使用上面的购物车示例,您的虚拟购物服务不仅要确认已将商品添加到购物车中,还可以模拟向购物车中添加商品,这对您的虚拟购物服务更加有用。这样,确定购物车中物品数量的查询将以正确的值成功执行。我们还可以模拟“购物车已满”状态,如上述状态机表示中所述。有状态的行为对于使我们的测试获得更有意义的结果并增加用例的覆盖范围是必要的。
但是有一点使模拟业务逻辑变得太复杂了。虚拟化的目的是减少工作量并提高生产率,因此模拟复杂性的回报越来越小。界限很难说,但是如果复杂度远远超出了我们的购物车或登录示例,那么很难证明这一努力的合理性。您如何确定模拟的行为正确?您不希望您的应用程序被构建为可与模拟服务一起使用,但实际上却无法正确地与真实服务一起使用!验证仍然需要使用实时服务(幸运的是,Parasoft的Environment Manager模块使切换变得容易)。
总结
有状态行为是创建现实的虚拟化服务的关键部分,有助于隔离测试中的应用程序。保留测试之间的测试数据状态的能力对于更实际和有用的测试是必需的。 Parasoft Virtualize提供了全面的测试数据管理解决方案,通过对API调用的输入进行有状态且基于状态的响应,使虚拟化服务的生命得以延续。
应当谨慎使用模拟,因为模拟复杂的业务逻辑的收益递减,并且有可能偏离“真实事物”。明智地使用模拟在隔离方面带来了巨大的好处,这反过来又解除了对实时服务器的依赖。但是,由于实时服务器仍在最终验证中发挥作用,因此需要诸如Parasoft Virtualize之类的服务虚拟化工具来无缝支持这些环境的混合和匹配。