• Python 面试:单元测试unit testing & 使用pytest


    1. 对于函数进行单元测试

    calc.py

    def add(x, y):
        """Add Function"""
        return x + y
    
    def subtract(x, y):
        """Subtract Function"""
        return x - y
    
    def multiply(x, y):
        """Multiply Function"""
        return x * y
    
    def divide(x, y):
        """Divide Function"""
        if y == 0: 
            raise ValueError('Can not divide by zero!')
        return x / y
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    test_calc.py

    import unittest
    import calc
    
    class TestCalc(unittest.TestCase):
    
        def test_add(self):
            self.assertEqual(calc.add(10, 5), 15)
            self.assertEqual(calc.add(-1, 1), 0)
            self.assertEqual(calc.add(-1, -1), -2)
    
        def test_subtract(self):
            self.assertEqual(calc.subtract(10, 5), 5)
            self.assertEqual(calc.subtract(-1, 1), -2)
            self.assertEqual(calc.subtract(-1, -1), 0)
    
        def test_multiply(self):
            self.assertEqual(calc.multiply(10, 5), 50)
            self.assertEqual(calc.multiply(-1, 1), -1)
            self.assertEqual(calc.multiply(-1, -1), 1)
    
        def test_divide(self):
            self.assertEqual(calc.divide(10, 5), 2)
            self.assertEqual(calc.divide(-1, 1), -1)
            self.assertEqual(calc.divide(-1, -1), 1)
    
            self.assertRaises(ValueError, calc.divide, 10, 0)
    
    
    if __name__ == '__main__':
        unittest.main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2. 对于对象(object)进行单元测试

    employee.py

    class Employee:
        """A sample Employee class"""
    
        raise_amt = 1.05
    
        def __init__(self, first, last, pay):
            self.first = first
            self.last = last
            self.pay = pay
    
        @property
        def email(self):
            return '{}.{}@email.com'.format(self.first, self.last)
        
        @property
        def fullname(self):
            return '{} {}'.format(self.first, self.last)
        
        def apply_raise(self):
            self.pay = int(self.pay * self.raise_amt)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    test_employee.py

    import unittest
    from employee import Employee
    
    class TestEmployee(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            print('setupClass')
    
        @classmethod
        def tearDownClass(cls):
            print('teardownClass')
    
        def setUp(self):
            print('setUp')
            self.emp_1 = Employee('Elon', 'Musk', 50000)
            self.emp_2 = Employee('Sue', 'Smith', 60000)
    
        def tearDown(self):
            print('tearDown\n')
    
        def test_email(self):
            print('test_email')
            self.assertEqual(self.emp_1.email, 'Elon.Musk@email.com')
            self.assertEqual(self.emp_2.email, 'Sue.Smith@email.com')
    
            self.emp_1.first = 'John'
            self.emp_2.first = 'Jane'
    
            self.assertEqual(self.emp_1.email, 'John.Musk@email.com')
            self.assertEqual(self.emp_2.email, 'Jane.Smith@email.com')
    
        def test_fullname(self):
            print('test_fullname')
            self.assertEqual(self.emp_1.fullname, 'Elon Musk')
            self.assertEqual(self.emp_2.fullname, 'Sue Smith')
    
            self.emp_1.first = 'John'
            self.emp_2.first = 'Jane'
    
            self.assertEqual(self.emp_1.fullname, 'John Musk')
            self.assertEqual(self.emp_2.fullname, 'Jane Smith')
    
        def test_apply_raise(self):
            print('test_apply_raise')
            self.emp_1.apply_raise()
            self.emp_2.apply_raise()
    
            self.assertEqual(self.emp_1.pay, 52500)
            self.assertEqual(self.emp_2.pay, 63000)
    
    if __name__ == '__main__':
        unittest.main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    输出为:
    setupClass
    setUp
    test_apply_raise
    tearDown

    .setUp
    test_email
    tearDown

    .setUp
    test_fullname
    tearDown

    .teardownClass


    Ran 3 tests in 0.001s

    OK

    3. 使用mock模拟对象库

    employee.py

    import requests
    
    class Employee:
        """A sample Employee class"""
    
        raise_amt = 1.05
    
        def __init__(self, first, last, pay):
            self.first = first
            self.last = last
            self.pay = pay
    
        @property
        def email(self):
            return '{}.{}@email.com'.format(self.first, self.last)
        
        @property
        def fullname(self):
            return '{} {}'.format(self.first, self.last)
        
        def apply_raise(self):
            self.pay = int(self.pay * self.raise_amt)
    
        def monthly_schedule(self, month):
            response = requests.get(f'http://company.com/{self.last}/{month}')
            if response.ok:
                return response.text
            else:
                return 'Bad Response!'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    test_employee.py

    import unittest
    from unittest.mock import patch
    from employee import Employee
    
    class TestEmployee(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            print('setupClass')
    
        @classmethod
        def tearDownClass(cls):
            print('teardownClass')
    
        def setUp(self):
            print('setUp')
            self.emp_1 = Employee('Elon', 'Musk', 50000)
            self.emp_2 = Employee('Sue', 'Smith', 60000)
    
        def tearDown(self):
            print('tearDown\n')
    
        # Test 1
        def test_email(self):
            print('test_email')
            self.assertEqual(self.emp_1.email, 'Elon.Musk@email.com')
            self.assertEqual(self.emp_2.email, 'Sue.Smith@email.com')
    
            self.emp_1.first = 'John'
            self.emp_2.first = 'Jane'
    
            self.assertEqual(self.emp_1.email, 'John.Musk@email.com')
            self.assertEqual(self.emp_2.email, 'Jane.Smith@email.com')
    
        # Test 2
        def test_fullname(self):
            print('test_fullname')
            self.assertEqual(self.emp_1.fullname, 'Elon Musk')
            self.assertEqual(self.emp_2.fullname, 'Sue Smith')
    
            self.emp_1.first = 'John'
            self.emp_2.first = 'Jane'
    
            self.assertEqual(self.emp_1.fullname, 'John Musk')
            self.assertEqual(self.emp_2.fullname, 'Jane Smith')
    
        # Test 3
        def test_apply_raise(self):
            print('test_apply_raise')
            self.emp_1.apply_raise()
            self.emp_2.apply_raise()
    
            self.assertEqual(self.emp_1.pay, 52500)
            self.assertEqual(self.emp_2.pay, 63000)
    
        # Test 4
        def test_monthly_schedule(self):
        	# 模拟替换网络请求
            with patch('employee.requests.get') as mocked_get:
                mocked_get.return_value.ok = True
                mocked_get.return_value.text = 'Success'
    
                schedule = self.emp_1.monthly_schedule('May')
                mocked_get.assert_called_with('http://company.com/Musk/May')
                self.assertEqual(schedule, 'Success')
    
                mocked_get.return_value.ok = False
    
                schedule = self.emp_2.monthly_schedule('June')
                mocked_get.assert_called_with('http://company.com/Smith/June')
                self.assertEqual(schedule, 'Bad Response!')
    
    if __name__ == '__main__':
        unittest.main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    输出为:
    setupClass
    setUp
    test_apply_raise
    tearDown

    .setUp
    test_email
    tearDown

    .setUp
    test_fullname
    tearDown

    .setUp
    tearDown

    .teardownClass


    Ran 4 tests in 0.001s

    OK

    4. 使用pytest进行测试

    binarysearch.py,主要使用assert。

    def binary_search(array, target):
        if not array:
            return -1
        begin, end = 0, len(array)
        while begin < end:
            mid = begin + (end - begin) // 2
            if array[mid] == target:
                return mid
            elif array[mid] > target:
                end = mid
            else:
                begin = mid + 1
        return -1
    
    def test():
        assert binary_search([0, 1, 2, 3, 4, 5], 1) == 1
        assert binary_search([0, 1, 2, 3, 4, 5], 6) == -1
        assert binary_search([0, 1, 2, 3, 4, 5], -1) == -1
    
        assert binary_search([0, 1, 2, 3, 4, 5], 0) == 0
        assert binary_search([0, 1, 2, 3, 4, 5], 5) == 5
        assert binary_search([0], 0) == 0
    
        assert binary_search([], 1) == -1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    在CMD中输入指令:pytest binarysearch.py

    输出为:
    ================================================= test session starts =================================================
    platform win32 – Python 3.10.9, pytest-7.1.2, pluggy-1.0.0
    rootdir: C:\Users\h13je\Working_Log\01092023\python_learning
    plugins: anyio-3.5.0
    collected 1 item

    binarysearch.py . [100%]

    ================================================== 1 passed in 0.02s ==================================================

  • 相关阅读:
    传奇登陆游戏黑屏错位以及登陆器配置和常见问题
    Interactive Tools Recommendation System integrating QT/ROS /Pytorch
    算法 盛水最多容器-(反向双指针)
    七夕送礼,让《新程序员》伴你一“杯”子!
    一些SQL的基本概念和用法
    Vue中如何扩展⼀个组件
    PG数据中DBeaver上传csv文件作为数据表
    【flask入门系列】Flask-SQLAlchemy的安装与配置
    Python编程经典案例【考题】求某个范围内能被3整除且能被5整除的所有数,及这些数的和
    C++用hiredis访问redis
  • 原文地址:https://blog.csdn.net/weixin_57266891/article/details/132579162