测试 通过测试代码,自动生成 API 文档

ThxFly · 2018年07月09日 · 最后由 ThxFly 回复于 2018年07月09日 · 1321 次阅读

前言

手动修改API文档好麻烦,如果能自动生成那该有多好😄

用到的Gem: pry-rails

0.最终的Redmine文档如下

获取手环数据列表-list_wristband

请求: GET /api/v2/wristbands/list_wristband

参数校验:

 # action内的每个#号开头的注释,required optional开头的代码行都会写入文档,你可以写任何东西
required(:b_user_id, :String)
optional(:search_begin_at, :Timestamp) # 数据起始时间
optional(:search_end_at, :Timestamp) # 数据结束时间

参数:

{
  "b_user_id": 3793,
  "search_begin_at": 1526745600,
  "search_end_at": 1529424000
}

返回值:

{
  "status_code": "20000",
  "status_message": "ok",
  "data": {
    "wristbands": [
      {
        "id": 1,
        "b_user_id": 3793,
        "day_time_stamp": 1529424000,
        "distance": 0.0,
        "walk_step": 0,
        "cardiopul_monary_exercise": 0,
        "fat_exercise": 0
      },
    "timestamp": 1526745600
  }
}
......

1. 书写控制器代码

app/controllers/api/v2/wristbands_controller.rb

class Api::V2::WristbandsController < Api::V2::BaseController
  def list_wristband
    # action内的每个#号开头的注释,required optional开头的代码行都会写入文档,你可以写任何东西
    required(:b_user_id, :String)
    optional(:search_begin_at, :Timestamp) # 数据起始时间
    optional(:search_end_at, :Timestamp) # 数据结束时间
    render_json Api::V2::WristbandsService.list_wristband(params)
  end
end

2. 书写测试代码

test/controllers/api/v2/wristbands_controller_test.rb

require 'test_helper'

class Api::V2::WristbandsControllerTest < ActionDispatch::IntegrationTest
  setup do
    @wristband = wristbands(:one)
  end

  test 'list_wristband' do
    method = :get
    url = list_wristband_api_v2_wristbands_url
    params = { b_user_id: 3793, search_begin_at: Time.new(2018, 5, 20).to_i, search_end_at: Time.new(2018, 6, 20).to_i }
    send_request(method, url, params)
    params = { b_user_id: 3793 }
    send_request(method, url, params, generate_doc_flag: false)
  end
end

3. 定义生成文档的方法

test/test_helper.rb

......
class ActionDispatch::IntegrationTest
  def doc_logger
    @doc_logger = Logger.new("#{Rails.root}/doc/api_v2.textile")
    @doc_logger.formatter = proc do |_severity, _datetime, _progname, msg|
      "#{msg}\n"
    end
    @doc_logger
  end

  def send_request(method, url, params, generate_doc_flag: true, code: '20000')
    send(method, url, params: params)
    assert_success(code)
    generate_doc(method, params) if generate_doc_flag
  end

  def assert_success(code)
    assert_equal code, body['status_code']
  end

  def body
    JSON.parse(@response.body) || {}
  end

 # NOTE 这一步是关键
  def generate_doc(method, params)
    # 非生产环境下引入pry-rails gem
    method_location = ::MethodSource.source_helper(@controller.class.new.method(@controller.action_name).source_location)
   # action内的每个#号开头的注释,required optional开头的代码行都会写入文档,你可以写任何东西
    detail = method_location.split("\n").map { |x| x[/^\s+(#.*)|(required.*)|(optional.*)/] }.compact.join("\n")
    doc_logger.info <<~HTML
      h1. #{I18n.t(@controller.action_name, scope: 'action_name', locale: 'zh-CN')}-#{@controller.action_name}

      请求: #{method.upcase} #{@request.path}
      参数校验:
      <pre>
      <code class="ruby">
      #{detail}
      </code>
      </pre>

      参数:
      <pre>
      <code class="json">
      #{JSON.pretty_generate(params)}
      </code>
      </pre>

      返回值:
      <pre>
      <code class="json">
      #{JSON.pretty_generate(body) if @response.content_type == 'application/json'}
      </code>
      </pre>
    HTML
  end
end

4. 书写Rake任务

lib/tasks/testdoc.rake

namespace :test do
  task doc: :environment do
    `echo "{{TOC}}\n" > doc/api_v2.textile`
    dir = 'test/controllers/api/v2/'
    order_controllers = %w[
      wristbands_controller_test.rb
      users_controller_test.rb
      device_binds_controller_test.rb
      feedbacks_controller_test.rb
      commons_controller_test.rb
    ]
    order_controllers.each do |x|
      `rails test #{dir}#{x}`
    end
  end
end

5. 修改Rails的测试顺序

Rails的测试顺序只支持:random和:alpha,修改为:alpha

6. 执行rake任务

# rails test  // 最好先测试通过后再生成文档
rails test:doc

这是一种写api文档的思路, 希望大家喜欢。

共收到 2 条回复

楼主知道 apipie 么

guyanbiao 回复

知道,用过后发现不好用。它不能自动生成响应,而且感觉没有在Redmine上来得好用

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册