123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- """
- Test suite for the Price Alarm System
- Tests alarm creation, management, triggering, and integration.
- """
- import unittest
- import tempfile
- import os
- from datetime import datetime
- from alarm_manager import AlarmManager
- class TestAlarmManager(unittest.TestCase):
- """Test the AlarmManager class."""
-
- def setUp(self):
- """Set up test fixtures."""
-
- self.temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.json')
- self.temp_file.close()
- self.alarm_manager = AlarmManager(self.temp_file.name)
-
- def tearDown(self):
- """Clean up after tests."""
-
- if os.path.exists(self.temp_file.name):
- os.unlink(self.temp_file.name)
-
- def test_create_alarm_above(self):
- """Test creating an alarm for price going above current price."""
-
- alarm = self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
-
- self.assertEqual(alarm['id'], 1)
- self.assertEqual(alarm['token'], 'BTC')
- self.assertEqual(alarm['target_price'], 55.0)
- self.assertEqual(alarm['current_price_when_set'], 50.0)
- self.assertEqual(alarm['direction'], 'above')
- self.assertEqual(alarm['status'], 'active')
-
- def test_create_alarm_below(self):
- """Test creating an alarm for price going below current price."""
-
- alarm = self.alarm_manager.create_alarm("ETH", 45.0, 50.0)
-
- self.assertEqual(alarm['id'], 1)
- self.assertEqual(alarm['token'], 'ETH')
- self.assertEqual(alarm['target_price'], 45.0)
- self.assertEqual(alarm['current_price_when_set'], 50.0)
- self.assertEqual(alarm['direction'], 'below')
- self.assertEqual(alarm['status'], 'active')
-
- def test_multiple_alarms_increment_id(self):
- """Test that multiple alarms get incrementing IDs."""
- alarm1 = self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- alarm2 = self.alarm_manager.create_alarm("ETH", 3500.0, 3000.0)
- alarm3 = self.alarm_manager.create_alarm("BTC", 45.0, 50.0)
-
- self.assertEqual(alarm1['id'], 1)
- self.assertEqual(alarm2['id'], 2)
- self.assertEqual(alarm3['id'], 3)
-
- def test_get_alarms_by_token(self):
- """Test filtering alarms by token."""
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- self.alarm_manager.create_alarm("ETH", 3500.0, 3000.0)
- self.alarm_manager.create_alarm("BTC", 45.0, 50.0)
-
- btc_alarms = self.alarm_manager.get_alarms_by_token("BTC")
- eth_alarms = self.alarm_manager.get_alarms_by_token("ETH")
-
- self.assertEqual(len(btc_alarms), 2)
- self.assertEqual(len(eth_alarms), 1)
- self.assertEqual(btc_alarms[0]['token'], 'BTC')
- self.assertEqual(eth_alarms[0]['token'], 'ETH')
-
- def test_remove_alarm(self):
- """Test removing an alarm by ID."""
- alarm = self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- alarm_id = alarm['id']
-
-
- self.assertIsNotNone(self.alarm_manager.get_alarm_by_id(alarm_id))
-
-
- result = self.alarm_manager.remove_alarm(alarm_id)
- self.assertTrue(result)
-
-
- self.assertIsNone(self.alarm_manager.get_alarm_by_id(alarm_id))
-
- def test_remove_nonexistent_alarm(self):
- """Test removing an alarm that doesn't exist."""
- result = self.alarm_manager.remove_alarm(999)
- self.assertFalse(result)
-
- def test_check_alarms_trigger_above(self):
- """Test triggering an alarm when price goes above target."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
-
-
- price_data = {"BTC": 56.0}
- triggered = self.alarm_manager.check_alarms(price_data)
-
- self.assertEqual(len(triggered), 1)
- self.assertEqual(triggered[0]['token'], 'BTC')
- self.assertEqual(triggered[0]['triggered_price'], 56.0)
- self.assertEqual(triggered[0]['status'], 'triggered')
-
- def test_check_alarms_trigger_below(self):
- """Test triggering an alarm when price goes below target."""
-
- self.alarm_manager.create_alarm("ETH", 45.0, 50.0)
-
-
- price_data = {"ETH": 44.0}
- triggered = self.alarm_manager.check_alarms(price_data)
-
- self.assertEqual(len(triggered), 1)
- self.assertEqual(triggered[0]['token'], 'ETH')
- self.assertEqual(triggered[0]['triggered_price'], 44.0)
- self.assertEqual(triggered[0]['status'], 'triggered')
-
- def test_check_alarms_no_trigger(self):
- """Test that alarms don't trigger when conditions aren't met."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
-
-
- price_data = {"BTC": 54.0}
- triggered = self.alarm_manager.check_alarms(price_data)
-
- self.assertEqual(len(triggered), 0)
-
-
- active_alarms = self.alarm_manager.get_all_active_alarms()
- self.assertEqual(len(active_alarms), 1)
- self.assertEqual(active_alarms[0]['status'], 'active')
-
- def test_check_alarms_exact_price(self):
- """Test that alarms trigger at exact target price."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
-
-
- price_data = {"BTC": 55.0}
- triggered = self.alarm_manager.check_alarms(price_data)
-
- self.assertEqual(len(triggered), 1)
- self.assertEqual(triggered[0]['triggered_price'], 55.0)
-
- def test_alarm_only_triggers_once(self):
- """Test that triggered alarms don't trigger again."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
-
-
- price_data = {"BTC": 56.0}
- triggered1 = self.alarm_manager.check_alarms(price_data)
- self.assertEqual(len(triggered1), 1)
-
-
- price_data = {"BTC": 60.0}
- triggered2 = self.alarm_manager.check_alarms(price_data)
- self.assertEqual(len(triggered2), 0)
-
- def test_multiple_alarms_selective_trigger(self):
- """Test that only applicable alarms trigger."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- self.alarm_manager.create_alarm("ETH", 45.0, 50.0)
- self.alarm_manager.create_alarm("BTC", 40.0, 50.0)
-
-
- price_data = {"BTC": 56.0, "ETH": 46.0}
- triggered = self.alarm_manager.check_alarms(price_data)
-
- self.assertEqual(len(triggered), 1)
- self.assertEqual(triggered[0]['token'], 'BTC')
- self.assertEqual(triggered[0]['target_price'], 55.0)
-
- def test_persistence(self):
- """Test that alarms persist across manager instances."""
-
- alarm = self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- alarm_id = alarm['id']
-
-
- new_manager = AlarmManager(self.temp_file.name)
-
-
- restored_alarm = new_manager.get_alarm_by_id(alarm_id)
- self.assertIsNotNone(restored_alarm)
- self.assertEqual(restored_alarm['token'], 'BTC')
- self.assertEqual(restored_alarm['target_price'], 55.0)
- self.assertEqual(restored_alarm['status'], 'active')
-
- def test_format_alarm_list_empty(self):
- """Test formatting empty alarm list."""
- message = self.alarm_manager.format_alarm_list([])
- self.assertIn("No alarms found", message)
-
- def test_format_alarm_list_with_alarms(self):
- """Test formatting alarm list with alarms."""
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- self.alarm_manager.create_alarm("ETH", 45.0, 50.0)
-
- alarms = self.alarm_manager.get_all_active_alarms()
- message = self.alarm_manager.format_alarm_list(alarms)
-
- self.assertIn("BTC", message)
- self.assertIn("ETH", message)
- self.assertIn("ID 1", message)
- self.assertIn("ID 2", message)
- self.assertIn("55.00", message)
- self.assertIn("45.00", message)
-
- def test_format_triggered_alarm(self):
- """Test formatting triggered alarm notification."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- price_data = {"BTC": 56.0}
- triggered = self.alarm_manager.check_alarms(price_data)
-
- message = self.alarm_manager.format_triggered_alarm(triggered[0])
-
- self.assertIn("Price Alert Triggered", message)
- self.assertIn("BTC", message)
- self.assertIn("56.00", message)
- self.assertIn("55.00", message)
- self.assertIn("50.00", message)
-
- def test_statistics(self):
- """Test alarm statistics."""
-
- self.alarm_manager.create_alarm("BTC", 55.0, 50.0)
- self.alarm_manager.create_alarm("BTC", 45.0, 50.0)
- self.alarm_manager.create_alarm("ETH", 3500.0, 3000.0)
-
-
- price_data = {"BTC": 56.0}
- self.alarm_manager.check_alarms(price_data)
-
- stats = self.alarm_manager.get_statistics()
-
- self.assertEqual(stats['total_active'], 2)
- self.assertEqual(stats['total_triggered'], 1)
- self.assertEqual(stats['tokens_tracked'], 2)
- self.assertEqual(stats['token_breakdown']['BTC'], 1)
- self.assertEqual(stats['token_breakdown']['ETH'], 1)
- if __name__ == '__main__':
- unittest.main()
|