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
objectque 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_idque contiene su ID exclusivo - hay operaciones definidas en el documento OpenAPI bajo
pathsque 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 existandisabled: un recurso referenciado no se puede suprimir hasta que se hayan suprimido todos los recursos dependientes que hacen referencia a élmutual: 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.