mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-14 18:37:58 +00:00
Removed magic mocking, using monkeypatch instead, and using a placex table to simulate a 'real database'
This commit is contained in:
@@ -2,13 +2,10 @@ import pytest
|
||||
import tempfile
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nominatim_db.errors import UsageError
|
||||
from nominatim_db.tools.special_phrases.sp_csv_loader import SPCsvLoader
|
||||
from nominatim_db.tools.special_phrases.special_phrase import SpecialPhrase
|
||||
from nominatim_db.tools.special_phrases.sp_importer import SPImporter
|
||||
|
||||
# Testing Style Class Pair Retrival
|
||||
@pytest.fixture
|
||||
def sample_style_file():
|
||||
sample_data = [
|
||||
@@ -59,135 +56,106 @@ def sample_style_file():
|
||||
yield tmp_path
|
||||
os.remove(tmp_path)
|
||||
|
||||
def test_get_classtype_style(sample_style_file):
|
||||
class Config:
|
||||
def get_import_style_file(self):
|
||||
return sample_style_file
|
||||
|
||||
def load_sub_configuration(self, name):
|
||||
return {'blackList': {}, 'whiteList': {}}
|
||||
|
||||
def test_get_sp_style(sample_style_file):
|
||||
mock_config = MagicMock()
|
||||
mock_config.get_import_style_file.return_value = sample_style_file
|
||||
config = Config()
|
||||
importer = SPImporter(config=config, conn=None, sp_loader=None)
|
||||
|
||||
importer = SPImporter(config=mock_config, conn=None, sp_loader=None)
|
||||
result = importer.get_sp_style()
|
||||
result = importer.get_classtype_pairs_style()
|
||||
|
||||
expected = {
|
||||
("highway", "motorway"),
|
||||
}
|
||||
|
||||
assert expected.issubset(result)
|
||||
|
||||
# Testing Database Class Pair Retrival using Mock Database
|
||||
def test_get_classtype_pairs(monkeypatch):
|
||||
class Config:
|
||||
def load_sub_configuration(self, path, section=None):
|
||||
return {"blackList": {}, "whiteList": {}}
|
||||
|
||||
class Cursor:
|
||||
def execute(self, query): pass
|
||||
def fetchall(self):
|
||||
return [
|
||||
("highway", "motorway"),
|
||||
("historic", "castle")
|
||||
]
|
||||
def __enter__(self): return self
|
||||
def __exit__(self, exc_type, exc_val, exc_tb): pass
|
||||
|
||||
class Connection:
|
||||
def cursor(self): return Cursor()
|
||||
|
||||
config = Config()
|
||||
conn = Connection()
|
||||
importer = SPImporter(config=config, conn=conn, sp_loader=None)
|
||||
|
||||
result = importer.get_classtype_pairs()
|
||||
|
||||
expected = {
|
||||
("highway", "motorway"),
|
||||
("historic", "castle")
|
||||
}
|
||||
|
||||
assert result == expected
|
||||
|
||||
@pytest.fixture
|
||||
def mock_phrase():
|
||||
return SpecialPhrase(
|
||||
p_label="test",
|
||||
p_class="highway",
|
||||
p_type="motorway",
|
||||
p_operator="eq"
|
||||
)
|
||||
# Testing Database Class Pair Retrival using Conftest.py and placex
|
||||
def test_get_classtype_pair_data(placex_table, temp_db_conn):
|
||||
class Config:
|
||||
def load_sub_configuration(self, *_):
|
||||
return {'blackList': {}, 'whiteList': {}}
|
||||
|
||||
for _ in range(101):
|
||||
placex_table.add(cls='highway', typ='motorway') # edge case 101
|
||||
|
||||
def test_create_classtype_table_and_indexes():
|
||||
mock_config = MagicMock()
|
||||
mock_config.TABLESPACE_AUX_DATA = ''
|
||||
mock_config.DATABASE_WEBUSER = 'www-data'
|
||||
for _ in range(99):
|
||||
placex_table.add(cls='amenity', typ='prison') # edge case 99
|
||||
|
||||
mock_cursor = MagicMock()
|
||||
mock_conn = MagicMock()
|
||||
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
|
||||
for _ in range(150):
|
||||
placex_table.add(cls='tourism', typ='hotel')
|
||||
|
||||
importer = SPImporter(config=mock_config, conn=mock_conn, sp_loader=None)
|
||||
config = Config()
|
||||
importer = SPImporter(config=config, conn=temp_db_conn, sp_loader=None)
|
||||
|
||||
importer._create_place_classtype_table = MagicMock()
|
||||
importer._create_place_classtype_indexes = MagicMock()
|
||||
importer._grant_access_to_webuser = MagicMock()
|
||||
importer.statistics_handler.notify_one_table_created = lambda: print("✓ Created table")
|
||||
importer.statistics_handler.notify_one_table_ignored = lambda: print("⨉ Ignored table")
|
||||
result = importer.get_classtype_pairs()
|
||||
|
||||
importer.table_phrases_to_delete = {"place_classtype_highway_motorway"}
|
||||
|
||||
test_pairs = [("highway", "motorway"), ("natural", "peak")]
|
||||
importer._create_classtype_table_and_indexes(test_pairs)
|
||||
|
||||
print("create_place_classtype_table calls:")
|
||||
for call in importer._create_place_classtype_table.call_args_list:
|
||||
print(call)
|
||||
|
||||
print("\ncreate_place_classtype_indexes calls:")
|
||||
for call in importer._create_place_classtype_indexes.call_args_list:
|
||||
print(call)
|
||||
|
||||
print("\ngrant_access_to_webuser calls:")
|
||||
for call in importer._grant_access_to_webuser.call_args_list:
|
||||
print(call)
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config():
|
||||
config = MagicMock()
|
||||
config.TABLESPACE_AUX_DATA = ''
|
||||
config.DATABASE_WEBUSER = 'www-data'
|
||||
config.load_sub_configuration.return_value = {'blackList': {}, 'whiteList': {}}
|
||||
return config
|
||||
|
||||
|
||||
def test_import_phrases_original(mock_config):
|
||||
phrase = SpecialPhrase("roundabout", "highway", "motorway", "eq")
|
||||
|
||||
mock_conn = MagicMock()
|
||||
mock_cursor = MagicMock()
|
||||
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
|
||||
mock_loader = MagicMock()
|
||||
mock_loader.generate_phrases.return_value = [phrase]
|
||||
|
||||
mock_analyzer = MagicMock()
|
||||
mock_tokenizer = MagicMock()
|
||||
mock_tokenizer.name_analyzer.return_value.__enter__.return_value = mock_analyzer
|
||||
|
||||
importer = SPImporter(config=mock_config, conn=mock_conn, sp_loader=mock_loader)
|
||||
importer._fetch_existing_place_classtype_tables = MagicMock()
|
||||
importer._create_classtype_table_and_indexes = MagicMock()
|
||||
importer._remove_non_existent_tables_from_db = MagicMock()
|
||||
|
||||
importer.import_phrases(tokenizer=mock_tokenizer, should_replace=True)
|
||||
|
||||
assert importer.word_phrases == {("roundabout", "highway", "motorway", "-")}
|
||||
|
||||
mock_analyzer.update_special_phrases.assert_called_once_with(
|
||||
importer.word_phrases, True
|
||||
)
|
||||
|
||||
|
||||
def test_get_sp_filters_correctly(sample_style_file):
|
||||
mock_config = MagicMock()
|
||||
mock_config.get_import_style_file.return_value = sample_style_file
|
||||
mock_config.load_sub_configuration.return_value = {"blackList": {}, "whiteList": {}}
|
||||
|
||||
importer = SPImporter(config=mock_config, conn=MagicMock(), sp_loader=None)
|
||||
|
||||
allowed_from_db = {("highway", "motorway"), ("historic", "castle")}
|
||||
importer.get_sp_db = lambda: allowed_from_db
|
||||
|
||||
result = importer.get_sp()
|
||||
|
||||
expected = {("highway", "motorway")}
|
||||
expected = {
|
||||
("highway", "motorway"),
|
||||
("tourism", "hotel")
|
||||
}
|
||||
|
||||
assert result == expected, f"Expected {expected}, got {result}"
|
||||
|
||||
def test_get_sp_db_filters_by_count_threshold(mock_config):
|
||||
mock_cursor = MagicMock()
|
||||
|
||||
# Simulate only results above the threshold being returned (as SQL would)
|
||||
# These tuples simulate real SELECT class, type FROM placex GROUP BY ... HAVING COUNT(*) > 100
|
||||
mock_cursor.fetchall.return_value = [
|
||||
("highway", "motorway"),
|
||||
("historic", "castle")
|
||||
]
|
||||
def test_get_classtype_pair_data_more(placex_table, temp_db_conn):
|
||||
class Config:
|
||||
def load_sub_configuration(self, *_):
|
||||
return {'blackList': {}, 'whiteList': {}}
|
||||
|
||||
for _ in range(100):
|
||||
placex_table.add(cls='emergency', typ='firehydrant') # edge case 100, not included
|
||||
|
||||
mock_conn = MagicMock()
|
||||
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
|
||||
importer = SPImporter(config=mock_config, conn=mock_conn, sp_loader=None)
|
||||
for _ in range(199):
|
||||
placex_table.add(cls='amenity', typ='prison')
|
||||
|
||||
result = importer.get_sp_db()
|
||||
for _ in range(3478):
|
||||
placex_table.add(cls='tourism', typ='hotel')
|
||||
|
||||
config = Config()
|
||||
importer = SPImporter(config=config, conn=temp_db_conn, sp_loader=None)
|
||||
|
||||
result = importer.get_classtype_pairs()
|
||||
|
||||
expected = {
|
||||
("highway", "motorway"),
|
||||
("historic", "castle")
|
||||
("amenity", "prison"),
|
||||
("tourism", "hotel")
|
||||
}
|
||||
|
||||
assert result == expected
|
||||
mock_cursor.execute.assert_called_once()
|
||||
assert result == expected, f"Expected {expected}, got {result}"
|
||||
|
||||
Reference in New Issue
Block a user