Extensiones de API

Una extensión de API aumenta una definición de OpenAPI con información semántica diseñada para mejorar la generación automática de casos de prueba. Las extensiones las utiliza principalmente el asistente de AutoTest para refinar sus casos de prueba generados aleatoriamente, pero tienen una aplicabilidad más amplia.

Una extensión se presenta en dos partes:

  • Los recursos identifican los tipos de recursos clave gestionados por la API y sus métodos
  • Las propiedades adjuntan categorías semánticas a las propiedades de esquema, para restringir el formato de los valores sugeridos para esos campos.

Una extensión está asociada con un documento OpenAPI específico y utiliza la notación JSON Pointer para localizar términos en ese documento.

Recursos

La sección resources contiene un conjunto de definiciones de recursos, donde cada definición contiene como mínimo lo siguiente:

  • un nombre para el recurso
  • un puntero a un esquema de tipo object que modela el recurso
  • una colección de métodos que operan en el recurso

Normalmente, una definición de recurso también identifica un campo dentro del esquema que almacena un identificador exclusivo para instancias de ese tipo.

Por ejemplo, considere este extracto de una extensión de API:

resources:
  Book:
    schemas:
      primary:
        json_ptr: '#/definitions/Book'
    properties:
      id_name: '$.book_id'
    operations:
      create:
        - json_ptr: '#/paths/~1books/post'
      retrieve:
        - json_ptr: '#/paths/~1books~1{book_id}/get'
        - json_ptr: '#/paths/~1books/get'
      update:
        - json_ptr: '#/paths/~1books~1{book_id}/put'
      delete:
        - json_ptr: '#/paths/~1books~1{book_id}/delete'

La sección resources contiene una única definición de recurso con las propiedades siguientes:

  • define un recurso denominado Book
  • un libro se modela mediante un esquema con el mismo nombre que se encuentra en el documento OpenAPI en definitions
  • cada libro tiene una propiedad book_id que contiene su ID exclusivo
  • hay operaciones definidas en el documento OpenAPI bajo paths que crean, recuperan, actualizan y suprimen libros

La correspondencia entre el nombre de recurso y el nombre de esquema es común pero no necesaria: un nombre de recurso puede ser cualquier cosa, siempre que sea exclusivo dentro de la API.

El campo de ID exclusivo para un libro se identifica mediante un formato simplificado de expresión de vía de acceso JSON que localiza una propiedad (book_id) dentro del esquema primario.

Las operaciones (o métodos) en un recurso se agrupan por categoría:

  • Crear
  • Recuperar
  • Actualizar
  • Suprimir

Puede haber varias operaciones en cada una. En este ejemplo hay dos operaciones que recuperan libros: una que devuelve un solo libro por ID, y otra que devuelve una lista de libros, y esto es común. Una definición diferente puede tener patch así como (o en lugar de) put en update.

Las expresiones de puntero JSON en una definición de recurso hacen referencia implícitamente al documento OpenAPI asociado, por lo que el prefijo # introduce una ubicación relativa dentro de dicho documento. La sintaxis del puntero JSON utiliza la serie ~1 para hacer referencia a un carácter de barra inclinada (/) para evitar confusiones con el mismo carácter utilizado como separador, por lo que la operación definida en el documento OpenAPI por el término:

paths:
  /books/{book_id}:
    get:

se identifica aquí mediante el puntero JSON:

#/paths/~1books~1{book_id}/get

Dependencias

Una definición de recurso también puede describir una dependencia de un tipo de recurso a otro.

Por ejemplo:

  Order:
    schemas:
      primary:
        json_ptr: '#/definitions/Order'
    properties:
      id_name: '$.order_id'
    dependencies:
      - name: Book
        required: true
        references:
          - name: $.book_id
            in: body
        dependee_deletion: disabled
      - name: Customer
        required: true
        references:
          - name: customer_id
            in: path
        dependee_deletion: mutual
    operations:
      create:
        - json_ptr: '#/paths/~1customers~1{customer_id}~1orders~1{order_id}/post'
      # rest omitted for brevity

