Back to Repositories

Testing Geocoding Result Validation in alexreisner/geocoder

This test suite validates the core functionality of geocoding results in the Geocoder gem, ensuring both forward and reverse geocoding operations return properly formatted location data with required attributes. The tests verify consistent behavior across multiple geocoding service providers.

Test Coverage Overview

The test suite provides comprehensive coverage of geocoding result attributes across multiple service providers. Key functionality tested includes:

  • Forward geocoding with location name input
  • Reverse geocoding with coordinate pairs
  • Required attribute validation for all supported services
  • Service-specific implementations (e.g. Amazon Location Service place_id)

Implementation Analysis

The testing approach uses a systematic service iteration pattern, testing each geocoding provider individually while excluding unsupported services. The implementation leverages Ruby’s test framework with custom assertions for attribute validation.

Technical patterns include:
  • Service-specific configuration management
  • Attribute type checking
  • Non-zero coordinate validation
  • Standardized error messaging

Technical Details

Testing tools and configuration:

  • Ruby test framework with GeocoderTestCase base class
  • Custom assertion methods for result validation
  • Service-specific API key configuration
  • UTF-8 encoding enforcement
  • Modular test organization with private helper methods

Best Practices Demonstrated

The test suite exemplifies several testing best practices for geocoding implementations:

  • Comprehensive service provider coverage
  • Explicit handling of service limitations and exceptions
  • Structured attribute validation
  • Clear error messaging with service context
  • DRY implementation through shared assertion methods

alexreisner/geocoder

test/unit/result_test.rb

            
# encoding: utf-8
require 'test_helper'

class ResultTest < GeocoderTestCase

  def test_forward_geocoding_result_has_required_attributes
    Geocoder::Lookup.all_services_except_test.each do |l|
      next if [
        :ip2location, # has pay-per-attribute pricing model
        :ip2location_io, # has pay-per-attribute pricing model
        :ip2location_lite, # no forward geocoding
        :twogis, # cant find 'Madison Square Garden'
      ].include?(l)

      Geocoder.configure(:lookup => l)
      set_api_key!(l)
      result = Geocoder.search("Madison Square Garden").first
      assert_result_has_required_attributes(result)
      assert_aws_result_supports_place_id(result) if l == :amazon_location_service
    end
  end

  def test_reverse_geocoding_result_has_required_attributes
    Geocoder::Lookup.all_services_except_test.each do |l|
      next if [
        :ip2location, # has pay-per-attribute pricing model
        :ip2location_io, # has pay-per-attribute pricing model
        :ip2location_lite, # no reverse geocoding
        :nationaal_georegister_nl, # no reverse geocoding
        :melissa_street, # reverse geocoding not implemented
        :twogis, # cant find 'Madison Square Garden'
      ].include?(l)

      Geocoder.configure(:lookup => l)
      set_api_key!(l)
      result = Geocoder.search([45.423733, -75.676333]).first
      assert_result_has_required_attributes(result)
    end
  end

  private # ------------------------------------------------------------------

  def assert_result_has_required_attributes(result)
    m = "Lookup #{Geocoder.config.lookup} does not support %s attribute."
    assert result.coordinates.is_a?(Array),    m % "coordinates"
    assert result.latitude.is_a?(Float),       m % "latitude"
    assert result.latitude != 0.0,             m % "latitude"
    assert result.longitude.is_a?(Float),      m % "longitude"
    assert result.longitude != 0.0,            m % "longitude"
    assert result.city.is_a?(String),          m % "city"
    assert result.state.is_a?(String),         m % "state"
    assert result.state_code.is_a?(String),    m % "state_code"
    assert result.province.is_a?(String),      m % "province"
    assert result.province_code.is_a?(String), m % "province_code"
    assert result.postal_code.is_a?(String),   m % "postal_code"
    assert result.country.is_a?(String),       m % "country"
    assert result.country_code.is_a?(String),  m % "country_code"
    assert_not_nil result.address,             m % "address"
  end

  def assert_aws_result_supports_place_id(result)
    assert result.place_id.is_a?(String)
  end
end