Testando a integração com APIs - RSonRails/11

45
Testando a integração com APIs e serviços externos Dicas sobre como testar integrações. @rafaelss http://rafaelss.com - http://softa.com.br 1

description

Slides da palestra dada no RS on Rails de 2011 sobre como testar a integração de aplicações com serviços de terceiros como Twitter, Facebook e outros

Transcript of Testando a integração com APIs - RSonRails/11

Testando a integração com APIs e serviços

externosDicas sobre como testar integrações.

@rafaelsshttp://rafaelss.com - http://softa.com.br

1

Muitas aplicações integram com algum tipo de

serviço externo

2

Twitter, Facebook, Google Accounts, Foursquare, Flickr, Moip, Pagseguro

3

Ou ainda: APIs de sistemas internos, sistemas legados,

scrapers, upload de conteúdo, ...

4

E tudo isso, tem que ser testado

5

Sem testes a integração pode ficar quebrada

por um bom tempo

6

Em algum momento alguma das pontas

vai mudar

7

Então, teste!

8

Depender desses serviços na hora de rodar os testes é

ruim

9

Depender da conexão com a

internet na hora de rodar os testes é

ruim

10

Ter que esperar uma suite de testes gigante

fazer todos os requests necessários ao rodar os testes é

muito ruim

11

Testes devem rodar offline

12

•OmniAuth

•WebMock

•Apigee

•VCR

•Artifice

13

“OmniAuth is an authentication framework that separates the concept of authentication from the concept of identity, providing simple

hooks for any application to have one or multiple authentication providers for a user”

https://rubygems.org/gems/omniauth

OmniAuth

14

1 # config/initializers/omniauth.rb 2 Rails.application.config.middleware.use OmniAuth::Builder do 3 provider :twitter, "key", "secret" 4 provider :facebook, "key", "secret", :scope => "email" 5 provider :linked_in, "key", "secret" 6 end 7 8 # test/test_helper.rb 9 OmniAuth.config.test_mode = true10 11 OmniAuth.config.mock_auth[:twitter] = {12 'uid' => '123545'13 # etc.14 }15 16 # test/functional/signup_test.rb17 test "..." do18 get "/auth/twitter"19 # ...20 end21 22 # test/functional/anything_test.rb23 setup do24 OmniAuth.config.add_mock(:facebook, :uid => '54321')25 end

15

Não preciso fazer stubs de requests

16

Autenticação testada

corretamente

17

Testes rodando muito rápido

18

WebMock

“WebMock allows stubbing HTTP requests and setting expectations on HTTP requests”

https://rubygems.org/gems/webmock

19

1 stub_request( 2 :get, 3 "https://graph.facebook.com/oauth/access_token" 4 ).with( 5 :query => { 6 :client_id => "client id", 7 :client_secret => "client secret", 8 :grant_type => "client_credentials" 9 }10 ).to_return(11 :body => "access_token=a1b2c3du4e5"12 )13 14 stub_request(15 :post,16 "https://api.twitter.com/1/statuses/update.json"17 ).with(18 :query => {19 :status => "hello #rsonrails"20 }21 ).to_return(22 :status => 200,23 :body => "{\"id\":83174481385556480}"24 )25 26 stub_request(27 :put,28 /s3\.amazonaws\.com/29 )

20

Evita mocks em código de terceiros

21

1 Twitter2 .should_receive(:update)3 .with("hello @rsonrails")4 .and_return('{"id":"1231313121313"}')

22

Mantém minha suite longe a

internet

23

WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://graph.facebook.com:443/oauth/access_token?client_id=112121312&client_secret=56757657655&grant_type=client_credentials with headers {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}

You can stub this request with the following snippet:

stub_request(:get, "http://graph.facebook.com:443/oauth/access_token?client_id=112121312&client_secret=56757657655&grant_type=client_credentials"). with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}). to_return(:status => 200, :body => "", :headers => {})

24

1 WebMock.disable_net_connect!(:allow_localhost => true)

25

Suporta diversos clientes HTTP

26

Necessita capturar os responses manualmente

27

Apigee

Free API tools for developers and providers

https://apigee.com/console

28

29

Mais prático que usar cURL

30

VCR

“VCR provides a simple API to record and replay your test suite's HTTP interactions. It works with a variety of HTTP client libraries,

HTTP stubbing libraries and testing frameworks”

https://rubygems.org/gems/vcr

31

1 # test/test_helper.rb 2 VCR.config do |c| 3 c.cassette_library_dir = 'fixtures/vcr_cassettes' 4 c.stub_with :webmock 5 end 6 7 # test/integration/signup_test.rb 8 VCR.use_cassette('facebook_access_token') do 9 uri = URI('https://graph.facebook.com/oauth/access_token')10 response = Net::HTTP.get_response(uri)11 assert_match /access_token=.+/, response.body12 end

32

É a opção mais prática

33

Elimina o trabalho de coletar os

responses

34

Permite atualizar automaticamente

os cassettes

35

1 A_WEEK = 7 * 24 * 60 * 602 3 VCR.use_cassette('my_cassette', :re_record_interval => A_WEEK) do4 # make an HTTP request5 end

36

“Replaces Net::HTTP with a subclass that routes all requests to a Rack application”

https://rubygems.org/gems/artifice

Artifice

37

1 # test/support/signup_app.rb 2 class SignupApp 3 def call(env) 4 if env["PATH_INFO"] == "/oauth/access_token" 5 [200, {}, "access_token=a1b2c3d4e5"] 6 end 7 end 8 end 9 10 # test/integration/signup_test.rb11 Artifice.activate_with(SignupApp) do12 uri = URI('https://graph.facebook.com/oauth/access_token')13 response = Net::HTTP.get_response(uri)14 assert_match /access_token=.+/, response.body15 end

38

Permite que uma ou várias apps rack-based respondam

pelos requests

39

Muita flexibilidade nos testes

40

Pode ser bem trabalhoso

41

Ainda é só uma idéia

42

Use em um pet-project

43

Pode ajudar a aprender mais

sobre Testes, Stubs, HTTP Requests e apps Rack-based

44

@rafaelss

Obrigado!

45