python-error handling\unit testing

table of Contents

Error handling

Affirmation

logging

 unit test

setUp() and tearDown() methods


Error handling

The function to open the file open()returns the file descriptor (that is, an integer) when successful, and returns when an error occurs -1.

try:
    foo()
except ValueError as e:
    print('ValueError')
except UnicodeError as e:
    print('UnicodeError')

Python's error is actually a class, all error types are inherited from BaseException, so when you use exceptit, you need to pay attention to that it not only catches errors of this type, but also "catch all of its subclasses."

The second one exceptwill never be captured UnicodeError, because it UnicodeErroris ValueErrora subclass, if there is, it is also exceptcaptured by the first one .

All errors in Python are BaseExceptionderived from classes. For common error types and inheritance relationships, see here:

https://docs.python.org/3/library/exceptions.html#exception-hierarchy

Affirmation

Those who use print()the place to aid viewing, you can use assertions (assert) instead, if the assertion fails, the assertstatement itself will throwAssertionError

logging

No errors will be thrown, and can be output to a file

import logging

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

After running, I found ZeroDivisionErrorthat there is no information except that, import loggingadd a line of configuration afterwards and try again:

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

See the output:

$ python err.py
INFO:root:n = 0
Traceback (most recent call last):
  File "err.py", line 8, in <module>
    print(10 / n)
ZeroDivisionError: division by zero

 This is loggingthe advantage, it allows you to specify the level of logging information,

The log levels are as follows:

CRITICAL : 'CRITICAL',
ERROR : 'ERROR',
WARNING : 'WARNING',
INFO : 'INFO',
DEBUG : 'DEBUG',
NOTSET : 'NOTSET',

When we specify level=INFO, logging.debugit doesn't work . Similarly, designated level=WARNINGlater, debugand info,notsetit does not work the

 unit test

For example, for functions abs(), we can write the following test cases:

  1. Enter a positive number, for example 1, , 1.2, 0.99the same input value expected return;

  2. Negative input, for example -1, -1.2, -0.99, opposite to the input expected return value;

  3. Enter 0, expect to return 0;

  4. Enter non-numeric types, such as None, [], {}and look forward to throw TypeError.

Putting the above test cases into a test module is a complete unit test.

Let's write a Dictclass. The behavior of this class is dictconsistent, but it can be accessed through attributes. It is used as follows:

>>> d = Dict(a=1, b=2)
>>> d['a']
1
>>> d.a
1

mydict.pycode show as below:

class Dict(dict):

    def __init__(self, **kw):
        super().__init__(**kw)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"'Dict' object has no attribute '%s'" % key)

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

In order to write a unit test, we need to introduce the unittestmodule that comes with Python , which is written mydict_test.pyas follows:

import unittest

from mydict import Dict

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_key(self):
        d = Dict()
        d['key'] = 'value'
        self.assertEqual(d.key, 'value')

    def test_attr(self):
        d = Dict()
        d.key = 'value'
        self.assertTrue('key' in d)
        self.assertEqual(d['key'], 'value')

    def test_keyerror(self):
        d = Dict()
        with self.assertRaises(KeyError): #期待抛出指定类型的Error,比如通过d['empty']访问不存在的key时,断言会抛出KeyError
            value = d['empty']

    def test_attrerror(self):
        d = Dict()
        with self.assertRaises(AttributeError):
            value = d.empty

When writing unit tests, we need to write a test class that unittest.TestCaseinherits from it .

testThe method with the beginning is the test method, testthe method without the beginning is not considered as the test method, and will not be executed during the test.

Unit testing, the simplest way to run is to mydict_test.pyadd two lines of code at the end:

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

In this way, you can run it mydict_test.pyas a normal python script:

$ python mydict_test.py

Another way is -m unittestto run unit tests directly on the command line with parameters :

$ python -m unittest mydict_test
.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s

OK

This is the recommended approach, because it allows you to run many unit tests in batches at once, and there are many tools that can automatically run these unit tests.

setUp()And tearDown()method

These two methods will be executed before and after each test method is called.

Imagine that your test needs to start a database. At this time, you can setUp()connect to the database in the tearDown()method and close the database in the method . In this way, you don't have to repeat the same code in each test method:

class TestDict(unittest.TestCase):

    def setUp(self):
        print('setUp...')

    def tearDown(self):
        print('tearDown...')

Run test: Whether the setUpsum will be printed before and after each test method is called tearDown.

Guess you like

Origin blog.csdn.net/zangba9624/article/details/106465605