Skip to content

Instantly share code, notes, and snippets.

@jonah-williams
Created April 21, 2011 16:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonah-williams/934902 to your computer and use it in GitHub Desktop.
Save jonah-williams/934902 to your computer and use it in GitHub Desktop.
Instrumenting rspec and using a custom formatter to generate API docs from specs. See http://blog.carbonfive.com/2011/04/21/generating-documentation-from-specs/
require 'rubygems'
require 'rspec/core/rake_task'
namespace :project_name do
namespace :api do
desc 'Generate API request documentation from API specs'
RSpec::Core::RakeTask.new('generate_docs') do |t|
t.pattern = 'spec/controllers/api/**/*_spec.rb'
t.rspec_opts = ["-Ilib/tasks/api_docs", "-rinstrument_specs", "-rapi_formatter", "--format APIFormatter"]
end
end
end
require 'rspec/core/formatters/base_formatter'
class APIFormatter < RSpec::Core::Formatters::BaseFormatter
def initialize(output)
super(output)
end
def example_group_started(example_group)
indented_message("#{example_group.description}\n", example_group)
end
def example_group_finished(example_group)
end
def example_started(example)
indented_message("#{example.description}\n", example)
end
def example_passed(example)
indented_message("#{example.metadata[:curl]}\n")
indented_message("#{example.metadata[:response]}\n\n")
end
def example_failed(example)
end
def example_pending(example)
end
private
def indented_message(message, context = nil)
if context.present?
if context.respond_to?(:example_group)
(context.example_group.ancestors.count + 1).times do
output << '#'
end
else
context.ancestors.count.times do
output << '#'
end
end
else
output << ' '
end
output << message
end
end
require 'action_dispatch'
require 'action_controller'
module InstrumentSpecs
module ::ActionController::TestCase::Behavior
alias_method :process_without_logging, :process
def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
version, route = described_class.to_s.match(/::(V\d)::(\S+)Controller/)[1..2].collect(&:downcase)
curl = "curl "
parameters.each {|key, value| curl << "-d \"#{key}=#{CGI.escape(value)}\" " } if parameters.present?
curl << "-X #{http_method} "
curl << "https://api.host.example/#{version}/#{route} "
example.metadata[:curl] = curl
response = process_without_logging(action, parameters, session, flash, http_method)
example.metadata[:response] = "#{response.status} #{response.body}"
response
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment