Cucumber高阶用法 —— 活用Cucumber测试服务端开放API

Abstract

本文首先介绍了服务端开放API的交互参数和返回格式,引出测试这样风格的API所需要注意的点,进而介绍如何使用Cucumber结合开源的Rest-Assured来测试开放API。对JSON格式的返回数据,本文介绍了如何使用JSON Schema来做数据结构和数据有效性验证,从而保证即使在复杂、大量返回数据的情况下也能够轻松地验证数据结构是否符合期望,同时不放过任何一个不合法的字段值。

服务端开放API

服务端开放API简介

所谓的开放API(OpenAPI)是服务型网站常见的一种应用,网站的服务商将自己的网站服务封装成一系列API(Application Programming Interface,应用编程接口)开放出去,供第三方开发者使用,所开放的API就被称作OpenAPI(开放API)

介绍本例中所使用的API功能,参数和返回结构

本文中所涉及到的开放API主要实现了对数据的查询:根据卡号查询银行卡信息、分页获取满足条件的银行卡记录、查询银行卡对应的账单地址信息等。读者可以通过类io.cucumber.samples.dw.controller.AppController所提供的各个方法去逐个查看。后续行文中主要使用了一个开放API:/card/query

Sample app 的实现和启动方式

本文中所述被测试应用是基于Spring boot实现,采用Spring boot可以加快开发和部署速度,加上Spring boot的快速启动方式,能够在开发环境中迅速启动并验证功能的实现是否符合预期设计。

功能实现

被测应用在功能上主要模拟现实的银行业务场景,简单实现了银行卡及其持卡人的信息管理。为了切合当前我们所介绍的测试方法,在实现业务的过程中主要关注了银行卡、持卡人信息的查询。对于行文中所采用的被测Open API,下文会给出详细的解释。

系统略图

在实现开放API功能的过程中,本文主要采用了如图 1 所示的架构,并使用主流的工具加以实现。

图 1 系统实现略图

应用启动

AppStarter类是整个应用的启动点,启动过程中主要做了:

  • 1, 初始化Spring;

  • 2, 启动Spring boot 及其内嵌的Web Container以接收HTTP请求;

  • 3, 为了便于读者搭建环境,减少不必要的数据库配置过程,同时也为了保证每次运行的时候都是一个干净的环境,数据库采用的是Derby的Memory模式,这样,在Sample app每次启动时都需要重新初始化数据库,并写入测试数据。

当应用成功启动之后,可以从控制台看到类似如下的输出信息

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.2.RELEASE)

…… …… ……

/*** Database initialization ***/
CREATE TABLE CARD
(
  ID              INT PRIMARY KEY          NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH 1, INCREMENT BY 1),
  CARD_NUM        CHAR(8)                  NOT NULL UNIQUE,
  IS_PRIMARY_CARD SMALLINT DEFAULT 0       NOT NULL,
  CARD_OWNER_NAME VARCHAR(64)              NOT NULL,
  CARD_TYPE       SMALLINT DEFAULT 0       NOT NULL,
  STAR_POINTS     DECIMAL(10) DEFAULT 0.00 NOT NULL
)

INSERT INTO CARD (CARD_NUM, IS_PRIMARY_CARD, CARD_OWNER_NAME, CARD_TYPE, STAR_POINTS)
VALUES ('C0000001', 1, 'CENT LUI', 0, 1024.64)

INSERT INTO CARD (CARD_NUM, IS_PRIMARY_CARD, CARD_OWNER_NAME, CARD_TYPE, STAR_POINTS)
VALUES ('C0000002', 1, 'ROD JOHN', 0, 1048576.16)

INSERT INTO CARD (CARD_NUM, IS_PRIMARY_CARD, CARD_OWNER_NAME, CARD_TYPE, STAR_POINTS)
VALUES ('C0000003', 1, 'STEVE JOBS', 0, 1048576.16)

INSERT INTO CARD (CARD_NUM, IS_PRIMARY_CARD, CARD_OWNER_NAME, CARD_TYPE, STAR_POINTS)
VALUES ('S0000001', 0, 'CENT LUI', 1, 0.00)

INSERT INTO CARD (CARD_NUM, IS_PRIMARY_CARD, CARD_OWNER_NAME, CARD_TYPE, STAR_POINTS)
VALUES ('S0000002', 0, 'ROD JOHN', 1, 512.64)

