My presentation about Test Driven Development of HTTP clients using WebMock, presented at RubyManor 2.
WebMock is a library for stubbing and setting expectations on HTTP requests in Ruby.
3. Hello http://my.geoservice.org
Give me location for zip code WC1H 9EF
GET http://my.geoservice.org/?zip=WC1H 9EF
HTTP 200 - OK
Content-Type: application/json
Here is your location:
{"latitude"=>"51.52","longitude":-0.12"}
new bamboo
4. describe GeoCoordinatesFinder do
it "should make http request to geocoding service" do
end
it "should report coordinates provided by geocoding service" do
end
end
new bamboo
5. describe GeoCoordinatesFinder do
it "should make http request to geocoding service" do
???
end
it "should report coordinates provided by geocoding service" do
???
end
end
new bamboo
8. class GeoCoordinatesFinder
def get_coordinates_by_zip_code(zip)
res = Net::HTTP.start("my.geoservice.org", 80) { |http|
http.get("/?zip=#{URI.encode(zip)}")
}
result = JSON.parse(res)
[result['latitude'], result['longitude']]
end
end
new bamboo
9. describe GeoCoordinatesFinder do
before(:each) do
@coordinates_finder = GeoCoordinatesFinder.new
@mock_http = mock("http")
@res = mock(Net::HTTPOK, :body => "{"latitude":"5.5","longitude":"6.6"}")
Net::HTTP.stub!(:start).with("my.geoservice.org", 80).and_yield @mock_http
@mock_http.stub!(:get).with("/?zip=WC1H%209EF").and_return(@res)
end
it "should make http request to geocoding service" do
Net::HTTP.should_receive(:start).and_yield @mock_http
@mock_http.should_receive(:get).with("/?zip=WC1H%209EF")
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF")
end
it "should report coordinates provided by geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").should == ["5.5", "6.6"]
end
end
new bamboo
11. class GeoCoordinatesFinder
def get_coordinates_by_zip_code(zip)
url = "http://my.geoservice.org?zip=#{URI.encode(zip)}"
response = RestClient.get(url)
result = JSON.parse(response)
[result['latitude'], result['longitude']]
end
end
new bamboo
13. describe GeoCoordinatesFinder do
before(:each) do
@coordinates_finder = GeoCoordinatesFinder.new
RestClient.stub!(:get).with("http://my.geoservice.org?zip=WC1H%209EF").
and_return("{"latitude":"5.5","longitude":"6.6"}")
end
it "should make http request to yahoo geocoding service" do
RestClient.should_receive(:get).with("http://my.geoservice.org?zip=WC1H%209EF")
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF")
end
it "should report coordinates provided by geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").should == ["5.5", "6.6"]
end
end
new bamboo
14. I wanted a tool for stubbing
HTTP requests that...
15. I wanted a tool for stubbing
HTTP requests that...
• doesn’t depend on usage of a specific API
16. I wanted a tool for stubbing
HTTP requests that...
• doesn’t depend on usage of a specific API
• supports stubbing based on request
method, uri, body and headers
17. I wanted a tool for stubbing
HTTP requests that...
• doesn’t depend on usage of a specific API
• supports stubbing based on request
method, uri, body and headers
• verifies expectations of requests
18. I wanted a tool for stubbing
HTTP requests that...
• doesn’t depend on usage of a specific API
• supports stubbing based on request
method, uri, body and headers
• verifies expectations of requests
• supports different HTTP libraries
20. require 'webmock/rspec'
include WebMock
describe GeoCoordinatesFinder do
before(:each) do
@coordinates_finder = GeoCoordinatesFinder.new
stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF").
to_return(:body => "{"latitude":"5.5","longitude":"6.6"}")
end
it "should make http request to geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF")
WebMock.should have_requested(:get, "http://my.geoservice.org?zip=WC1H 9EF")
end
it "should report coordinates provided by geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").
should == ["5.5", "6.6"]
end
end
new bamboo
21. require 'webmock/rspec'
include WebMock
describe GeoCoordinatesFinder do
before(:each) do
@coordinates_finder = GeoCoordinatesFinder.new
stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF").
to_return(:body => "{"latitude":"5.5","longitude":"6.6"}")
end
it "should make http request to geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF")
WebMock.should have_requested(:get, "http://my.geoservice.org?zip=WC1H 9EF")
end
it "should report coordinates provided by geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").
should == ["5.5", "6.6"]
end
end
new bamboo
22. require 'webmock/rspec'
include WebMock
describe GeoCoordinatesFinder do
before(:each) do
@coordinates_finder = GeoCoordinatesFinder.new
stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF").
to_return(:body => "{"latitude":"5.5","longitude":"6.6"}")
end
it "should make http request to geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF")
WebMock.should have_requested(:get, "http://my.geoservice.org?zip=WC1H 9EF")
end
it "should report coordinates provided by geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").
should == ["5.5", "6.6"]
end
end
new bamboo
23. require 'webmock/rspec'
include WebMock
describe GeoCoordinatesFinder do
before(:each) do
@coordinates_finder = GeoCoordinatesFinder.new
stub_request(:get, "http://my.geoservice.org?zip=WC1H 9EF").
to_return(:body => "{"latitude":"5.5","longitude":"6.6"}")
end
it "should make http request to geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF")
request(:get, "http://my.geoservice.org?zip=WC1H 9EF").should have_been_made
end
it "should report coordinates provided by geocoding service" do
@coordinates_finder.get_coordinates_by_zip_code("WC1H 9EF").
should == ["5.5", "6.6"]
end
end
new bamboo
25. class GeoCoordinatesFinder
def get_coordinates_by_zip_code(zip)
uri = "http://my_geoservice.org?zip=#{URI.encode(zip)}"
result = JSON.parse(HTTPClient.new.get(uri).content)
[result['latitude'], result['longitude']]
end
end
new bamboo
30. Cucumber
features/finding_geo_coordinates.feature
Feature: Finding the way to an awesome conference
In order to find the best way to Ruby Manor
As a ruby geek
I want to see how to get there on a map
Scenario: User finds zip code coordinates on a map
Given geoservice reports coordinates "51.52, -0.12" for zip code "WC1H 9EF"
When I type "WC1H 9EF" into zip code field
And I press "Show on map"
Then I should see map centered at latitude "51.52" and longitude "-0.12"
new bamboo
31. Cucumber
features/step_definitions/geocoding_service_steps.rb
Given /^geoservice reports (.+), (.+) as coordinates for zip code (.+)$/ do
|lat, long, zip_code|
stub_request(:get, "http://my.geoservice.org?zip=#{zip_code}").
to_return(
:body => "{"latitude":"#{lat}","longitude":"#{long}"}"
)
end
new bamboo
32. Matching Requests
on Body and Headers
stub_request(:post, "www.example.net").
with(:body => "abc", :headers => { :content_type => 'text/plain' })
RestClient.post "www.example.net", "abc", :content_type => 'text/plain'
WebMock.should have_requested(:post, "www.example.net").
with(:body => "abc", :headers => { 'Content-Type' => 'text/plain' })
new bamboo
Hi. I’m Bartosz Blimke. I’m work for New Bamboo, a development shop. We are working in a rigorous agile environment and we also offer agile coaching.
I’ve been working in Extreme Programming environments for the last 5 years, on small projects as well as on very big corporate projects.
One of the code XP practices is ....
is test driven development. I’m doing TDD for about 3 or 4 years now.
none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features
none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features
none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features
none of the tools I found offered these features, and non of the tools I found were easily extandable to implement these features