Download - Testing Services Effectively
![Page 1: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/1.jpg)
TESTING SERVICESeffectively
Alberto Leal @albertoleal
![Page 2: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/2.jpg)
http://albertoleal.me
![Page 3: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/3.jpg)
![Page 4: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/4.jpg)
What is a service?
![Page 5: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/5.jpg)
ExternalService
Internal Service
![Page 6: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/6.jpg)
ad$
A
![Page 7: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/7.jpg)
http://api.example.com/cars
Request Response
![Page 8: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/8.jpg)
Connection: keep-aliveContent-Length: 1466Content-Type: application/json; Date: Sat, 02 Aug 2014 19:42:38 GMTETag: 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
![Page 9: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/9.jpg)
Connection: keep-aliveContent-Length: 1466Content-Type: application/json; Date: Sat, 02 Aug 2014 19:42:38 GMTETag: 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
![Page 10: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/10.jpg)
Connection: keep-aliveContent-Length: 1466Content-Type: application/json; Date: Sat, 02 Aug 2014 19:42:38 GMTETag: 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
![Page 11: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/11.jpg)
![Page 12: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/12.jpg)
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
![Page 13: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/13.jpg)
gem 'webmock'
https://github.com/bblimke/webmock
![Page 14: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/14.jpg)
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) endend
![Page 15: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/15.jpg)
------------------------------ 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 => {})
![Page 16: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/16.jpg)
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) endend
![Page 17: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/17.jpg)
![Page 18: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/18.jpg)
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.') endend
![Page 19: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/19.jpg)
gem 'vcr'gem 'vcr'
https://github.com/vcr/vcr
![Page 20: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/20.jpg)
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 } endend
![Page 21: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/21.jpg)
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
![Page 22: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/22.jpg)
gem 'puffing-billy'
https://github.com/oesmith/puffing-billy
![Page 23: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/23.jpg)
require ‘billy/rspec'!
Capybara.javascript_driver = :selenium_billy
![Page 24: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/24.jpg)
proxy.stub(‘http://api.example.com/cars').and_return(json: {cars: […]})
![Page 25: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/25.jpg)
IntegrationTests
Contract Tests
![Page 26: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/26.jpg)
Consumer-Driven Contracts: A Service Evolution Pattern
http://martinfowler.com/articles/consumerDrivenContracts.html
![Page 27: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/27.jpg)
![Page 28: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/28.jpg)
Contracts can couple
service providers and
consumers
![Page 29: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/29.jpg)
![Page 30: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/30.jpg)
![Page 31: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/31.jpg)
![Page 32: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/32.jpg)
![Page 33: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/33.jpg)
![Page 34: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/34.jpg)
gem 'pact'
https://github.com/realestate-com-au/pact
![Page 35: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/35.jpg)
class MyServiceProviderClient include HTTParty base_uri 'http://my-service'!
def get_something name = JSON.parse(self.class.get("/something").body)['name'] Something.new(name) endend
Client
![Page 36: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/36.jpg)
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 endend
Mock Server
![Page 37: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/37.jpg)
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
![Page 38: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/38.jpg)
thanks!http://albertoleal.me
![Page 39: Testing Services Effectively](https://reader033.vdocument.in/reader033/viewer/2022051323/54b79fec4a795993718b4698/html5/thumbnails/39.jpg)
https://www.flickr.com/photos/robsmits/5452184206
https://www.flickr.com/photos/hotcherry/521006473
Photos:
https://www.flickr.com/photos/vern/5379218273/sizes/l