Back to Repositories

Testing Google Geocoding Implementation in alexreisner/geocoder

This test suite validates the Google geocoding functionality in the Geocoder gem, focusing on address component parsing, result formatting, and API request handling.

Test Coverage Overview

The test suite provides comprehensive coverage of Google geocoding operations including:

  • Address component extraction and parsing
  • Geocoding result format validation
  • Location precision and boundary checks
  • URL parameter handling for API requests
  • HTTPS protocol verification

Implementation Analysis

The testing approach implements systematic validation of the Google geocoding lookup class, using Ruby’s Test::Unit framework. Tests verify both the parsing of Google API responses and proper formation of API requests with various parameters and configurations.

Technical Details

Key technical components include:

  • Test::Unit as the testing framework
  • WebMock for HTTP request stubbing
  • CGI for URL encoding validation
  • Custom test case inheritance from GeocoderTestCase

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test cases with clear, single-purpose assertions
  • Comprehensive edge case handling
  • Proper test setup and configuration management
  • Structured test organization by functionality

alexreisner/geocoder

test/unit/lookups/google_test.rb

            
# encoding: utf-8
require 'test_helper'

class GoogleTest < GeocoderTestCase

  def setup
    super
    Geocoder.configure(lookup: :google)
  end

  def test_google_result_components
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal "Manhattan",
      result.address_components_of_type(:sublocality).first['long_name']
  end

  def test_google_result_components_contains_route
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal "Penn Plaza",
      result.address_components_of_type(:route).first['long_name']
  end

  def test_google_result_components_contains_street_number
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal "4",
      result.address_components_of_type(:street_number).first['long_name']
  end

  def test_google_returns_city_when_no_locality_in_result
    result = Geocoder.search("no locality").first
    assert_equal "Haram", result.city
  end

  def test_google_city_results_returns_nil_if_no_matching_component_types
    result = Geocoder.search("no city data").first
    assert_equal nil, result.city
  end

  def test_google_street_address_returns_formatted_street_address
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal "4 Penn Plaza", result.street_address
  end

  def test_google_precision
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal "ROOFTOP",
      result.precision
  end

  def test_google_viewport
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal [40.7473324, -73.9965316, 40.7536276, -73.9902364],
      result.viewport
  end

  def test_google_bounds
    result = Geocoder.search("new york").first
    assert_equal [40.4773991, -74.2590899, 40.9175771, -73.7002721],
      result.bounds
  end

  def test_google_no_bounds
    result = Geocoder.search("Madison Square Garden, New York, NY").first
    assert_equal nil, result.bounds
  end

  def test_google_query_url_contains_bounds
    lookup = Geocoder::Lookup::Google.new
    url = lookup.query_url(Geocoder::Query.new(
      "Some Intersection",
      :bounds => [[40.0, -120.0], [39.0, -121.0]]
    ))
    assert_match(/bounds=40.0+%2C-120.0+%7C39.0+%2C-121.0+/, url)
  end

  def test_google_query_url_contains_region
    lookup = Geocoder::Lookup::Google.new
    url = lookup.query_url(Geocoder::Query.new(
      "Some Intersection",
      :region => "gb"
    ))
    assert_match(/region=gb/, url)
  end

  def test_google_query_url_contains_components_when_given_as_string
    lookup = Geocoder::Lookup::Google.new
    url = lookup.query_url(Geocoder::Query.new(
      "Some Intersection",
      :components => "locality:ES"
    ))
    formatted = "components=" + CGI.escape("locality:ES")
    assert url.include?(formatted), "Expected #{formatted} to be included in #{url}"
  end

  def test_google_query_url_contains_components_when_given_as_array
    lookup = Geocoder::Lookup::Google.new
    url = lookup.query_url(Geocoder::Query.new(
      "Some Intersection",
      :components => ["country:ES", "locality:ES"]
    ))
    formatted = "components=" + CGI.escape("country:ES|locality:ES")
    assert url.include?(formatted), "Expected #{formatted} to be included in #{url}"
  end

  def test_google_query_url_contains_result_type_when_given_as_string
    lookup = Geocoder::Lookup::Google.new
    url = lookup.query_url(Geocoder::Query.new(
      "Some Intersection",
      :result_type => "country"
    ))
    formatted = "result_type=" + CGI.escape("country")
    assert url.include?(formatted), "Expected #{formatted} to be included in #{url}"
  end

  def test_google_query_url_contains_result_type_when_given_as_array
    lookup = Geocoder::Lookup::Google.new
    url = lookup.query_url(Geocoder::Query.new(
      "Some Intersection",
      :result_type => ["country", "postal_code"]
    ))
    formatted = "result_type=" + CGI.escape("country|postal_code")
    assert url.include?(formatted), "Expected #{formatted} to be included in #{url}"
  end

  def test_google_uses_https_when_api_key_is_set
    Geocoder.configure(api_key: "deadbeef")
    query = Geocoder::Query.new("Madison Square Garden, New York, NY")
    assert_match(/^https:/, query.url)
  end

  def test_actual_make_api_request_with_https
    Geocoder.configure(use_https: true, lookup: :google)

    require 'webmock/test_unit'
    WebMock.enable!
    stub_all = WebMock.stub_request(:any, /.*/).to_return(status: 200)

    g = Geocoder::Lookup::Google.new
    g.send(:actual_make_api_request, Geocoder::Query.new('test location'))
    assert_requested(stub_all)

    WebMock.reset!
    WebMock.disable!
  end
end