Esta definición indica que el recurso Order tiene dependencias en otros dos recursos Customer y Book (que se deben definir en la misma extensión).

Ambas dependencias son necesarias en el sentido de que una orden no puede existir a menos que haya un cliente (para formalizar la orden) y al menos un libro (para comprar).

Un pedido hace referencia a un libro existente a través de la propiedad book_id en el esquema primario, y a un cliente a través del parámetro de vía de acceso customer_id, como en el método create mostrado (y en otros métodos omitidos).

Un cliente es propietario de un conjunto de órdenes; esta es una relación jerárquica implícita en la vía de acceso:

/customer/{customer_id}/orders/{order_id}

Cuando se suprime un cliente, también se suprimen todos sus pedidos, y este comportamiento se indica mediante el valor mutual de la propiedad de supresión.

Se aplica una relación diferente a los libros: un libro no se puede suprimir hasta que se hayan suprimido todos los pedidos que hacen referencia a él, por lo que la supresión se indica como disabled en ese caso.

Hay tres valores posibles para la propiedad dependee_deletion :

  • enabled: un recurso referenciado se puede suprimir aunque los recursos dependientes que hacen referencia a él todavía existan
  • disabled: un recurso referenciado no se puede suprimir hasta que se hayan suprimido todos los recursos dependientes que hacen referencia a él
  • mutual: al suprimir un recurso referenciado se suprimen todos los recursos dependientes que hacen referencia a él: esto es típico cuando el dependiente es propiedad o está contenido en el referente

Recursos puros

Un recurso puro es aquel que no tiene instancias, o al menos ninguna instancia que se pueda rastrear con ID exclusivos, y se utiliza como marcador para operaciones que no se comportan como métodos de recurso.

Un recurso puro difiere de un recurso estándar de las siguientes maneras:

  • no tiene ningún campo de ID (porque no hay instancias)
  • las dependencias no tienen dependee_deletion (por la misma razón)
  • todas las operaciones se agrupan bajo una única categoría pure

Por ejemplo:

ServiceAvailability:
  schemas:
    primary:
      json_ptr: '#/definitions/ServiceAvailability'
    operations:
      pure:
        - json_ptr: '#/paths/~1service~1status/get'

ServiceAvailability es un tipo que se devuelve como resultado de una solicitud de estado de servicio pero no tiene un estado exclusivo y persistente.

Propiedades

La sección properties asigna categorías semánticas a las propiedades de esquema que se producen en las cargas útiles de operación, para restringir el rango de valores interpolados en cuerpos de solicitud generados.

Por ejemplo:

properties:
  - json_ptr: '#/definitions/CardPayment'
    items:
      - name: card_number
        semantic: credit_card_number
      - name: expiry_date
        semantic: expiry
      - name: security_code
        semantic: cvv

La expresión de puntero JSON localiza un esquema denominado CardPayment en el documento de API bajo definitions; el esquema debe tener el tipo object con al menos las propiedades card_number, expiry_date y security_code que se especifican aquí para tener una semántica determinada que guiará la generación automática de valores adecuados siempre que se produzca un CardPayment en una carga útil de solicitud.

Las categorías semánticas deben extraerse del siguiente conjunto:

address                 cvv                     latitude                state_code
age                     date                    longitude               street
area_code               domain                  minutes                 temperature
birthday                email                   month                   time
certificate             expiry                  name                    timestamp
charset                 first_name              number                  token
cidr                    gender                  paragraph               twitter
city                    geo_location            percentage              url
color                   hours                   phone                   user_agent
content_encoding        humidity                phone_number            username
content_type            iban                    prefix                  uuid
coordinates             id                      pressure                version
country                 identity_provider       price                   year
country_code            ip_address              revision                zip_code
credit_card_number      language                sentence
currency                language_code           social_security_number
currency_code           last_name               state

Collection apunta a un esquema que describe un conjunto de recursos. Suele utilizarse para recuperar una lista de recursos.