Post in continuation of the
topic of experimental solutions , from where the code will be reused for example. In the last post I covered the topic of how to write tests for a simple service, when it acts as a black box and from the test code we do not have direct access to the code of the program under test. Once again I’ll dwell on the fact that the test service was implemented in the Go language, and the tests for the service in the Ruby language and the framework for testing RSpec. The stack was chosen from its own preferences and has no key meaning to the topic in question. In this article I want to consider the issue of documenting the API, again using not quite a standard solution.
There are several basic approaches to writing documentation:
- Just write the documentation manually.
- Automatic generation of documentation for comments in the code.
- Automatic generation of documentation on the code.
In the first case, the disadvantages are obvious, you must manually maintain the documentation, besides the text of the documentation is separated from the code. In the second case, documentation is most often generated from comments to classes, methods, functions. In this case, it is much easier to maintain the actual description, besides there may be additional checks, such as the fact that the function signature matches the description of the parameters in the comment. Automatic code generation should eliminate the problem of supporting the actual description of API methods. These methods are widely used for documenting libraries. However, automatic generation is extremely rare for the WEB API, one of the possible reasons is that all such generators are framework dependent and require some reflection support from the web framework and programming language.
Now let's take a quick look at some less common ways of compiling (and using) documentation:
')
- We write machine-readable documentation; we generate the code for it, the code template for the server and the client.
- Having machine-readable documentation, we check in our tests that the behavior of the API matches the description in the documentation, for example, that the method's response corresponds to what is written in the documentation.
Immediately I will explain why the API documentation may be needed (including machine-readable ones) before the implementation of the API itself is written. Most often, this situation occurs when both the API server and client code are being developed simultaneously. Having machine-readable documentation at the client development stage, it is possible to generate both the client API itself and the server that emulates the real answers.
I also want to note that protocols such as GRPC, Apache Thrift and the like actually force you to first write (and then maintain) the machine-readable description of the API and only then write the implementation, which undoubtedly can bear some irritating effect of the need to constantly edit the protocol description files, but on the other hand, we are always confident that at least the description of the signatures corresponds to reality.
And the last (in this text) method of obtaining documentation:
- We generate the documentation to API methods on the real answer from the server. Requests to the server are encoded to the tests.
And this is the topic put up in the title. Since the test code is an integral part of the system under test, it is quite cheap to assign additional functionality to the tests. I will highlight the advantages of this method:
- Inside the documentation, we get 100% relevant examples of responses from API methods, and all possible use cases, if they are separately covered with tests.
- We can automatically generate documentation without making changes to the source code of the service. Thus, we are no longer dependent on auto documentation support for a specific framework or technology,
- In general, we may not have access to the source code of the service, but we may receive, including computer-readable documentation, and use all its advantages.
In this example, the
Swagger specification will be used to document the API, I omit the general description of this tool, since such reviews are sufficient. But I’ll note that this is a machine-readable documentation that allows you to generate both human documentation and templates for server and client code for working with the described API.
In the open spaces of the network,
rspec-rails-swagger and
rswag rubies were found. Both unfortunately have at least minimal, but binding to rails. The gems have quite detailed documentation with examples and fairly simple code. As an experiment, I untied the
rspec-rails-swagger gem from Rails and connected it to existing functional tests.
The test description for generating the method documentation is as follows:
describe 'swagger_docs' do let(:movies_resp_body) { File.read('spec/fixtures/movies.json') } path '/movies' do operation "GET", summary: "respond 200 OK" do parameter :rating, in: :query, type: :string, required: false, description: "filter by rating" response 200, description: "successful" do schema( type: :array, items: { type: :string, } ) end end end end
This code runs execution tests and uses the syntax extension Rspec to specify the meta information that will be used when generating the swagger file.
Run rspec through a long command:
bundle exec rspec -f RSpec::Rails::Swagger::Formatter --order defined -t swagger_object
The -t flag filters tests run only by those that use special heme syntax. The -f flag enables the “formatter” to output the result as a swagger json file.
The command output will produce a valid swagger file that can be loaded into swagger-ui or try to use it to generate a client to the API.
Ultimately, we have functional tests on the Rspec framework, generating swagger documentation along the way, from which you can quickly get a client API for any other programming language.
Full listing example .
Summarizing:
- Automatic documentation guarantees some minimal overlap of your expectations from the API and the harsh changeable reality.
- In some cases, the developer is physically forced to first describe the API methods and only then implement them (GRPC protocols, Apache Thrift).
- Automatically generated machine-readable documentation can simplify life at the design stage as well as at the support and operation stage of the API.
- Using special tools, you can generate machine-readable documentation without making changes to the source code.