INSERT INTO CARD (CARD_NUM, IS_PRIMARY_CARD, CARD_OWNER_NAME, CARD_TYPE, STAR_POINTS)
VALUES ('S0000003', 0, 'STEVE JOBS', 1, 1024.64)


CREATE TABLE ADDRESS
(
  ID         INT PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH 1, INCREMENT BY 1),
  CARD_NUM   CHAR(8)         NOT NULL,
  REGION     VARCHAR(128)    NOT NULL,
  COUNTRY    VARCHAR(6)      NOT NULL DEFAULT 'CHN',
  STATE      VARCHAR(64)     NOT NULL,
  CITY       VARCHAR(64)     NOT NULL,
  STREET     VARCHAR(64)     NOT NULL,
  EXT_DETAIL VARCHAR(128)    NOT NULL,
  FOREIGN KEY (CARD_NUM) REFERENCES CARD (CARD_NUM)
)

INSERT INTO ADDRESS (CARD_NUM, REGION, COUNTRY, STATE, CITY, STREET, EXT_DETAIL)
  SELECT
    CARD_NUM,
    'AP',
    'CN',
    'HeNan',
    'LuoYang',
    'Peking Rd',
    'Apartment 1-13-01 No.777'
  FROM CARD

INSERT INTO ADDRESS (CARD_NUM, REGION, COUNTRY, STATE, CITY, STREET, EXT_DETAIL)
  SELECT
    CARD_NUM,
    'EU',
    'ES',
    'Madrid',
    'Sol',
    'Century Rd',
    'Apartment 1-13-01 No.777'
  FROM CARD

…… …… ……
/*** Open API URI mappings ***/
Mapped "{[/address/count],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.countAddress(java.lang.String)
Mapped "{[/card/count],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.countCards(java.lang.String)
Mapped "{[/address/query],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.getAddressByCardNum(java.lang.String)
Mapped "{[/address/all],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.getAllAddress()
Mapped "{[/address/paged],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.getPagedAddress(java.lang.Integer,java.lang.Integer)
Mapped "{[/card/query],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.getCardByCardNum(java.lang.String)
Mapped "{[/card/all],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.getAllCards()
Mapped "{[/card/paged],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<io.cucumber.samples.dw.base.StandardJsonResponse> io.cucumber.samples.dw.controller.AppController.getPagedCards(java.lang.Integer,java.lang.Integer)
Mapped "{[/database/test],methods=[GET],produces=[application/json]}" onto org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Integer>> io.cucumber.samples.dw.controller.DatabaseController.filterAddressByCardNum()

…… …… ……

Tomcat started on port(s): 8080 (http)

应用启动验证

当应用启动之后,可以通过应用提供的Open API/database/test来验证系统是否正确启动。若系统正确启动了所有的模块,那么当以GET方法访问Open API/database/test时,能够看到如下的输出内容:

[
  {
    "cardCount": 6
  },
  {
    "addressCount": 
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Cucumber是一种行为驱动开发(BDD)工具,它结合了自然语言和自动化测试,用于编写可执行的规范文档。它使用Gherkin语言来描述应用程序的行为,并将这些描述转化为可执行的测试代码。 Cucumber的核心思想是通过定义特定的场景和步骤来描述应用程序的行为。这些场景和步骤以Gherkin语言的格式编写,例如: ``` Feature: 用户登录 用户可以通过用户名和密码登录系统 Scenario: 正确的用户名和密码 Given 用户打开登录页面 When 用户输入正确的用户名和密码 And 用户点击登录按钮 Then 用户成功登录系统 Scenario: 错误的用户名和密码 Given 用户打开登录页面 When 用户输入错误的用户名和密码 And 用户点击登录按钮 Then 用户收到错误提示信息 ``` 上述示例中,`Feature`定义了一个功能,`Scenario`定义了一个具体的场景,`Given`、`When`、`Then`等关键词定义了具体的步骤。 Cucumber支持多种编程语言,如Java、Ruby、JavaScript等。你可以使用相应的Cucumber库来编写测试代码,并将Gherkin语言的描述与测试代码关联起来。当运行测试时,Cucumber会解析Gherkin语言的描述,并执行相应的测试代码。 Cucumber的优点包括: 1. 提供了一种可读性强的测试文档形式,使得非技术人员也能理解和参与测试过程。 2. 通过自然语言描述测试场景,减少了测试用例的维护成本。 3. 支持多种编程语言和测试框架,灵活性高。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值