goez/open-api-tester

2.1.0 2023-11-22 06:34 UTC

This package is auto-updated.

Last update: 2024-09-22 08:36:26 UTC


README

使用Open API Spec 3文档测试API输出格式。

分支

  • 1.x: 支持 PHP 7.2。
  • 2.x: 支持 PHP 7.4及以上。

安装

将此包安装到您的项目中

composer require goez/open-api-tester --dev

在您的Laravel项目中生成API文档示例和PHPUnit测试用例

php artisan vendor:publish --tag=open-api-tester

该命令将生成以下文件

  • docs/api/*: API文档示例。
  • tests/Feature/OpenApiSchemaTest.php: PHPUnit测试用例。

基本用法

定义测试用例

在文档的操作级别中,添加一个x-api-tests扩展字段。在里面,以数组格式列出一个或多个测试用例。

测试用例的格式如下

  - type: request_test_case
    value:

      # Which response this test corresponds to
      response: 200

      # Description of this test (optional)
      description: "Test post user data"

      # Overriding parameter values (optional)
      # Defaults are taken from the parameters field of the operation
      # But if listed here, it overrides the default
      parameters:
        - name: some_parameter
          in: query
          value: some_value

      # Mock object outputs (optional)
      # Used to declare the output content of certain objects; multiple can be declared
      # Only its value will be retrieved in the test, requires additional handling through code
      mocks:
        - type: guzzle
          value: post_200_v1_login

      # Pre-test hook (optional)
      # Called before the test is executed, can be given a string or an array of PHP callable definitions
      setUp: ExampleClass::setUp

      # Post-test hook (optional)
      # Called after the test is executed, can be given a string or an array of PHP callable definitions
      tearDown: ExampleClass::tearDown

      # Request body (optional)
      #
      # Request format. This will affect how the request content should be encoded before sending.
      # It will also generate the corresponding Header.
      # Supports application/json, multipart/form-data, application/x-www-form-urlencoded
      requestBody:
        type: application/json
        data:
          # Directly write structured request content in the format of `key: string`.
          username: "John"
          # Or use `key: { type: file }` to upload a file
          image:
            type: file
            path: ./uploaded_image.jpg
            filename: original_name.jpg
          # Or use `key: { type: array, data }` to represent an array
          array_data:
            type: array
            data:
              some_key: 1
              some_other_key:
                - a
                - b
                - c

检索测试用例

use Goez\OpenAPI\Tester\TestSuite;
use Goez\OpenAPI\Tester\TestCase;

// Parse the entire API document to get the test suite
$testSuite = TestSuite::loadFromYamlFile(
  __DIR__ . '/docs/api.yaml', // Document location
  'My API Tests',             // Test suite name
  __DIR__ . '/test_files/'    // External file path (Where to find the test files for testing uploads)
);

// Get warnings from the parsing process, which can be echoed to notify developers.

// Currently, warnings are generated when:
//   - No tests are defined for an Operation
$warnings = $testSuite->getWarning();

// Retrieve the test cases
// An array of Goez\OpenAPI\Tester\TestCase
$testCases = $testSuite->getTestCases();

foreach ($testCases as $testName => $testCase) {
  // Use the information contained in `$request` to make an HTTP call to your API or mock the Controller directly.
  $request = $testCase->getRequest();

  // Here, we use the fictitious function `callMyApi` to represent it. You'll need to implement it yourself.
  // If you're using Laravel, more information is provided below.
  $response = callMyApi($request);

  // Here are some commonly used methods:
  //
  // $request->getPath();
  // $request->getMethod();
  // $request->getQuery();
  // $request->getRequestBody();
  // $request->getHeader();

  // Verify if the actual response matches the definition
  $result = $testCase->validate($response->code, $response->body, TestCase::FORMAT_JSON);

  // Check if the validation was successful
  assert($result->isValid(), true);

  // Print out the validation details
  echo $result->renderReport();
}

使用Laravel/Lumen与PHPUnit

定义PHPUnit测试用例

您可以参考此文件tests/Feature/OpenApiSchemaTest.php

组织请求格式

Laravel实际上并不发送HTTP请求,而是创建一个请求对象并将其直接馈送到Laravel应用程序进行处理。

因此,以下内容需要注意

  • 请求内容不需要编译成实际格式(JSON、urlencoded等);它可以直接以PHP数组的形式插入到$parameters参数中。
  • 对于文件上传,使用Illuminate\Http\UploadedFile对象。这两个$parameters$files字段都应包含一个副本。
  • 您可以使用Laravel TestCase中内置的transformHeadersToServerVars方法将请求的头部部分转换为$server变量。在此示例中,我们将测试请求转换为Laravel可以轻松处理的格式。
public function extractRequestInfo(\Goez\OpenAPI\Tester\Request\Request $request): array
{
    $files = [];
    $body = [];

    $server = $this->transformHeadersToServerVars($request->getHeader());
    $requestBody = $request->getRequestBody();

    if ($requestBody === null) {
        return [$body, $files, $server];
    }

    $body = collect($requestBody->getStructuredData())
        ->map(function ($item, $name) use (&$files) {
            if (is_a($item, \Goez\OpenAPI\Tester\Request\UploadedFile::class)) {
                // Convert the `UploadedFile` object into the `Illuminate\Http\UploadedFile`
                $uploadedFile = new \Illuminate\Http\UploadedFile(
                    $item->getPath(),
                    $item->getClientOriginalName(),
                    $item->getClientMimeType(),
                    null,
                    true
                );

                $files[$name] = $uploadedFile;

                return $uploadedFile;
            }

            return $item;
        })->toArray();

    return [$body, $files, $server];
}