使用BDD和IOD开发微服务

BDD-通过行为发展。 微服务的BDD是客户端,开发人员和测试人员的协作。 BDD是一项兼顾技术利益和业务需求的开发。 这种方法通常用于描述应用程序接口,并且由于微服务是系统实现的细节,因此BDD也适合开发微服务。 怎么做-Ken Pugh的翻译。

图片

关于作者:Ken Pugh教公司开发灵活性,使用验收测试驱动开发,BDD,DevOps加速来创建高质量的系统。 肯(Ken)撰写了几本有关软件开发的书,曾获得2006年乔尔特奖(Jolt Award)预制奖,这是SAFe敏捷软件工程课程的创建者之一。

BDD中的行为通常由Give / When / Then构造表达 动作或事件发生时,我们被赋予某种状态, 然后状态改变和/或信息被返回。

例如,诸如业务规则和计算之类的无状态逻辑仅描述了输入到输出的转换。

面向接口的设计使用“设计接口,而不是实现”的原则。 服务的使用者使用它提供的接口,而不是内部接口。 这意味着应该清楚地考虑这样的接口,包括错误行为。 为了定义接口描述或其行为中的术语,可以使用DDD-域驱动设计。

当使用者直接调用另一个服务并期望结果时,微服务可以是同步的,或者当服务回答客户端已放入队列中的消息时,微服务可以是异步

考虑一个同步服务的例子。

同步服务


想象一下一个计算销售订单折扣的服务,整个过程是一组相关的操作。



此服务的行为可以描述如下:

Get discount for a customer Given these inputs Customer category Order Amount Then service outputs Discount Amount 

该服务可以基于本地数据数据库或通过与其他服务联系,使用代码中的算法来计算折扣。

它可以使用JSON或XML作为消息格式。 但是,在不指定实现细节的情况下描述服务有助于将操作的语义与语法分开。

这是什么行为?


使用BDD,您可以开始使用样本数据进行设计,以了解所需的行为。 服务,客户端和测试人员开发人员可以提出此示例。 前两列是服务的输入,右列是输出。

客户类别
订单金额
折扣金额?
好啊
100.00美元
1.00美元
优秀的
100.00美元
2.00美元

该示例显示了可能需要进一步细化的域术语-例如,描述有效值。



可以理解,如果输入数据落入可接受值的范围内,则服务将返回正确的结果。

行为描述(尤其是针对微服务的行为描述)通常包括发生故障和错误时的响应。 对潜在故障的描述有助于消费者理解在这种情况下的处理方法。 该服务的客户可以使用特殊的库(例如Netflix的Hystrix)来修复其中的一些故障。

我们服务的一些潜在错误:

崩溃
无效的查询语法
相关服务呼叫超时
无效的请求参数值

故障可以表示为通信协议中的数字或字符常量。

在BDD中使用有意义的名称有助于强调失败的语义,而不是其语法。

如果作为类别传递的值不在有效值列表中,则服务将返回失败指示符:“查询参数的值无效”。 例如,这可以通过返回HTTP代码400和相应的文本描述来表示。

或者,您可以确定将返回的折扣值,例如,如果任何参数不正确,则返回0。 在这种情况下,服务应负责记录此问题,以便可以分析其后果。

服务BDD测试可以构成其单元测试的上下文。 在设计过程中, 通过BDD测试责任在于类和方法 。 单元测试确定这些职责。

存根


测试服务时,通常需要调用它的依赖服务存根。 对于缓慢,昂贵或随机的服务,尤其需要它们。 如果打折服务的行为从未改变,则在测试客户端时,可以使用战斗实例。

更改通常是不可避免的,因此通常需要存根。



存根始终可以返回相同的值,例如:

客户类别
订单金额
折扣金额?
好啊
100.00美元
1.00美元
优秀的
100.00美元
2.00美元

客户测试可以依靠这些值。 在此示例中,恒定行为可能就足够了。 对于其他测试,最好使用自定义存根响应。

另外,无论输入什么,打折服务存根都可以简单地返回相同的金额。

这个存根如何适应更广泛的情况? 考虑订单的系统行为,其中包括折扣和税收。 税收是由微服务计算的,类似于折扣。



有一个买家。

买家类别
所在位置
好啊
北卡罗莱纳州

可调折扣。

客户类别
订单金额
折扣金额?
好啊
100.00美元
1.00美元

