import unittest from datetime import datetime, timezone import os import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from validator import validate_row, validate_snapshot class TestValidator(unittest.TestCase): def setUp(self): self.config = { "validation": { "price_min": 1.0, "price_max": 500.0, "reject_zero_finish_rate": True, "reject_zero_surplus": True } } self.valid_row = { "adv_no": "12345", "price": 58.50, "surplus_amount": 100.0, "month_finish_rate": 0.95, "month_order_count": 100, "payment_methods": ["BANESCO"], "ad_created_at": datetime.now(timezone.utc) } def test_validate_row_valid(self): seen = set() self.assertTrue(validate_row(self.valid_row, self.config, seen)) self.assertIn("12345", seen) def test_validate_row_duplicate(self): seen = {"12345"} self.assertFalse(validate_row(self.valid_row, self.config, seen)) def test_validate_row_invalid_price(self): seen = set() # Price <= 0 row_bad_price = self.valid_row.copy() row_bad_price["price"] = -1.0 self.assertFalse(validate_row(row_bad_price, self.config, seen)) # Price > max row_high_price = self.valid_row.copy() row_high_price["price"] = 1000.0 self.assertFalse(validate_row(row_high_price, self.config, seen)) def test_validate_row_zero_surplus(self): seen = set() row_zero_surplus = self.valid_row.copy() row_zero_surplus["surplus_amount"] = 0.0 self.assertFalse(validate_row(row_zero_surplus, self.config, seen)) def test_validate_row_suspicious_finish(self): seen = set() row_suspicious = self.valid_row.copy() row_suspicious["month_finish_rate"] = 0.0 row_suspicious["month_order_count"] = 5 self.assertFalse(validate_row(row_suspicious, self.config, seen)) def test_validate_snapshot_empty(self): with self.assertRaises(ValueError): validate_snapshot([], datetime.now(timezone.utc)) def test_validate_snapshot_calculations(self): fetched_at = datetime.now(timezone.utc) ads = [ # BUY ads {"trade_type": "BUY", "price": 58.00, "payment_methods": ["BANESCO"], "ad_created_at": fetched_at}, {"trade_type": "BUY", "price": 59.00, "payment_methods": ["PAGO_MOVIL"], "ad_created_at": fetched_at}, # SELL ads {"trade_type": "SELL", "price": 61.00, "payment_methods": ["MERCANTIL"], "ad_created_at": fetched_at}, {"trade_type": "SELL", "price": 62.00, "payment_methods": ["BANESCO"], "ad_created_at": fetched_at}, ] summary = validate_snapshot(ads, fetched_at) self.assertEqual(summary["buy_count"], 2) self.assertEqual(summary["sell_count"], 2) self.assertEqual(summary["buy_min"], 58.00) self.assertEqual(summary["buy_max"], 59.00) self.assertEqual(summary["sell_min"], 61.00) self.assertEqual(summary["sell_max"], 62.00) self.assertEqual(summary["buy_median"], 58.50) self.assertEqual(summary["sell_median"], 61.50) # spread = sell_min - buy_max = 61.00 - 59.00 = 2.00 self.assertEqual(summary["spread"], 2.00) self.assertEqual(set(summary["methods"]), {"BANESCO", "PAGO_MOVIL", "MERCANTIL"}) if __name__ == "__main__": unittest.main()