作好自動化 API 測試(1)- 從一個好用的 Json Validator 開始

目前,先後端分離的開發模式愈來愈受到你們的青睞,前端與後端的職責也更加清晰,後端經過 API 提供數據,前端經過 API 獲取數據,展現頁面,前端有更大的發揮空間、後端也能夠更加專一於數據處理。php

在這樣的時代大背景下,我嘗試從後端的角度出發,經過一系列文章,探討後端開發人員應該如何交付高質量的 API 接口,減小溝通成本,下降「聯調」可能出現的問題,保證代碼質量以及項目定期完成。前端

就目前個人面試經驗而言,絕大部分項目都沒有引入自動化 API 測試,測試基本都是依靠開發人員的自測以及測試人員黑盒測試。本文不探討黑盒測試,僅僅發表一點我對自動化 API 測試的想法。laravel

首先,在我來看,缺乏自動化 API 測試可能存在如下問題:git

  1. API 實現與設計不符,好比缺乏字段或者字段類型不正確github

  2. API 沒法造成完整閉環,缺乏功能,「聯調」還須要不斷修改面試

  3. 新加功能可能致使已有 API 出現 BUG,手動迴歸測試耗時且繁瑣thinkphp

API 測試是一個比較大的主題,本文主要就「如何讓 API 的實現與設計相符合」這一點出發,說一說個人想法及開發 Json Validator 的心路歷程。json

緣起

早在兩年多之前,就在思考如何作 API Schema 的測試,保證 API 返回的結果與預期的一致。當時發現了 Json-Schema 這個工具,也研究了一番,但上手成本仍是略高,最終並無實質的產出什麼東西。後端

而後去年在開發 Blink Framework 的 API 測試組件的時候,發現 Laravel 中 驗證 Json 的用法,很簡潔優雅,同時 Codeception 也有相似的組件。api

因而我就在想,有沒有可能結合這兩種方式的優勢,本身開發一個 Json Validator,保持嚴謹的同時儘量簡單易用。

契機

正好2017新的一年,公司產品須要對外提供新的 Open API,方便與合做廠商就行業務對接。我認爲這是一個實驗和推行新 API 測試方式的時機,因而便利用假期的時間,開發出了 Json Validator 的原型,讀者能夠在 rethinkphp/json-validator 查看它的最新代碼。
Json Validator 經過簡單的語法定義 Json 結構,而後驗證給定的數據是否知足預約義的 Json 結構,比 Json-Schema 更加簡單易用。

設計思想

除了保證設計的簡潔優雅外,Json Validator 引入類型系統的概念,經過開發者自定義類型,實現類型的複用與自由組合,讓 Json 的驗證更方便高效,只要一個項目的基礎類型定義好了,剩下基本搭積木組裝便可。

基本用法之類型

Json Validator 默認提供7種內置類型,他們分別是: integer, double, boolean, string, number, arrayobject。開發者也能夠定義本身的複合數據類型,以下的例子定義了一個 User 複合類型:

$validator->defineType('User', [
    'name' => 'string',
    'gender' => 'string',
    'age' => '?integer',
]);

這個 User 類型有三個屬性,name、gender 和 age,其中 name 和 gender 都是 string 類型,age 爲 integer 類型,但容許爲 null。這裏咱們在類型的前面加一個 ? 表示該字段能夠爲 null

除了定義複合數據類型,咱們也能夠定義列表類型,好比定義一個 UserCollection 的類型,它是一個數組,數組的每一個元素都是 User:

$validator->defineType('UserCollection', ['User']);

要定義一個列表類型,類型的定義必須是隻有一個元素的數組,數組的第一個元素即該列表類型所容許容納的類型。

對於複雜應用場景,咱們也可使用 PHP 的 callable 來定義更靈活的類型,以下咱們定義一個 timestamp 的類型,它驗證給定的值必須是合法的時間字符串。

$validator->defineType('timestamp', function ($value) {
    if ((!is_string($value) && !is_numeric($value)) || strtotime($value) === false) {
        return false;
    }

    $date = date_parse($value);

    return checkdate($date['month'], $date['day'], $date['year']);
});

基本用法之驗證

定義好了數據類型以後,咱們就能夠驗證給定的數據是否符合定義,若是不符合定義,Validator 會給出錯誤信息。

use rethinkphp\jsv\Validator;

$validator = new Validator();
// $validator->defineType(...)  Add your custom type if necessary

$matched = $validator->matches($data, 'User');
if ($matched) {
    // Validation passed
} else {
    $errors = $validator->getErrors();
}

在一些場景下,咱們但願咱們定義的類型與給定的數據徹底匹配,不須要多餘的字段,這個時候可使用 Json Validator 的嚴格模式:

$data = [
    'name' => 'Bob',
    'gender' => 'Male',
    'age' => 19,
    'phone' => null, // This property is unnecessary
];
$matched = $validator->matches($data, 'User', true); // strict mode is turned on
var_dump($matched); // false is returned

這個例子就會驗證失敗,由於 phone 字段在 User 中並無定義。

將來暢想

本文介紹了我開發 Json Validator 的背景和過程以及它的簡單用法,但我也在想它的使用場景可能不只侷限於此,下面是我對其將來的一些想法:

  1. 類型系統與文檔生成工具相結合,從代碼直接生成 API 文檔的數據模型部分

  2. 自動生成 Json-Schema 定義文件,跨語言使用更方便

  3. 經過生成 Json-Schema 定義文件,實現自描述 RESTFul API

未完待續...


本文首發於「代碼寫詩」微信公衆號及同名知乎專欄

圖片描述

掃描二維碼關注「代碼寫詩」公衆號

微信公衆號: https://mp.weixin.qq.com/s/cN...
知乎專欄: https://zhuanlan.zhihu.com/p/...

相關文章
相關標籤/搜索