def test_delivery_system_creation(self): ds = DeliverySystem(loss_chance=self.loss_chance, read_chance=self.read_chance) self.assertEqual(ds._loss_chance, self.loss_chance) self.assertEqual(ds._read_chance, self.read_chance) self.assertIsInstance(ds._users, set) self.assertEqual(len(ds._users), 0) self.assertIsInstance(ds._messages, set) self.assertEqual(len(ds._messages), 0)
def test_chances_type_validation(self): for arguments in ( { 'loss_chance': None }, { 'read_chance': None }, { 'loss_chance': 'wrong' }, { 'read_chance': 'wrong' }, ): with self.assertRaises(TypeError): DeliverySystem(**arguments)
def test_chances_value_validation(self): for arguments in ( { 'loss_chance': -1 }, { 'read_chance': -1 }, { 'loss_chance': 1.1 }, { 'read_chance': 1.1 }, { 'loss_chance': 2 }, { 'read_chance': 2 }, ): with self.assertRaises(ValueError): DeliverySystem(**arguments)
def test_default_chances(self): ds = DeliverySystem() self.assertEqual(ds.loss_chance, LOSS_CHANCE) self.assertEqual(ds.read_chance, READ_CHANCE)
def setUp(self): self.ds = DeliverySystem(loss_chance=self.loss_chance, read_chance=self.read_chance)
class DeliverySystemTestCase(TestCase): loss_chance = 0 read_chance = 1 def setUp(self): self.ds = DeliverySystem(loss_chance=self.loss_chance, read_chance=self.read_chance) def test_delivery_system_creation(self): ds = DeliverySystem(loss_chance=self.loss_chance, read_chance=self.read_chance) self.assertEqual(ds._loss_chance, self.loss_chance) self.assertEqual(ds._read_chance, self.read_chance) self.assertIsInstance(ds._users, set) self.assertEqual(len(ds._users), 0) self.assertIsInstance(ds._messages, set) self.assertEqual(len(ds._messages), 0) def test_default_chances(self): ds = DeliverySystem() self.assertEqual(ds.loss_chance, LOSS_CHANCE) self.assertEqual(ds.read_chance, READ_CHANCE) def test_chances_type_validation(self): for arguments in ( { 'loss_chance': None }, { 'read_chance': None }, { 'loss_chance': 'wrong' }, { 'read_chance': 'wrong' }, ): with self.assertRaises(TypeError): DeliverySystem(**arguments) def test_chances_value_validation(self): for arguments in ( { 'loss_chance': -1 }, { 'read_chance': -1 }, { 'loss_chance': 1.1 }, { 'read_chance': 1.1 }, { 'loss_chance': 2 }, { 'read_chance': 2 }, ): with self.assertRaises(ValueError): DeliverySystem(**arguments) def test_register_user(self): username = '******' self.assertEqual(len(self.ds.users), 0) user = self.ds.register_user(name=username) self.assertEqual(len(self.ds.users), 1) self.assertEqual(self.ds._user_count, 1) self.assertIn(user, self.ds.users) self.assertEqual(user.name, username) self.assertEqual(user.code, 1) def test_create_message(self): message_body = 'This is a message.' self.assertEqual(len(self.ds.messages), 0) message = self.ds.create_message(body=message_body) self.assertEqual(len(self.ds.messages), 1) self.assertEqual(self.ds._message_count, 1) self.assertIn(message, self.ds.messages) self.assertEqual(message.body, message_body) self.assertEqual(message.code, 1) def test_get_user_and_message_code(self): control_series = list(range(1, 11)) for code_generator in (self.ds._get_user_code, self.ds._get_message_code): series = list(code_generator() for _ in range(10)) self.assertEqual(series, control_series) def test_users_property(self): users = (self.ds.register_user(), self.ds.register_user(), self.ds.register_user()) self.assertEqual(self.ds.users, list(users)) def test_messages_property(self): messages = (self.ds.create_message(), self.ds.create_message(), self.ds.create_message()) self.assertEqual(self.ds.messages, list(messages)) def test_is_registered_user(self): registered_user = self.ds.register_user(name='John Smith') self.assertTrue(self.ds.is_registered_user(user=registered_user)) unregistered_user = User(name='Jane Doe', code=registered_user.code + 1) self.assertFalse(self.ds.is_registered_user(user=unregistered_user)) def test_is_registered_message(self): registered_message = self.ds.create_message( body='This message is registered') self.assertTrue( self.ds.is_registered_message(message=registered_message)) unregistered_message = Message(body='This message is not registered', code=registered_message.code + 1) self.assertFalse( self.ds.is_registered_message(message=unregistered_message)) def test_send_message(self): user = self.ds.register_user(name='John Doe') message = self.ds.create_message(body='This is a message') for iterable in (message.users_sent, message.users_received, message.users_read, user.inbox): self.assertEqual(len(iterable), 0) self.ds.send_message(user=user, message=message) for iterable in (message.users_sent, message.users_received, message.users_read, user.inbox): self.assertEqual(len(iterable), 1) for iterable in (message.users_sent, message.users_received, message.users_read): self.assertIn(user, iterable) self.assertIn(message, user.inbox) def test_send_message_creation(self): user = self.ds.register_user(name='John Doe') self.assertEqual(len(self.ds.messages), 0) self.ds.send_message(user=user) self.assertEqual(len(self.ds.messages), 1) self.assertEqual(len(user.inbox), 1) def test_send_message_user_validation(self): user = User(name='John Doe', code=1) self.assertNotIn(user, self.ds.users) with self.assertRaises(ValueError): self.ds.send_message(user=user, body='This should raise and exception.') def test_send_message_validation(self): user = self.ds.register_user() message = Message(body='This message is not registered.', code=1) with self.assertRaises(ValueError): self.ds.send_message(user=user, message=message) def test_broadcast_message(self): users = (self.ds.register_user(), self.ds.register_user(), self.ds.register_user()) self.assertEqual(len(self.ds.users), len(users)) message = self.ds.broadcast_message( body='This message will be sent to every user.') for user in users: self.assertIn(message, user.inbox) def test_broadcast_message_creation(self): user = self.ds.register_user() self.assertEqual(len(self.ds.messages), 0) self.ds.broadcast_message() self.assertEqual(len(self.ds.messages), 1) self.assertEqual(len(user.inbox), 1) def test_broadcast_message_validation(self): self.ds.register_user() message = Message(body='This message is not registered.', code=1) with self.assertRaises(ValueError): self.ds.broadcast_message(message=message) def test_loss_chance(self): users = [self.ds.register_user() for _ in range(1000)] self.assertEqual(len(self.ds.users), len(users)) self.ds.loss_chance = 0 message = self.ds.broadcast_message() self.assertEqual(len(message.users_sent), len(message.users_received)) self.ds.loss_chance = 1 message = self.ds.broadcast_message() self.assertEqual(len(message.users_sent), len(users)) self.assertEqual(len(message.users_received), 0) def test_read_chance(self): users = [self.ds.register_user() for _ in range(1000)] self.assertEqual(len(self.ds.users), len(users)) self.ds.loss_chance = 0 self.ds.read_chance = 1 message = self.ds.broadcast_message() self.assertEqual(len(message.users_sent), len(message.users_read)) self.ds.read_chance = 0 message = self.ds.broadcast_message() self.assertEqual(len(message.users_sent), len(users)) self.assertEqual(len(message.users_received), len(users)) self.assertEqual(len(message.users_read), 0)
def main(): parser = argparse.ArgumentParser( prog='Notification Simulator', description='Simulator for delivering notifications to users.') parser.add_argument( '-u', '--numusers', type=int, default=NUM_USERS, help=f'Number of users to register. Defaults to {NUM_USERS}.') parser.add_argument( '-m', '--nummessages', type=int, default=NUM_MESSAGES, help=f'Number of messages to send. Defaults to {NUM_MESSAGES}.') parser.add_argument( '-lc', '--losschance', type=float, default=LOSS_CHANCE, metavar='[0-1]', help=f'Message loss chance. Defaults to {LOSS_CHANCE}.') parser.add_argument( '-rc', '--readchance', type=float, default=READ_CHANCE, metavar='[0-1]', help=f'Message read chance. Defaults to {READ_CHANCE}.') parser.add_argument('-o', '--output', choices=('console', 'logfile'), default='console', help='Set program output. Defaults to "console".') parser.add_argument('-f', '--logfile', type=str, default=log.LOGFILE, help=f'Path to log file. Defaults to "{log.LOGFILE}".') parser.add_argument('-lv', '--loglevel', choices=log.LOG_LEVELS.keys(), default='info', help='Logging level. Defaults to "info".') parser.add_argument( '-ls', '--logsize', type=int, default=log.MAX_BYTES, help= f'Max log size in bytes before rotation. Defaults to {log.MAX_BYTES}.') parser.add_argument( '-lb', '--logbackup', type=int, default=log.BACKUP_COUNT, help=f'Max number of backup logs. Defaults to {log.BACKUP_COUNT}.') args = parser.parse_args() if args.output.lower() == 'console' or not args.logfile: logging.basicConfig(level=log.LOG_LEVELS[args.loglevel.lower()], format=log.LOG_FORMAT, datefmt=log.DATETIME_FORMAT) else: log.configure_root_logger(filename=args.logfile, level=log.LOG_LEVELS[args.loglevel.lower()], max_bytes=args.logsize, backup_count=args.logbackup) logging.info('Launching Notification Simulator.') ds = DeliverySystem(loss_chance=args.losschance, read_chance=args.readchance) logging.info('Registering users...') for _ in range(args.numusers): ds.register_user() logging.info(f'Registered {args.numusers} users.') logging.info(f'Creating and sending messages to all registered users....') for _ in range(args.nummessages): ds.broadcast_message() logging.info(f'Created and sent {args.nummessages} messages.') logging.info('Displaying system statistics...') ds.show_statistics()