├── before.py ├── LICENSE ├── with_dep_inj.py ├── before-test.py ├── final.py ├── with_dep_inj_test.py └── final-test.py /before.py: -------------------------------------------------------------------------------- 1 | import string 2 | import random 3 | 4 | class Order: 5 | 6 | def __init__(self): 7 | self.id = ''.join(random.choices(string.ascii_lowercase, k=6)) 8 | self.status = "open" 9 | 10 | def set_status(self, status): 11 | self.status = status 12 | 13 | class Authorizer_SMS: 14 | 15 | def __init__(self): 16 | self.authorized = False 17 | self.code = None 18 | 19 | def generate_sms_code(self): 20 | self.code = ''.join(random.choices(string.digits, k=6)) 21 | 22 | def authorize(self): 23 | code = input("Enter SMS code: ") 24 | self.authorized = code == self.code 25 | 26 | def is_authorized(self) -> bool: 27 | return self.authorized 28 | 29 | class PaymentProcessor: 30 | 31 | def pay(self, order): 32 | authorizer = Authorizer_SMS() 33 | authorizer.generate_sms_code() 34 | authorizer.authorize() 35 | if not authorizer.is_authorized(): 36 | raise Exception("Not authorized") 37 | print(f"Processing payment for order with id {order.id}") 38 | order.set_status("paid") 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 ArjanCodes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /with_dep_inj.py: -------------------------------------------------------------------------------- 1 | import string 2 | import random 3 | 4 | class Order: 5 | 6 | def __init__(self): 7 | self.id = ''.join(random.choices(string.ascii_lowercase, k=6)) 8 | self.status = "open" 9 | 10 | def set_status(self, status): 11 | self.status = status 12 | 13 | class Authorizer_SMS: 14 | 15 | def __init__(self): 16 | self.authorized = False 17 | self.code = None 18 | 19 | def generate_sms_code(self): 20 | self.code = ''.join(random.choices(string.digits, k=6)) 21 | 22 | def authorize(self): 23 | code = input("Enter SMS code: ") 24 | self.authorized = code == self.code 25 | 26 | def is_authorized(self) -> bool: 27 | return self.authorized 28 | 29 | class PaymentProcessor: 30 | 31 | def __init__(self, authorizer: Authorizer_SMS): 32 | self.authorizer = authorizer 33 | 34 | def pay(self, order): 35 | self.authorizer.authorize() 36 | if not self.authorizer.is_authorized(): 37 | raise Exception("Not authorized") 38 | print(f"Processing payment for order with id {order.id}") 39 | order.set_status("paid") 40 | -------------------------------------------------------------------------------- /before-test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from io import StringIO 3 | from unittest.mock import patch 4 | from before import * 5 | 6 | class Authorizer_SMS_TestCase(unittest.TestCase): 7 | 8 | def test_init_authorized(self): 9 | auth = Authorizer_SMS() 10 | self.assertFalse(auth.is_authorized()) 11 | 12 | def test_code_decimal(self): 13 | auth = Authorizer_SMS() 14 | auth.generate_sms_code() 15 | self.assertTrue(auth.code.isdecimal()) 16 | 17 | def test_authorize_success(self): 18 | auth = Authorizer_SMS() 19 | auth.generate_sms_code() 20 | with patch('builtins.input', return_value=auth.code): 21 | auth.authorize() 22 | self.assertTrue(auth.is_authorized()) 23 | 24 | @patch('builtins.input', return_value="1234567") 25 | def test_authorize_fail(self, mocked_input): 26 | auth = Authorizer_SMS() 27 | auth.generate_sms_code() 28 | auth.authorize() 29 | self.assertFalse(auth.is_authorized()) 30 | 31 | 32 | class PaymentProcessor_TestCase(unittest.TestCase): 33 | 34 | def test_payment_success(self): 35 | # ??? 36 | self.assertTrue(True) 37 | 38 | def test_payment_fail(self): 39 | # ??? 40 | self.assertTrue(True) 41 | 42 | 43 | if __name__ == '__main__': 44 | unittest.main() -------------------------------------------------------------------------------- /final.py: -------------------------------------------------------------------------------- 1 | import string 2 | import random 3 | from abc import ABC, abstractmethod 4 | 5 | class Authorizer(ABC): 6 | @abstractmethod 7 | def authorize(self): 8 | pass 9 | 10 | @abstractmethod 11 | def is_authorized(self) -> bool: 12 | pass 13 | 14 | class Order: 15 | 16 | def __init__(self): 17 | self.id = ''.join(random.choices(string.ascii_lowercase, k=6)) 18 | self.status = "open" 19 | 20 | def set_status(self, status): 21 | self.status = status 22 | 23 | class Authorizer_SMS(Authorizer): 24 | 25 | def __init__(self): 26 | self.authorized = False 27 | self.code = None 28 | 29 | def generate_sms_code(self): 30 | self.code = ''.join(random.choices(string.digits, k=6)) 31 | 32 | def authorize(self): 33 | code = input("Enter SMS code: ") 34 | self.authorized = code == self.code 35 | 36 | def is_authorized(self) -> bool: 37 | return self.authorized 38 | 39 | class Authorizer_Robot(Authorizer): 40 | 41 | def __init__(self): 42 | self.authorized = False 43 | 44 | def authorize(self): 45 | robot = "" 46 | while robot != "y" and robot != "n": 47 | robot = input("Are you a robot (y/n) ?").lower() 48 | self.authorized = robot == "n" 49 | 50 | def is_authorized(self) -> bool: 51 | return self.authorized 52 | 53 | class PaymentProcessor: 54 | 55 | def __init__(self, authorizer: Authorizer): 56 | self.authorizer = authorizer 57 | 58 | def pay(self, order): 59 | self.authorizer.authorize() 60 | if not self.authorizer.is_authorized(): 61 | raise Exception("Not authorized") 62 | print(f"Processing payment for order with id {order.id}") 63 | order.set_status("paid") 64 | -------------------------------------------------------------------------------- /with_dep_inj_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from io import StringIO 3 | from unittest.mock import patch 4 | from with_dep_inj import * 5 | 6 | class Authorizer_SMS_TestCase(unittest.TestCase): 7 | 8 | def test_init_authorized(self): 9 | auth = Authorizer_SMS() 10 | self.assertFalse(auth.is_authorized()) 11 | 12 | def test_code_decimal(self): 13 | auth = Authorizer_SMS() 14 | auth.generate_sms_code() 15 | self.assertTrue(auth.code.isdecimal()) 16 | 17 | def test_authorize_success(self): 18 | auth = Authorizer_SMS() 19 | auth.generate_sms_code() 20 | with patch('builtins.input', return_value=auth.code): 21 | auth.authorize() 22 | self.assertTrue(auth.is_authorized()) 23 | 24 | @patch('builtins.input', return_value="1234567") 25 | def test_authorize_fail(self, mocked_input): 26 | auth = Authorizer_SMS() 27 | auth.generate_sms_code() 28 | auth.authorize() 29 | self.assertFalse(auth.is_authorized()) 30 | 31 | class PaymentProcessor_TestCase(unittest.TestCase): 32 | 33 | def test_init(self): 34 | auth = Authorizer_SMS() 35 | p = PaymentProcessor(auth) 36 | self.assertEqual(p.authorizer, auth) 37 | 38 | def test_payment_success(self): 39 | auth = Authorizer_SMS() 40 | auth.generate_sms_code() 41 | with patch('builtins.input', return_value=auth.code): 42 | p = PaymentProcessor(auth) 43 | order = Order() 44 | p.pay(order) 45 | self.assertEqual(order.status, "paid") 46 | 47 | def test_payment_fail(self): 48 | auth = Authorizer_SMS() 49 | auth.generate_sms_code() 50 | with patch('builtins.input', return_value="1234567"): 51 | p = PaymentProcessor(auth) 52 | order = Order() 53 | self.assertRaises(Exception, p.pay, order) 54 | 55 | 56 | if __name__ == '__main__': 57 | unittest.main() -------------------------------------------------------------------------------- /final-test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from io import StringIO 3 | from unittest.mock import patch 4 | 5 | from final import * 6 | 7 | 8 | class Authorizer_SMS_TestCase(unittest.TestCase): 9 | 10 | def test_init_authorized(self): 11 | auth = Authorizer_SMS() 12 | self.assertFalse(auth.is_authorized()) 13 | 14 | def test_code_decimal(self): 15 | auth = Authorizer_SMS() 16 | auth.generate_sms_code() 17 | self.assertTrue(auth.code.isdecimal()) 18 | 19 | def test_authorize_success(self): 20 | auth = Authorizer_SMS() 21 | auth.generate_sms_code() 22 | with patch('builtins.input', return_value=auth.code): 23 | auth.authorize() 24 | self.assertTrue(auth.is_authorized()) 25 | 26 | @patch('builtins.input', return_value="1234567") 27 | def test_authorize_fail(self, mocked_input): 28 | auth = Authorizer_SMS() 29 | auth.generate_sms_code() 30 | auth.authorize() 31 | self.assertFalse(auth.is_authorized()) 32 | 33 | class Authorizer_Robot_TestCase(unittest.TestCase): 34 | 35 | def test_init_authorized(self): 36 | auth = Authorizer_Robot() 37 | self.assertFalse(auth.is_authorized()) 38 | 39 | def test_authorize_success(self): 40 | with patch('builtins.input', return_value="n"): 41 | auth = Authorizer_Robot() 42 | auth.authorize() 43 | self.assertTrue(auth.is_authorized()) 44 | 45 | def test_authorize_success_uppercase(self): 46 | with patch('builtins.input', return_value="N"): 47 | auth = Authorizer_Robot() 48 | auth.authorize() 49 | self.assertTrue(auth.is_authorized()) 50 | 51 | def test_authorize_fail(self): 52 | with patch('builtins.input', return_value="y"): 53 | auth = Authorizer_Robot() 54 | auth.authorize() 55 | self.assertFalse(auth.is_authorized()) 56 | 57 | class PaymentProcessor_TestCase(unittest.TestCase): 58 | 59 | def test_init(self): 60 | auth = Authorizer_SMS() 61 | p = PaymentProcessor(auth) 62 | self.assertEqual(p.authorizer, auth) 63 | 64 | def test_payment_success(self): 65 | auth = Authorizer_SMS() 66 | auth.generate_sms_code() 67 | with patch('builtins.input', return_value=auth.code): 68 | p = PaymentProcessor(auth) 69 | order = Order() 70 | p.pay(order) 71 | self.assertEqual(order.status, "paid") 72 | 73 | def test_payment_fail(self): 74 | auth = Authorizer_SMS() 75 | auth.generate_sms_code() 76 | with patch('builtins.input', return_value="1234567"): 77 | p = PaymentProcessor(auth) 78 | order = Order() 79 | self.assertRaises(Exception, p.pay, order) 80 | 81 | 82 | if __name__ == '__main__': 83 | unittest.main() 84 | --------------------------------------------------------------------------------