Skip to main content

OpenAPI Documentation

OpenAPI Creation and Artifact Generation

We document our API endpoints using OpenAPI3. The documentation is recorded in a group of yaml files, which are converted to HTML and JSON via the modules/mobile/docs/generate_static_docs.sh script. Developers must run that script each time they change the yaml to ensure that our documentation is up to date.

Setup

Developers will need to install redocly in order to run the generate_static_docs script.

Using OpenAPI in RSpec

The backend team uses the committee-rails gem to tie our documentation and specs together. This gem should be used in request specs to validate requests and responses against the JSON file generated by the generate_static_docs script. To add it to a request spec, simply call the method assert_schema_conform(expected_status). This will use the uri path from the request object and the expected status (e.g., 200) to look up which schema the response should match and validate the response.body against it.

Limitations

Our schema tests are only as good as the data we're testing against. These tests run against VCR cassettes we've either recorded or been given. These cassettes will not necessarily cover all cases. It's also possible for cassettes to become out of date, which can cause drift between our specs/OpenAPI documentation and reality.

Schema tests are also only as good as the schema they're testing against. Schema should be written as strictly as possible. That means indicating when properties are required or nullable, when additional properties are not permitted in objects, indicating string formats, and specifying which strings are possible via the enum type. Greater specificity results in better documentation.

Best Practices

  • use models and serializers to lock down the schema
  • use all VCR cassettes available to ensure broad test coverage
  • only validate the schema once per unique case. In other words, if you need to run several tests with the same data setup and you expect the same response each time, there's no need to validate the schema each time.
  • use nullable: true when you know an attribute may be null. This should also be reflected in the model.
  • use additionalProperties: false on all objects. Additional properties should be prevented by the model and serializer.