oem_crawler/tests/test_mercedes_parser.py
2026-11-07 16:53:30 +01:00

338 lines
16 KiB
Python

"""
Unit tests for Mercedes-Benz stock parser.
"""
from decimal import Decimal
import unittest
from oem_crawler.db.schemas import (
BatteryCapacityUnit,
DrivetrainType,
FuelType,
TransmissionType,
VehicleCondition,
VehicleStatus,
)
from oem_crawler.crawlers.mercedes.parser import (
extract_city_postal_code,
map_mercedes_drivetrain,
map_mercedes_fuel_type,
map_mercedes_transmission,
map_mercedes_used_fuel_type,
map_mercedes_used_series,
parse_mercedes_used_vehicle,
parse_mercedes_vehicle,
)
class TestMercedesParser(unittest.TestCase):
def test_extract_city_postal_code(self):
city, zip_code = extract_city_postal_code("Mercedesstraße 120, 70372 Stuttgart")
self.assertEqual(city, "Stuttgart")
self.assertEqual(zip_code, "70372")
city2, zip_code2 = extract_city_postal_code("Am Seestern 1, 40547 Düsseldorf")
self.assertEqual(city2, "Düsseldorf")
self.assertEqual(zip_code2, "40547")
def test_map_fuel_type(self):
self.assertEqual(map_mercedes_fuel_type("ELECTRIC", []), FuelType.BEV)
self.assertEqual(map_mercedes_fuel_type("PETROL", [{"id": "90W-BI_MILD"}]), FuelType.MHEV)
self.assertEqual(map_mercedes_fuel_type("DIESEL", []), FuelType.DIESEL)
self.assertEqual(map_mercedes_fuel_type("PLUGIN", []), FuelType.PHEV)
def test_map_transmission_and_drivetrain(self):
self.assertEqual(map_mercedes_transmission("AUTOMATIC"), TransmissionType.AUTOMATIC)
self.assertEqual(map_mercedes_transmission("MANUAL"), TransmissionType.MANUAL)
self.assertEqual(map_mercedes_drivetrain("C 400 4MATIC"), DrivetrainType.AWD)
self.assertEqual(map_mercedes_drivetrain("A 180", "W177"), DrivetrainType.FWD)
self.assertEqual(map_mercedes_drivetrain("C 200", "W206"), DrivetrainType.RWD)
def test_parse_mercedes_vehicle(self):
raw_search = {
"identification": {
"code": "MB8SXSK01",
"commissionNumber": "0555673413",
"vin": None,
},
"vehicleModel": {
"name": "A 180",
"motorization": "A 180",
"vehicleClass": {"formattedValue": "A-Klasse"},
"bodyType": {"formattedValue": "Kompaktwagen"},
"modelYearCode": "806",
"typeClass": "W177",
},
"technicalInformation": {
"engine": {
"fuelType": {"value": "PETROL"},
"power": {
"combinedKw": {"value": 110},
"combinedHp": {"value": 150},
},
},
"transmission": {"value": "AUTOMATIC"},
},
"dealer": {
"nameLocalLanguage": "Mercedes-Benz AG",
"outletId": "GS00113259",
"addressLocalLanguage": "Mercedesstraße 120, 70372 Stuttgart",
},
"emissionAndConsumption": {
"attributes": [
{"id": "90W-BI_MILD", "value": "5.9", "unit": "l/100km"},
{"id": "85W", "value": "133.0", "unit": "g/km"},
]
},
"stock": {"stockType": "AVAILABLE"},
"characteristics": {
"highlights": [{"label": "Progressive"}, {"label": "Spiegel-Paket"}]
},
"images": {
"default": "https://media.oneweb.mercedes-benz.com/images/default.jpg"
},
}
raw_price = {
"currency": "EUR",
"purchasePrice": {"amount": "38167.76"},
"priceBreakDown": [{"type": "BASE_PRICE", "amount": "37453.76"}],
"financeLeasingInfo": {
"vehicle": {
"prices": [
{"id": "grossListPrice", "rawValue": "49938.35"},
{"id": "baseListPrice", "rawValue": "39513.95"},
]
}
},
"taxProfile": "GROSS",
}
raw_vpc = {
"color": {
"id": "LU-787",
"text": {"de": "mountaingrau"},
"group": {"de": "Grau"},
},
"upholstery": {
"id": "AU-311",
"group": {"de": "Schwarz"},
"polish": {"de": "Ledernachbildung ARTICO"},
},
"components": {
"SA-R31": {
"code": "R31",
"codeType": "SA",
"name": {"de": "18\" Leichtmetallräder"},
"standard": True,
}
},
}
veh = parse_mercedes_vehicle(raw_search, raw_price=raw_price, raw_vpc=raw_vpc)
self.assertEqual(veh.brand, "Mercedes-Benz")
self.assertEqual(veh.oem_vehicle_id, "MB8SXSK01")
self.assertEqual(veh.series, "A-Klasse")
self.assertEqual(veh.model_name, "A 180")
self.assertEqual(veh.trim_line, "Progressive")
self.assertEqual(veh.body_type, "Kompaktwagen")
self.assertEqual(veh.condition, VehicleCondition.NEW)
self.assertEqual(veh.model_year, 2026)
self.assertEqual(veh.fuel_type, FuelType.MHEV)
self.assertEqual(veh.transmission, TransmissionType.AUTOMATIC)
self.assertEqual(veh.drivetrain, DrivetrainType.FWD)
self.assertEqual(veh.power_kw, 110)
self.assertEqual(veh.power_hp, 150)
self.assertEqual(veh.price_gross, Decimal("38167.76"))
self.assertEqual(veh.msrp_gross, Decimal("49938.35"))
self.assertEqual(veh.discount_percentage, Decimal("23.57"))
self.assertEqual(veh.location_city, "Stuttgart")
self.assertEqual(veh.location_postal_code, "70372")
self.assertEqual(veh.exterior_color, "mountaingrau")
self.assertEqual(veh.exterior_color_code, "LU-787")
self.assertEqual(veh.interior_color, "Schwarz")
self.assertEqual(len(veh.options), 1)
self.assertEqual(veh.options[0].option_code, "R31")
def test_parse_mercedes_electric_vehicle(self):
raw_search = {
"identification": {"code": "MB_EV_001"},
"vehicleModel": {
"name": "EQE 350+ 4MATIC",
"vehicleClass": {"formattedValue": "EQE"},
"bodyType": {"formattedValue": "Limousine"},
},
"technicalInformation": {
"engine": {
"fuelType": {"value": "ELECTRIC"},
"power": {"combinedKw": {"value": 215}, "combinedHp": {"value": 292}},
},
"transmission": {"value": "AUTOMATIC"},
},
"emissionAndConsumption": {
"attributes": [
{"id": "237W", "value": "16.5", "unit": "kWh/100km"},
{"id": "193W", "value": "620", "unit": "km"},
{"id": "85W", "value": "0", "unit": "g/km"},
]
},
}
raw_vpc = {
"technicalInformation": {
"engine": {
"batteryCapacity": {"value": 141, "unit": "Ah"},
"chargingCapacityAC": {"value": 11, "unit": "kW"},
"chargingCapacityDC": {"value": 170, "unit": "kW"},
},
"chargeTime": {
"chargeTimeDCHigh": {"value": 22.0, "unit": "min"}
},
}
}
raw_price = {
"purchasePrice": {"amount": "74500.00"},
}
veh = parse_mercedes_vehicle(raw_search, raw_price=raw_price, raw_vpc=raw_vpc)
self.assertEqual(veh.fuel_type, FuelType.BEV)
self.assertEqual(veh.drivetrain, DrivetrainType.AWD)
self.assertEqual(veh.electric_range_wltp_km, 620)
self.assertEqual(veh.consumption_combined, Decimal("16.5"))
self.assertEqual(veh.battery_capacity, Decimal("141"))
self.assertEqual(veh.battery_capacity_unit, BatteryCapacityUnit.AH)
self.assertEqual(veh.charging_power_ac_kw, Decimal("11"))
self.assertEqual(veh.charging_power_dc_kw, Decimal("170"))
self.assertEqual(veh.charging_time_dc_minutes, 22)
def test_map_mercedes_used_series(self):
self.assertEqual(map_mercedes_used_series("V 300 d Avantgarde lang"), "V-Klasse")
self.assertEqual(map_mercedes_used_series("EQV 300 lang"), "EQV")
self.assertEqual(map_mercedes_used_series("EQE 350 4MATIC"), "EQE")
self.assertEqual(map_mercedes_used_series("C 200 T-Modell AMG Line"), "C-Klasse")
self.assertEqual(map_mercedes_used_series("A 180 Progressive"), "A-Klasse")
def test_map_mercedes_used_fuel_type(self):
self.assertEqual(map_mercedes_used_fuel_type("Elektro"), FuelType.BEV)
self.assertEqual(map_mercedes_used_fuel_type("Diesel"), FuelType.DIESEL)
self.assertEqual(map_mercedes_used_fuel_type("Benzin"), FuelType.PETROL)
self.assertEqual(map_mercedes_used_fuel_type("Plug-in-Hybrid Benzin"), FuelType.PHEV)
def test_parse_mercedes_used_vehicle_ice(self):
card_html = """
<div id="resultListItem19170569" class="list-vehicle-card col-md-6">
<div class="vehicle_title_headline"><span class="manufacturer">Mercedes-Benz</span><br>V 300 d Avantgarde lang</div>
<div class="vehicle_title_subheadline">Fahrzeugnummer 55229GK030</div>
<div class="vehicle_price_headline">95.490 &euro;</div>
<div class="financing-box"><div class="financing-data">699,00 €</div></div>
<ul class="vehicle-card-list">
<li class="vc-vehicle-attribute-row"><svg><use href="#vehicle-box-body-type"></use></svg><p class="vc-vehicle-attribute-text">Van/Kleinbus</p></li>
<li class="vc-vehicle-attribute-row"><svg><use href="#vehicle-box-first-registration"></use></svg><p class="vc-vehicle-attribute-text">25.07.2025</p></li>
<li class="vc-vehicle-attribute-row"><svg><use href="#vehicle-box-power"></use></svg><p class="vc-vehicle-attribute-text">174 kW (237 PS)</p></li>
<li class="vc-vehicle-attribute-row"><svg><use href="#vehicle-box-mileage"></use></svg><p class="vc-vehicle-attribute-text">10.018 km</p></li>
<li class="vc-vehicle-attribute-row"><svg><use href="#vehicle-box-engine-ice"></use></svg><p class="vc-vehicle-attribute-text">Diesel</p></li>
<li class="vc-vehicle-attribute-row result-box-location-item"><span class="vc-vehicle-attribute-text">Mercedes-Benz AG</span><span class="vc-vehicle-attribute-text">71034 Böblingen</span></li>
</ul>
</div>
"""
detail_html = """
<html>
<body>
<div class="basic-data"><div class="data-label">Erstzulassung</div><div class="data-value">25.07.2025</div></div>
<div class="basic-data"><div class="data-label">Modeljahr</div><div class="data-value">2025</div></div>
<div class="basic-data"><div class="data-label">Laufleistung</div><div class="data-value">10.018 km</div></div>
<div class="basic-data"><div class="data-label">Hubraum</div><div class="data-value">1.950 ccm</div></div>
<div class="basic-data"><div class="data-label">Getriebe</div><div class="data-value">Automatikgetriebe</div></div>
<div class="basic-data"><div class="data-label">Garantie</div><div class="data-value">Mercedes-Benz Junge Sterne</div></div>
<div class="basic-data"><div class="data-label">Außenfarbe (grau)</div><div class="data-value">Alpingrau</div></div>
<div class="basic-data"><div class="data-label">Polster (Leder)</div><div class="data-value">Leder Lugano schwarz</div></div>
<script>
dealerLocationMap.setCenterCoordinate('48.682361000000000', '8.982236000000000');
</script>
<div class="eq-search-container"><div class="eq-item">Leichtmetallfelgen 19 Zoll<span> | R1W</span></div></div>
</body>
</html>
"""
veh = parse_mercedes_used_vehicle(card=card_html, detail_html=detail_html)
self.assertEqual(veh.oem_vehicle_id, "19170569")
self.assertEqual(veh.raw_payload.get("commission_number"), "55229GK030")
self.assertEqual(veh.series, "V-Klasse")
self.assertEqual(veh.model_name, "V 300 d Avantgarde lang")
self.assertEqual(veh.trim_line, "Avantgarde")
self.assertEqual(veh.body_type, "Van/Kleinbus")
self.assertEqual(veh.condition, VehicleCondition.CERTIFIED_PRE_OWNED)
self.assertEqual(veh.model_year, 2025)
self.assertEqual(veh.fuel_type, FuelType.DIESEL)
self.assertEqual(veh.transmission, TransmissionType.AUTOMATIC)
self.assertEqual(veh.power_kw, 174)
self.assertEqual(veh.power_hp, 237)
self.assertEqual(veh.engine_displacement_cc, 1950)
self.assertEqual(veh.mileage_km, 10018)
self.assertEqual(veh.price_gross, Decimal("95490"))
self.assertEqual(veh.monthly_rate, Decimal("699.00"))
self.assertEqual(veh.exterior_color, "Alpingrau")
self.assertEqual(veh.interior_material, "Leder Lugano schwarz")
self.assertEqual(veh.dealer_name, "Mercedes-Benz AG")
self.assertEqual(veh.location_postal_code, "71034")
self.assertEqual(veh.location_city, "Böblingen")
self.assertEqual(veh.latitude, Decimal("48.682361000000000"))
self.assertEqual(veh.longitude, Decimal("8.982236000000000"))
self.assertEqual(len(veh.options), 1)
self.assertEqual(veh.options[0].option_code, "R1W")
def test_parse_mercedes_used_vehicle_ev(self):
card_html = """
<div id="resultListItem19169425" class="list-vehicle-card">
<div class="vehicle_title_headline"><span class="manufacturer">Mercedes-Benz</span><br>EQV 300 lang</div>
<div class="vehicle_title_subheadline">Fahrzeugnummer 56F27180</div>
<div class="vehicle_price_headline">33.444 &euro;</div>
<ul class="vehicle-card-list">
<li class="vc-vehicle-attribute-row"><p class="vc-vehicle-attribute-text">150 kW (204 PS)</p></li>
<li class="vc-vehicle-attribute-row"><p class="vc-vehicle-attribute-text">121.962 km</p></li>
<li class="vc-vehicle-attribute-row"><p class="vc-vehicle-attribute-text">Elektro</p></li>
<li class="vc-vehicle-attribute-row result-box-location-item"><span class="vc-vehicle-attribute-text">KTW</span><span class="vc-vehicle-attribute-text">31137 Hildesheim</span></li>
</ul>
</div>
"""
detail_html = """
<html>
<body>
<div class="basic-data"><div class="data-label">Erstzulassung</div><div class="data-value">23.05.2022</div></div>
<div class="basic-data"><div class="data-label">Modeljahr</div><div class="data-value">2024</div></div>
<div class="basic-data"><div class="data-label">Kraftstoffart</div><div class="data-value">Elektro</div></div>
<div class="basic-data"><div class="data-label">Außenfarbe (blau)</div><div class="data-value">Cavansitblau</div></div>
<div class="bento-2-item"><div class="bento-2-title">Elektrische Reichweite</div><div class="bento-2-value">348 km</div></div>
<div class="bento-2-item"><div class="bento-2-title">Energie</div><div class="bento-2-value">90 kWh</div></div>
<p>Die Ladeleistung von 110 kW ermöglicht schnelles Laden an DC-Stationen. An Wallboxen mit bis zu 11 kW AC laden.</p>
<script>
dealerLocationMap.setCenterCoordinate('52.167469000000000', '9.920900000000000');
</script>
</body>
</html>
"""
veh = parse_mercedes_used_vehicle(card=card_html, detail_html=detail_html)
self.assertEqual(veh.oem_vehicle_id, "19169425")
self.assertEqual(veh.raw_payload.get("commission_number"), "56F27180")
self.assertEqual(veh.series, "EQV")
self.assertEqual(veh.model_name, "EQV 300 lang")
self.assertEqual(veh.fuel_type, FuelType.BEV)
self.assertEqual(veh.battery_capacity, Decimal("90"))
self.assertEqual(veh.battery_capacity_unit, BatteryCapacityUnit.KWH)
self.assertEqual(veh.battery_capacity_net_kwh, Decimal("90"))
self.assertEqual(veh.electric_range_wltp_km, 348)
self.assertEqual(veh.charging_power_ac_kw, Decimal("11"))
self.assertEqual(veh.charging_power_dc_kw, Decimal("110"))
self.assertEqual(veh.latitude, Decimal("52.167469000000000"))
self.assertEqual(veh.longitude, Decimal("9.920900000000000"))
if __name__ == "__main__":
unittest.main()