"Python Basics" Errors, Debugging, and Testing

1. Error handling

try:
    # 可能有异常的代码块
    r = 10/int('2')
except ValueError as e:
    # 有异常时执行,捕获指定类型及其子类型的错误
    print('ValueError', e)
except ZeroDivisionError as e:
    # 当前面的异常命中后,后面不会再次捕获
    print('ZeroDivisionError', e)
else:
    # 无异常时执行
    print('no error.')
finally# 上面结束后一定会执行
    print('finally')

call stack

From top to bottom, the entire wrong calling function chain, in order from outside to inside;

log error

try:
    r = 10/int('0')
except Exception as e:
    # 记录错误堆栈
    logging.exception(e)

Throw an exception

# 自定义异常
class FooError(ValueError):
    pass

# 抛出异常
raise FooError('invalid value')

# 捕获异常,原样抛出
except ValueError as e:
    raise

# 转化成另一种异常抛出
except ZeroDivisionError:
    raise ValueError('input error.')

When the program actively throws an exception, the possible exception and its cause should be clearly written in the document, so that the caller can handle the corresponding error;

2. debug

assert

If the asserted statement is not true, the assert statement will throw AssertionError;

assert n!=0, 'n is zero.'

The assertion can be turned off by -Othe parameter . After it is turned off, assertthe statement is equivalent to pass;

logging

import logging
logging.basicConfig(level=logging.INFO)

logging.info('xxx')

logging level

  • CRITICAL
  • ERROR
  • WARNING - root logger level default level
  • INFO
  • DEBUG
  • NOTSET - default level, handles all messages

Another benefit of logging is that through configuration, a message can be output to different places at the same time, for example console, files, database;

use morelogging

pdb

-m pdbStart with parameters .pyand run in a single step;

python -m pdb xxx.py

pdbinterface command

instruction effect
l view code
n single step
p p 变量名view variables
q End debugging, exit the program
c keep running

set_trace()

Set a breakpoint, and after entering debugging, crun the command to automatically pause at the breakpoint;

IDE

Visual Studio Code

PyCharm

3. unittest

TDD

Test Driven Development;

Unit testing is the guarantee for refactoring code in the future;

Unit tests should cover common input combinations, boundary conditions, and exceptions;

Unit testing should not be too complicated, otherwise it may have bugs;

write

import unittest
class TestDict(unittest.TestCase):
    def test_init(self):
        d = dict(a=1, b='test')
        # 断言相等
        self.assertEqual(d.a, 1)
        self.assertEqual(d.b, 'test')
        # 断言为真
        self.assertTrue(isinstance(d, dict))

    def test_keyerror(self):
        d = dict()
        # 期待语句块中抛出指定类型的 Error
        with self.assertRaises(KeyError):
            value = d['empty']

单元测试类inherited from unittest.TestCase;

单元测试方法It must be testnamed at the beginning, otherwise it will not be executed;

run

run by code

if __name__ == '__main__':
    unittest.main()

Run with command arguments

python -m unittest mytest

setUp and tearDown

Executed before and after each call to a unit test;

4.doctest

Documentation tests, which can be used to run tests as well as sample code;

Strictly follow the input and output of the Python interactive command line to judge the correctness of the test results;

When testing exceptions, you can use ...the output that represents the middle omission;

class Dict(dict):
    """
    Simple dict but also support access as x.y style.

    >>> d1 = Dict()
    >>> d1['x'] = 100
    >>> d1.x
    100
    >>> d1.y = 200
    >>> d1['y']
    200
    >>> d2 = Dict(a=1, b=2, c='3')
    >>> d2.c
    '3'
    >>> d2['empty']
    Traceback (most recent call last):
        ...
    KeyError: 'empty'
    >>> d2.empty
    Traceback (most recent call last):
        ...
    AttributeError: 'Dict' object has no attribute 'empty'
    """
    def __init__(self, **kw):
        super(Dict, self).__init__(**kw)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(f"'Dict' object has no attribute '{
      
      key}'")

    def __setattr__(self, key, value):
        self[key] = value


if __name__ == "__main__":
    import doctest
    doctest.testmod()

run

python mydict.py

If there is no output, it is running correctly;


PS: Thank you to everyone who has the same goals for reading, welcome to pay attention, comment, and praise!

Guess you like

Origin blog.csdn.net/ChaoMing_H/article/details/129393970