• Like
Testing Services Effectively
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Testing Services Effectively

  • 44 views
Published

Testing Services Effectively with Ruby

Testing Services Effectively with Ruby

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
44
On SlideShare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
1
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. TESTING SERVICES effectively Alberto Leal @albertoleal
  • 2. http://albertoleal.me
  • 3. What is a service?
  • 4. External
 Service Internal Service
  • 5. ad$ A
  • 6. http://api.example.com/cars Request Response
  • 7. Connection: keep-alive Content-Length: 1466 Content-Type: application/json; Date: Sat, 02 Aug 2014 19:42:38 GMT ETag: W/"5ba-70348105" { "cars": [ { "created": "2014-07-25T19:27:56.919Z", "id": "53d2afbc7165355f0eaf79da", "modified": "2014-07-25T19:27:56.919Z", "name": "Ferrari" }, { "created": "2014-07-25T19:27:56.874Z", "id": "53d2afbc7165355f0eaf79d9", "modified": "2014-07-25T19:27:56.874Z", "name": "Porshe" } ] } Request Response http://api.example.com/cars
  • 8. Connection: keep-alive Content-Length: 1466 Content-Type: application/json; Date: Sat, 02 Aug 2014 19:42:38 GMT ETag: W/"5ba-70348105" { "cars": [ { "created": "2014-07-25T19:27:56.919Z", "id": "53d2afbc7165355f0eaf79da", "modified": "2014-07-25T19:27:56.919Z", "name": "Ferrari" }, { "created": "2014-07-25T19:27:56.874Z", "id": "53d2afbc7165355f0eaf79d9", "modified": "2014-07-25T19:27:56.874Z", "name": "Porshe" } ] } headers
  • 9. Connection: keep-alive Content-Length: 1466 Content-Type: application/json; Date: Sat, 02 Aug 2014 19:42:38 GMT ETag: W/"5ba-70348105" { "cars": [ { "created": "2014-07-25T19:27:56.919Z", "id": "53d2afbc7165355f0eaf79da", "modified": "2014-07-25T19:27:56.919Z", "name": "Ferrari" }, { "created": "2014-07-25T19:27:56.874Z", "id": "53d2afbc7165355f0eaf79d9", "modified": "2014-07-25T19:27:56.874Z", "name": "Porshe" } ] } body
  • 10. Failures: ! 1) Car Service should retrieve all cars Failure/Error: response = RestClient.get ‘api.example.com/cars' SocketError: getaddrinfo: nodename nor servname provided, or not known # ./test_spec.rb:12:in `block (2 levels) in <top (required)>' ! Finished in 0.02436 seconds (files took 0.81924 seconds to load) 1 example, 1 failure ! Failed examples: ! rspec ./test_spec.rb:11 # External Service should retrieve all cars
  • 11. gem 'webmock' https://github.com/bblimke/webmock
  • 12. require 'webmock/rspec' require 'rest_client' ! describe 'Car Service’ do it 'should retrieve all cars' do response = RestClient.get ‘api.example.com/cars' expect(response).to be_an_instance_of(String) end end
  • 13. ------------------------------ FAIL: 1 PASS: 0 PENDING: 0 ------------------------------ Finished in 0.04571 seconds [Car Service] - should retrieve all cars Real HTTP connections are disabled. Unregistered request: GET http:// api.example.com/cars with headers {'Accept'=>'*/*; q=0.5, application/ xml', 'Accept-Encoding'=>'gzip, deflate', 'User-Agent'=>'Ruby'}You can stub this request with the following snippet:stub_request(:get, “http:// api.example.com/cars”). with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'User- Agent'=>'Ruby'}). to_return(:status => 200, :body => "", :headers => {})
  • 14. require 'webmock/rspec' require 'rest_client' ! WebMock.allow_net_connect! ! describe 'Car Service' do it 'should retrieve all cars' do response = RestClient.get ‘api.example.com/cars' expect(response).to be_an_instance_of(String) end end
  • 15. require 'webmock/rspec' require 'rest_client' ! # WebMock.allow_net_connect! ! describe 'Car Service' do before :all do stub_request(:get, ‘api.example.com/cars') .to_return(status: 200, headers: {}, body: 'This is a mock.') end ! it 'should retrieve all cars' do response = RestClient.get ‘http://api.example.com/cars' expect(response).to eq(‘This is a mock.') end end
  • 16. gem 'vcr'gem 'vcr' https://github.com/vcr/vcr
  • 17. ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'rspec/autorun' ! RSpec.configure do |config| config.mock_with :rspec config.infer_base_class_for_anonymous_controllers = false config.order = "random" ! #Configuring VCR gem config.around(:each, :vcr) do |example| opts = example.metadata.slice(:record, :match_requests_on).except(:example_group) VCR.use_cassette(example.metadata[:cassette_name], opts) { example.call } end end
  • 18. describe Car do ... describe '.all' do it 'should retrieve all available cars', :vcr, cassette_name: ‘cars/all’ do cars = Car.all expect(cars).to be_an_instance_of Array expect(cars).to have(2).items end end ! ... end
  • 19. gem 'puffing-billy' https://github.com/oesmith/puffing-billy
  • 20. require ‘billy/rspec' ! Capybara.javascript_driver = :selenium_billy
  • 21. proxy.stub(‘http://api.example.com/cars').and_return(json: {cars: […]})
  • 22. Integration
 Tests Contract Tests
  • 23. Consumer-Driven Contracts: A Service Evolution Pattern http://martinfowler.com/articles/consumerDrivenContracts.html
  • 24. Contracts can couple service providers and consumers
  • 25. gem 'pact' https://github.com/realestate-com-au/pact
  • 26. class MyServiceProviderClient include HTTParty base_uri 'http://my-service' ! def get_something name = JSON.parse(self.class.get("/something").body)['name'] Something.new(name) end end Client
  • 27. require 'pact/consumer/rspec' ! Pact.service_consumer "My Service Consumer" do has_pact_with "My Service Provider" do mock_service :my_service_provider do port 1234 end end end Mock Server
  • 28. describe MyServiceProviderClient, pact: true do ! before do # Configure your client to point to the stub service on localhost using the port you have specified MyServiceProviderClient.base_uri 'localhost:1234' end ! subject { MyServiceProviderClient.new } ! describe "get_something" do ! before do my_service_provider.given("something exists"). upon_receiving("a request for something").with(method: :get, path: '/something'). will_respond_with( status: 200, headers: {'Content-Type' => 'application/json'}, body: {name: 'A small something'} ) end ! it "returns a Something" do expect(subject.get_something).to eq(Something.new('A small something')) end ! end ! end
  • 29. thanks! http://albertoleal.me
  • 30. https://www.flickr.com/photos/robsmits/5452184206 https://www.flickr.com/photos/hotcherry/521006473 Photos: https://www.flickr.com/photos/vern/5379218273/sizes/l