税收确定了。

所在位置
数量
征税?
北卡罗莱纳州
99.00美元
6.60美元

当客户下订单时:

订单金额
100.00美元

然后订购选项。

订单金额
打折
折后金额
税款
应付总额
100美元
1.00美元
99.00美元
6.60美元
105.60美元

有状态的服务


如果打折服务使用数据库获取用于计算打折的信息,则其内容就是服务的状态。 应记录响应数据更新的状态更改。 假设服务具有此状态。

客户类别
门槛等级
折扣率
好啊
100.00美元
1%
优秀的
50,00美元
2%

在这种情况下,服务应允许更改此数据。 可以组织更新,以便单个元素被更新或整个表被立即更新。 这是针对单个更新的行为测试的示例。

给定当前数据。

客户类别
门槛等级
折扣率
好啊
100.00美元
1%
优秀的
50,00美元
2%

更新项目时。

客户类别
门槛等级
折扣率
优秀的
50,00美元
3.5%

然后更新数据。

客户类别
门槛等级
折扣率
好啊
100.00美元
1%
优秀的
50,00美元
3.5%

您还可以验证是否使用更新的数据来计算折扣。

客户类别
门槛等级
折扣金额?
优秀的
100.00美元
3,50美元

在此示例中,折扣服务可能具有用于存储数据的本地存储,但是它也可能依赖于此数据的单独存储服务。 如果是这样,那么上一节中的测试将应用于单独的服务。 但是每种成瘾都会增加问题。 如果服务的依赖项不可用,服务的行为应该是什么? 对于折扣服务,这应该表示失败还是应该简单地返回默认值,即0? 有时,您可以使用全局错误处理策略,但决策通常取决于服务的上下文

测试配方和自动化


一旦微服务的行为一致,就可以将其表述为自动化测试。 有几种微服务测试系统,例如PACT或空手道。 另外,您可以使用BDD框架,例如Cucumber或FIT。

例如,Cucumber使用库来查询服务。 然后,有关环境的其他信息可以作为脚本的一部分呈现。

例如,黄瓜目标文件可能包括在内。

场景:计算订单金额的折扣
给定的设置是:
| 网址| myrestservice.com |
使用以下方式计算折扣时:
| 方法 GET |
| 路径| 折扣|
| 版本| 1 |
那么每个实例的结果是:
| 客户类别| 订单金额| 折扣金额? |
| 好 100.00美元| 1.00美元|
| 优秀 100.00美元| 2.00美元|

步骤选项取决于您的测试约定。

前两列中的值可以传输到任何调用约定,例如,查询参数。 正文中的结果必须与第三列匹配。 如果查询的名称和值是列的名称和值,则这将减少测试和实现之间的差异。

为了重用,可以为执行计算或确定业务规则结果的任意服务编写步骤。 在上面的示例中,使用上面的“折扣金额”中的“?”符号可以帮助分析仪区分输入和输出。

例如,测试还应包括失败。

客户类别订单金额折扣金额?结果
不错100.00美元
1.00美元&nbsp
好啦
不太好100.00美元2.00美元&nbsp参数值无效
优秀&nbsp100.00 ZZZ&nbsp2.00美元&nbsp参数值无效

结论


微服务依赖于其他服务和系统,这需要接口的明确规范及其准确的测试。 这可以通过描述测试定义的行为和接口来实现。 使用BDD,服务的功能由可执行测试描述,这些测试关注于操作的语义而不是语法 。 这种测试的自动化通常需要设置其他服务的存根,其行为由其单独的BDD测试来描述。

面向接口的设计-IOD,包括服务的其他义务:对资源使用,带宽和错误报告的限制。 BDD和IOD一起帮助描述服务的行为,以便客户可以轻松理解和依赖它。

  • BDD微服务专注于三合会的合作-服务开发人员,客户开发人员和测试人员。
  • 使用IOD为微服务接口创建明确定义的约定。
  • 微服务通常需要测试插头以加快测试速度。
  • 测试必须是独立的。
  • 在测试中测试否定场景。
5月27日至28日,在QualityConf会议上举行的RIT ++节上 Artyom Malyshev将讨论在代码中清楚地表达域模型的重要性,并通过示例演示如何做到这一点。

快来谈论开发优质产品并分享您的想法!

Source: https://habr.com/ru/post/zh-CN450800/


All Articles