Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing APIs - Guru SP

Testing APIs - Guru SP

Rodrigo Flores

June 22, 2013
Tweet

More Decks by Rodrigo Flores

Other Decks in Technology

Transcript

  1. I’ve been on both sides... Aplicações sem “Banco” (SOA) API

    para aplicações móveis API para aplicações sem Banco Saturday, June 22, 13
  2. API para aplicações Mobile API para aplicações web baseadas em

    serviços Aplicações Web baseadas em serviço Saturday, June 22, 13
  3. “Multi-ambiente” aware Em desenvolvimento, não deve ter efeito Em teste

    não deve acessar nada Em produção deve funcionar Saturday, June 22, 13
  4. require 'net/http' require 'json' uri = URI.parse('https://api.github.com/users/ rodrigoflores/repos') http =

    Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri.request_uri) response = http.request(request) repos = JSON.parse(response.body) repos.each do |repo| puts repo['name'] end Saturday, June 22, 13
  5. # encoding: utf-8 require 'net/http' require 'json' require 'webmock' include

    WebMock::API stub_request(:get, "https://api.github.com/users/rodrigoflores/ repos"). to_return(body: File.read('response.json')) uri = URI.parse('https://api.github.com/users/rodrigoflores/ repos') http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri.request_uri) response = http.request(request) repos = JSON.parse(response.body) repos.each do |repo| puts repo['name'] end Saturday, June 22, 13
  6. Real HTTP connections are disabled. Unregistered request: GET https:// api.github.com/users/bioritmo/repos

    with headers {'Accept'=>'*/*', 'User- Agent'=>'Ruby'} (WebMock::NetConnectNotAllowedError) You can stub this request with the following snippet: stub_request(:get, "https://api.github.com/users/bioritmo/repos"). with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}). to_return(:status => 200, :body => "", :headers => {}) registered request stubs: stub_request(:get, "https://api.github.com/users/rodrigoflores/repos") ============================================================ from request_fakeweb.rb:16:in `<main>' É possível desativar e permitir requests HTTP Saturday, June 22, 13
  7. 1ª Vez: Faz o Request e grava 2ª-nª Vez: Reproduz

    o que foi gravado Saturday, June 22, 13
  8. uri = URI.parse('https://api.github.com/users/ rodrigoflores/repos') http = Net::HTTP.new(uri.host, uri.port) http.use_ssl =

    true request = Net::HTTP::Get.new(uri.request_uri) VCR.use_cassette('repos') do response = http.request(request) repos = JSON.parse(response.body) repos.each do |repo| puts repo['name'] end end Saturday, June 22, 13
  9. --- http_interactions: - request: method: get uri: https://api.github.com/users/ rodrigoflores/repos body:

    encoding: US-ASCII string: "" headers: Accept: - "*/*" User-Agent: - Ruby response: (...) recorded_at: Sun, 16 Jun 2013 16:00:06 GMT recorded_with: VCR 2.5.0 Saturday, June 22, 13
  10. --- http_interactions: - request: (...) response: status: code: 200 message:

    OK headers: (...) body: encoding: ASCII-8BIT string: "[{\"id\":1254869,\"name\":\"1001\", \"full_name\":\"rodrigoflores/1001\", (...)" http_version: recorded_at: Sun, 16 Jun 2013 16:00:06 GMT recorded_with: VCR 2.5.0 Saturday, June 22, 13
  11. require 'net/http' require 'json' require 'faraday' require 'faraday_middleware' conn =

    Faraday.new(:url => 'https://api.github.com') do |faraday| faraday.adapter Faraday.default_adapter faraday.response :json, :content_type => /\bjson$/ end repos = conn.get('/users/rodrigoflores/repos').body repos.each do |repo| puts repo['name'] end Saturday, June 22, 13
  12. require 'net/http' require 'json' require 'faraday' require 'faraday_middleware' conn =

    Faraday.new(:url => 'https://api.github.com') do | faraday| faraday.adapter :test do |stub| stub.get('/users/rodrigoflores/repos') do [ 200, { 'Content-Type' => 'application/json; charset=utf-8' }, File.read('response.json') ] end end faraday.response :json, :content_type => /\bjson$/ end repos = conn.get('/users/rodrigoflores/repos').body repos.each do |repo| puts repo['name'] end Saturday, June 22, 13
  13. Decidir qual o melhor jeito de testar Testar o cliente

    como uma aplicação Ruby Tomar cuidado para não fazer requests em teste (pelo menos não o tempo todo) Testes de contrato valem a pena? Saturday, June 22, 13
  14. class ExampleController < ApplicationController def index expires_in 10.minutes, public: true

    render json: { version: '3.2.19' } end end Saturday, June 22, 13
  15. require 'spec_helper' describe ExampleController do describe "GET #index" do it

    "shows the version info" do get :index parsed_response = JSON.parse(response.body) parsed_response['version'].should == '3.2.19' end it "has a max-age of 10 minutes" do get :index response.headers['Cache-Control'].should == "max- age=600, public" end it 'has a 200 status' do get :index response.status.should == 200 end end end Saturday, June 22, 13
  16. Testar com testes de controller Testar headers e status code

    (quando forem relevantes) Manter documentação atualizada! Saturday, June 22, 13