{"id":1668,"date":"2023-11-16T10:00:00","date_gmt":"2023-11-16T09:00:00","guid":{"rendered":"https:\/\/www.devengo.com\/?p=1668"},"modified":"2024-06-27T13:58:23","modified_gmt":"2024-06-27T13:58:23","slug":"api-spec-testing-for-accurate-documentation","status":"publish","type":"post","link":"https:\/\/www.devengo.com\/en\/blog\/api-spec-testing-for-accurate-documentation\/","title":{"rendered":"API Spec Testing for Hardened and Accurate Documentation\u00a0"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Humans write documentation<\/strong><\/h2>\n\n\n\n<p>Documenting is instructing or informing someone about the news and evidence related to a specific topic. Therefore, when we write technical documentation, It\u2019s important to understand that we are writing for humans, not machines. We try to help the reader understand the complexity of our system, and to achieve this, we can make use of <strong>our extensive and rich language<\/strong>. However, the tools we have for creating documentation don&#8217;t always make things easy for us.<\/p>\n\n\n\n<p>For example, in the case of <a href=\"https:\/\/www.openapis.org\/\" target=\"_blank\" rel=\"noopener\">OpenAPI<\/a>, the most widely used tool for API documentation, we can only add arbitrary text in certain \u201cdescription\u201d fields. This falls short if we need to elaborate on the explanation of a resource, display examples, images, etc.<\/p>\n\n\n\n<p>Furthermore, JSON and YAML formats are highly oriented towards machine-generated or machine-interpreted purposes, making it very challenging for humans to create and maintain them. Even though there are tools to simplify editing, it&#8217;s a format where syntactical definition takes precedence over semantics.<\/p>\n\n\n\n<p>At Devengo, we believe that documentation <strong>should be oriented towards people<\/strong>. That&#8217;s why we&#8217;ve always advocated for using Markdown whenever possible. On the other hand, we also understand the value of syntactical definition when generating schemas, validators, clients, etc. Wouldn&#8217;t it be great if we could combine both worlds? As a matter of fact, that tool has existed for years, and it&#8217;s called <a href=\"https:\/\/apiblueprint.org\/\" target=\"_blank\" rel=\"noopener\">API Blueprint<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Markdown FTW<\/strong><\/h2>\n\n\n\n<p>API Blueprint is a tool that was born in 2013, allowing us to use Markdown as a language to document our APIs. Many people reading this article may have tried it at some point and considered it outdated because it lost the battle against OpenAPI. The latter tool became the industry standard, and all the focus has been on it. However, we believe it is still entirely valid because it provides the principles we mentioned earlier.<\/p>\n\n\n\n<p>The number of artifacts we use in Blueprint is minimal and easy to learn.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Data Structures<\/strong><\/h3>\n\n\n\n<p>It&#8217;s the definition of the different data types that the API handles.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/devengo-devteam\/51aea7f3e08eb35ae7d86777d06a507d.js\"><\/script>\n\n\n\n<p>If you open that snippet in a Markdown viewer, you won&#8217;t have any trouble reading and understanding the data structure. Additionally, it&#8217;s straightforward to write.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Endpoints<\/strong><\/h3>\n\n\n\n<p>Once you have defined your data structures, you can use them in the endpoints definition. This is how it looks:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/devengo-devteam\/e505d04c8dea6d2d5a533d4c729b48ca.js\"><\/script>\n\n\n\n<p>A great thing we can do is define different examples of requests and their responses. This is very convenient for providing examples of erroneous requests with their corresponding error messages. For instance, if we want to simulate a request where the authentication header is missing:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/devengo-devteam\/87c3e736539b08f4a7606b534cc8a692.js\"><\/script>\n\n\n\n<p>Another typical example would be documenting the case where we omit a required parameter.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/devengo-devteam\/21b0f7cb8821083acdd679f033ec2604.js\"><\/script>\n\n\n\n<p>The crucial point is that in Markdown, we can define documents in a much more flexible way, <strong>alternating between semantic and syntactic documentation<\/strong> as needed. While these files can be easily read with a Markdown reader, there are also tools capable of analysing and understanding the format, allowing us to operationalise the documentation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u0434\u043e\u0432\u0435\u0440\u044f\u0439, \u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439 &#8211; Testing with Dredd<\/strong><\/h2>\n\n\n\n<p>A widely popularised <a href=\"https:\/\/en.wikipedia.org\/wiki\/Trust,_but_verify\" target=\"_blank\" rel=\"noopener\">Russian proverb<\/a> from the Cold War era says \u201cTrust, but verify\u201d (\u0434\u043e\u0432\u0435\u0440\u044f\u0439, \u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439 <audio id=\"devengo-audio-69ff72ad68cc4\" src=\"https:\/\/www.devengo.com\/wp-content\/uploads\/2023\/11\/api_spec_testing_doveryay_pronunciation.mp3\"><\/audio><button style=\"all: initial; cursor: pointer; display: inline-flex; justify-content: center; vertical-align: middle; margin-top: -3px;\" data-devengo-audio-target=\"devengo-audio-69ff72ad68cc4\"><\/button>, doveryay, no proveryay) &#8211; a good practice to apply to our documentation.<\/p>\n\n\n\n<p>As we explained in a <a href=\"https:\/\/www.devengo.com\/blog\/generate-up-to-date-documentation-for-your-api\/\">previous post<\/a>, it&#8217;s crucial to have living documentation to ensure it remains updated. At Devengo, our main product is an API, so we need the best integration experience and ensure that whatever the documentation states is aligned with the system&#8217;s actual behaviour.<\/p>\n\n\n\n<p>One of the tools that allows us to operationalise API Blueprint documentation is <a href=\"https:\/\/dredd.org\/\" target=\"_blank\" rel=\"noopener\">Dredd<\/a>. Personally, I believe this is one of the most useful yet lesser-known tools for API testing. Dredd will run an instance of your web server, automatically read all the requests defined in the document, and send them to this server to <strong>validate that the schemas and response codes match<\/strong> what has been documented. How cool is that?<\/p>\n\n\n\n<figure class=\"wp-block-image size-large zoom-it is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"579\" src=\"https:\/\/www.devengo.com\/wp-content\/uploads\/2023\/11\/post-api-spec-testing-1024x579.png\" alt=\"API Spec testing\" class=\"wp-image-5092\" srcset=\"https:\/\/www.devengo.com\/wp-content\/uploads\/2023\/11\/post-api-spec-testing-1024x579.png 1024w, https:\/\/www.devengo.com\/wp-content\/uploads\/2023\/11\/post-api-spec-testing-300x170.png 300w, https:\/\/www.devengo.com\/wp-content\/uploads\/2023\/11\/post-api-spec-testing-768x435.png 768w, https:\/\/www.devengo.com\/wp-content\/uploads\/2023\/11\/post-api-spec-testing.png 1520w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>If you liked what you just read but think you won&#8217;t be able to use it because you don&#8217;t use Blueprint, you should know that Dredd is quite stack-agnostic. It supports both OpenAPI and Blueprint files, and it even has plugins to integrate with various languages.<\/p>\n\n\n\n<p>The installation and configuration of Dredd is very straightforward. You just need to specify the command to start your server, the file where the documentation resides, the endpoint to use, and, optionally, the configuration for hooks.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/devengo-devteam\/9b458284f5b1e5a7bd2c860aabafaa15.js\"><\/script>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Providing Clean Data<\/strong><\/h3>\n\n\n\n<p>As you may have inferred, the requests executed by Dredd are real requests against a test server, so they alter the state of resources. You&#8217;ll need to be cautious about this, just like in any other end-to-end type of test. For example, you might want to define a couple of different users to test different flows or create a resource only used for testing its deletion on a specific endpoint.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Hooks<\/strong><\/h3>\n\n\n\n<p>Optionally, you can configure hooks that run before or after each request to the server. A good use case is storing the authentication token after the call to the login endpoint and automatically including it in the subsequent requests.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/devengo-devteam\/4455a0cc2dc7a6da17082d0e875ad45a.js\"><\/script>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Even if it&#8217;s technical, documentation is <strong>written by humans and intended for humans<\/strong>. Therefore, it&#8217;s crucial for it to be easy to write and read. In this post, we&#8217;ve seen how, with just a couple of simple and stack-agnostic tools, we can have a pipeline for generating and testing API documentation. Remember: Doveryay, no Proveryay.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Technical documentation should be written for people, not machines. However, the tools available for creating documentation don&#8217;t make it easy to help our readers understand complex systems. How do we solve this?<\/p>\n","protected":false},"author":7,"featured_media":5052,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","inline_featured_image":false,"footnotes":""},"categories":[19],"tags":[28],"ppma_author":[9],"class_list":["post-1668","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-api"],"acf":[],"authors":[{"term_id":9,"user_id":7,"is_guest":0,"slug":"ivan","display_name":"Ivan Guardado","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/c95af420757b70c1e5d8a8ae3cc42ea79d5748ae5cba704c244b30c683e20b27?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/posts\/1668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/comments?post=1668"}],"version-history":[{"count":2,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/posts\/1668\/revisions"}],"predecessor-version":[{"id":5093,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/posts\/1668\/revisions\/5093"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/media\/5052"}],"wp:attachment":[{"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/media?parent=1668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/categories?post=1668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/tags?post=1668"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.devengo.com\/en\/wp-json\/wp\/v2\/ppma_author?post=1668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}