Back to Repositories

Testing French Address Geocoding Implementation in Geocoder

This test suite validates the BAN Data Gouv FR geocoding service integration in the Geocoder gem, covering address lookup, reverse geocoding, and location data parsing. The tests ensure accurate French address processing and location data retrieval.

Test Coverage Overview

The test suite provides comprehensive coverage of the BAN Data Gouv FR geocoding service functionality, including:

  • Forward geocoding with address queries
  • Reverse geocoding with coordinates
  • Geographic priority handling
  • Special business logic for Paris addresses
  • Detailed location component parsing

Implementation Analysis

The testing approach employs Ruby’s Test::Unit framework with custom assertions for geocoding operations. The implementation validates API URL construction, response parsing, and data mapping to Ruby objects. WebMock is used for HTTP request testing.

Technical Details

Key technical components include:

  • GeocoderTestCase as the base test class
  • WebMock for HTTP request stubbing
  • HTTPS protocol validation
  • UTF-8 encoding support
  • Custom assertion methods for location verification

Best Practices Demonstrated

The test suite exemplifies testing best practices through:

  • Isolated test cases with proper setup/teardown
  • Comprehensive edge case coverage
  • Clear test method naming
  • Detailed assertion messages
  • Proper HTTP request mocking

alexreisner/geocoder

test/unit/lookups/ban_data_gouv_fr_test.rb

            
# encoding: utf-8
require 'test_helper'

class BanDataGouvFrTest < GeocoderTestCase

  def setup
    super
    Geocoder.configure(lookup: :ban_data_gouv_fr, use_https: true)
  end

  def test_query_for_geocode
    query = Geocoder::Query.new('13 rue yves toudic, 75010 Paris')
    lookup = Geocoder::Lookup.get(:ban_data_gouv_fr)
    res = lookup.query_url(query)
    assert_equal 'https://api-adresse.data.gouv.fr/search/?q=13+rue+yves+toudic%2C+75010+Paris', res
  end

  def test_query_for_geocode_with_geographic_priority
    query = Geocoder::Query.new('13 rue yves toudic, 75010 Paris', lat: 48.789, lon: 2.789)
    lookup = Geocoder::Lookup.get(:ban_data_gouv_fr)
    res = lookup.query_url(query)
    assert_equal 'https://api-adresse.data.gouv.fr/search/?lat=48.789&lon=2.789&q=13+rue+yves+toudic%2C+75010+Paris', res
  end

  def test_query_for_reverse_geocode
    query = Geocoder::Query.new([48.770639, 2.364375])
    lookup = Geocoder::Lookup.get(:ban_data_gouv_fr)
    res = lookup.query_url(query)
    assert_equal 'https://api-adresse.data.gouv.fr/reverse/?lat=48.770639&lon=2.364375', res
  end

  def test_results_component
    result = Geocoder.search('13 rue yves toudic, 75010 Paris').first
    assert_equal 'ADRNIVX_0000000270748760', result.location_id
    assert_equal 'housenumber', result.result_type
    assert_equal 'Paris', result.city_name
    assert_equal '13 Rue Yves Toudic 75010 Paris, France', result.international_address
    assert_equal '13 Rue Yves Toudic 75010 Paris, France', result.address
    assert_equal '13 Rue Yves Toudic 75010 Paris', result.national_address
    assert_equal '13 Rue Yves Toudic', result.street_address
    assert_equal '13', result.street_number
    assert_equal 'Rue Yves Toudic', result.street
    assert_equal 'Rue Yves Toudic', result.street_name
    assert_equal 'Paris', result.city
    assert_equal 'Paris', result.city_name
    assert_equal '75110', result.city_code
    assert_equal '75010', result.postal_code
    assert_equal '75', result.department_code
    assert_equal 'Paris', result.department_name
    assert_equal 'Île-de-France', result.region_name
    assert_equal '11', result.region_code
    assert_equal 'France', result.country
    assert_equal 'FR', result.country_code
    assert_equal(48.870131, result.coordinates[0])
    assert_equal(2.363473, result.coordinates[1])
  end

  def test_paris_special_business_logic
    result = Geocoder.search('paris').first
    assert_equal 'municipality', result.result_type
    assert_equal '75000', result.postal_code
    assert_equal 'France', result.country
    assert_equal 'FR', result.country_code
    assert_equal(2244000, result.population)
    assert_equal 'Paris', result.city
    assert_equal 'Paris', result.city_name
    assert_equal '75056', result.city_code
    assert_equal '75000', result.postal_code
    assert_equal '75', result.department_code
    assert_equal 'Paris', result.department_name
    assert_equal 'Île-de-France', result.region_name
    assert_equal '11', result.region_code
    assert_equal(48.8589, result.coordinates[0])
    assert_equal(2.3469, result.coordinates[1])
  end

  def test_city_result_methods
    result = Geocoder.search('montpellier', type: 'municipality').first
    assert_equal 'municipality', result.result_type
    assert_equal '34080', result.postal_code
    assert_equal '34172', result.city_code
    assert_equal 'France', result.country
    assert_equal 'FR', result.country_code
    assert_equal(5, result.administrative_weight)
    assert_equal(255100, result.population)
    assert_equal '34', result.department_code
    assert_equal 'Hérault', result.department_name
    assert_equal 'Occitanie', result.region_name
    assert_equal '76', result.region_code
    assert_equal(43.611024, result.coordinates[0])
    assert_equal(3.875521, result.coordinates[1])
  end

  def test_results_component_when_reverse_geocoding
    result = Geocoder.search([48.770431, 2.364463]).first
    assert_equal '94021_1133_49638b', result.location_id
    assert_equal 'housenumber', result.result_type
    assert_equal '4 Rue du Lieutenant Alain le Coz 94550 Chevilly-Larue, France', result.international_address
    assert_equal '4 Rue du Lieutenant Alain le Coz 94550 Chevilly-Larue, France', result.address
    assert_equal '4 Rue du Lieutenant Alain le Coz 94550 Chevilly-Larue', result.national_address
    assert_equal '4 Rue du Lieutenant Alain le Coz', result.street_address
    assert_equal '4', result.street_number
    assert_equal 'Rue du Lieutenant Alain le Coz', result.street
    assert_equal 'Rue du Lieutenant Alain le Coz', result.street_name
    assert_equal 'Chevilly-Larue', result.city
    assert_equal 'Chevilly-Larue', result.city_name
    assert_equal '94021', result.city_code
    assert_equal '94550', result.postal_code
    assert_equal '94', result.department_code
    assert_equal 'Val-de-Marne', result.department_name
    assert_equal 'Île-de-France', result.region_name
    assert_equal '11', result.region_code
    assert_equal 'France', result.country
    assert_equal 'FR', result.country_code
    assert_equal(48.770639, result.coordinates[0])
    assert_equal(2.364375, result.coordinates[1])
  end

  def test_no_reverse_results
    result = Geocoder.search('no reverse results')
    assert_equal 0, result.length
  end

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

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

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

    WebMock.reset!
    WebMock.disable!
  end


  private

  def assert_country_code(result)
    [:state_code, :country_code, :province_code].each do |method|
      assert_equal 'FR', result.send(method)
    end
  end
end