What is the Mock of Python unit test?

unit test

What is unit testing? Wikipedia defines it as follows: unit testing is a method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine if they are fit for use.[1] Intuitively, one can view a unit as the smallest testable part of an application. In short, it is an automated test that verifies whether the function of the smallest testable unit in the system is correct. Therefore, the purpose of unit testing is to "verify the responsibilities of the tested object". Before writing a unit test, first identify the responsibilities of the tested object, and then you will know how to write the unit test.

According to the object being tested, unit testing can be divided into two categories:

  • Unit testing of components that do not depend on external resources: use the basic functions of unittest
  • Unit testing of components that depend on external resources: mocks are required

unittest uses

For the basic use of the python unit test library unittest, see Liao XuefengPython unit test

For specific use, refer to the following information

  1. Unit testing in Python
  2. ningning.today-flask project unit test practice
  3. Python unittest official documentation
  4. Geek Academy - Unit Test
  5. nicholas-how to write unit tests

mock

Why use mocks?

I have read a lot of mock explanations, and the best one I wrote is [ Naftuli Kay-An Introduction to Mocking in Python , which uses deleting files as an example to explain the use of mock in depth. Additional information can be found at:

  1. Python unit testing and mock testing
  2. mock-autospec

Follow this article to rewrite the qk_log log module, the qk_log.py code is as follows

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import datetime
import logging
import logging.handlers

_console_logger = None
_warn_logger = None
_error_logger = None

CONSOLE_FILENAME = 'log/console.log'
WARNING_FILENAME = 'log/warn.log'
ERROR_FILENAME = 'log/error.log'


def log_init():
    if os.path.exists('log/') is True:
        pass
    else:
        os.mkdir('log/')
    global _console_logger, _warn_logger, _error_logger
    handler = logging.handlers.RotatingFileHandler(
        CONSOLE_FILENAME, maxBytes=20*1024*1024, backupCount=5)
    hdr = logging.StreamHandler()
    _console_logger = logging.getLogger('debug')
    _console_logger.addHandler(handler)
    _console_logger.addHandler(hdr)
    _console_logger.setLevel(logging.DEBUG)

    handler = logging.handlers.RotatingFileHandler(
        WARNING_FILENAME, maxBytes=20*1024*1024, backupCount=5)
    hdr = logging.StreamHandler()
    _warn_logger = logging.getLogger('warn')
    _warn_logger.addHandler(handler)
    _warn_logger.addHandler(hdr)
    _warn_logger.setLevel(logging.WARN)

    handler = logging.handlers.RotatingFileHandler(
        ERROR_FILENAME, maxBytes=20*1024*1024, backupCount=5)
    hdr = logging.StreamHandler()
    _error_logger = logging.getLogger('error')
    _error_logger.addHandler(handler)
    _error_logger.addHandler(hdr)
    _error_logger.setLevel(logging.ERROR)


def dlog(msg):
    file_name, file_no, unused = find_caler()
    time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    _console_logger.debug('[%s] [%s] [%s,%d] %s' % (time_str, 'debug', file_name, file_no, msg))


def ilog(msg):
    file_name, file_no, unused = find_caler()
    time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    _console_logger.info('[%s] [%s] [%s,%d] %s' % (time_str, 'info', file_name, file_no, msg))


def wlog(msg):
    file_name, file_no, unused = find_caler()
    time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    _console_logger.warn('[%s] [%s] [%s,%d] %s' % (time_str, 'warning', file_name, file_no, msg))
    _warn_logger.warn('[%s] [%s] [%s,%d] %s' % (time_str, 'warning', file_name, file_no, msg))


def elog(msg):
    file_name, file_no, unused = find_caler()
    time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    _console_logger.error('[%s] [%s] [%s,%d] %s' % (time_str, 'error', file_name, file_no, msg))
    _error_logger.error('[%s] [%s] [%s,%d] %s' % (time_str, 'error', file_name, file_no, msg))


def find_caler():
    f = sys._getframe(2)
    co = f.f_code
    return (os.path.basename(co.co_filename), f.f_lineno, co.co_name) if co != None else ('unknown', 0, 'unknown')


if __name__ == '__main__':
    log_init()
    dlog('test.log %d'%(123))
    ilog('test.log %d' % (123))
    wlog('test.log %d' % (123))
    elog('test.log %d' % (123))

The unit test code is as follows:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Created on 10/10/17 11:27 AM
@author: Chen Liang
@function: 日志模块  单元测试
"""

import sys

reload(sys)
sys.setdefaultencoding('utf-8')
import unittest
import mock
import datetime
from qk_log import log_init, dlog, ilog, wlog, elog


class TestQkLog(unittest.TestCase):
    dt_str = datetime.datetime.strptime('2017-10-11 11:08:59', '%Y-%m-%d %H:%M:%S')

    @mock.patch('qk_log.os.path')
    @mock.patch('qk_log.datetime.datetime')
    @mock.patch('qk_log.logging')
    @mock.patch('qk_log.find_caler')
    def test_dlog(self, mock_caler, mock_logging, mock_datetime, mock_path):
        mock_path.exists.return_value = True
        log_init()
        self.assertFalse(mock_logging.getLogger('debug').debug.called, "Failed to not write log.")

        mock_caler.return_value = ('qk_log_test', 12, '')
        mock_datetime.now.return_value = self.dt_str
        dlog('any msg')
        mock_logging.getLogger('debug').debug.assert_called_with(
            '[%s] [%s] [%s,%d] %s' % ('2017-10-11 11:08:59', 'debug', 'qk_log_test', 12, 'any msg'))

    @mock.patch('qk_log.os.path')
    @mock.patch('qk_log.datetime.datetime')
    @mock.patch('qk_log.logging')
    @mock.patch('qk_log.find_caler')
    def test_ilog(self, mock_caler, mock_logging, mock_datetime, mock_path):
        mock_path.exists.return_value = True
        log_init()
        self.assertFalse(mock_logging.getLogger('debug').info.called, "Failed to not write log.")
        mock_caler.return_value = ('qk_log_test', 12, '')
        mock_datetime.now.return_value = self.dt_str
        ilog('any msg')
        mock_logging.getLogger('debug').info.assert_called_with(
            '[%s] [%s] [%s,%d] %s' % ('2017-10-11 11:08:59', 'info', 'qk_log_test', 12, 'any msg'))

    @mock.patch('qk_log.os.path')
    @mock.patch('qk_log.datetime.datetime')
    @mock.patch('qk_log.logging')
    @mock.patch('qk_log.find_caler')
    def test_wlog(self, mock_caler, mock_logging, mock_datetime, mock_path):
        mock_path.exists.return_value = True
        log_init()
        self.assertFalse(mock_logging.getLogger('warn').info.called, "Failed to not write log.")
        mock_caler.return_value = ('qk_log_test', 12, '')
        mock_datetime.now.return_value = self.dt_str
        wlog('any msg')
        mock_logging.getLogger('warn').warn.assert_called_with(
            '[%s] [%s] [%s,%d] %s' % ('2017-10-11 11:08:59', 'warning', 'qk_log_test', 12, 'any msg'))

    @mock.patch('qk_log.os.path')
    @mock.patch('qk_log.datetime.datetime')
    @mock.patch('qk_log.logging')
    @mock.patch('qk_log.find_caler')
    def test_elog(self, mock_caler, mock_logging, mock_datetime, mock_path):
        mock_path.exists.return_value = True
        log_init()
        self.assertFalse(mock_logging.getLogger('error').info.called, "Failed to not write log.")
        mock_caler.return_value = ('qk_log_test', 12, '')
        mock_datetime.now.return_value = self.dt_str
        elog('any msg')
        mock_logging.getLogger('error').error.assert_called_with(
            '[%s] [%s] [%s,%d] %s' % ('2017-10-11 11:08:59', 'error', 'qk_log_test', 12, 'any msg'))

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

Views on unit testing

In an overall transformation of the Python data statistical analysis project, I planned to introduce unit testing. After writing the unit testing of the public library, I found that more time was spent on unit testing, and the public library was not changed frequently, and the business logic was relatively confusing. Therefore, the team Decided to drop unit testing. For projects of start-up companies and start-up teams that go online quickly, there is no need to rush to write unit tests, because in the case that all changes may occur, the corresponding unit tests will be discarded when the code is discarded, which is a waste of time. Too much manpower.

Therefore, start-up teams do not recommend writing unit tests, just do a good job of program burying and monitoring and alarming.


Remember to give me a thumbs up!

Carefully sort out the video courses and e-books in all directions of computer, from introductory, advanced, and practical, and classify them reasonably according to the catalog. You can always find the learning materials you need. What are you waiting for? Follow and download now! ! !

resource-introduce

If you never forget, there will be echoes, friends, please give me a thumbs up, thank you very much.

I am a bright brother in the workplace, a YY senior software engineer with four years of work experience, and a slash programmer who refuses to be the leader.

Listen to me, a lot of progress, the life of the program is a shuttle

If you are lucky enough to be able to help you, please give me a [Like], give me a follow, and if you can comment to give encouragement, it will be very grateful.

Workplace Liangge article list: more articles

wechat-platform-guide-attention

All my articles and answers have cooperated with the copyright protection platform, and the copyright belongs to Brother Liang in the workplace. Unauthorized reprinting will be punished!

Guess you like

Origin blog.csdn.net/u013637931/article/details/111152189