Unit testing

What is a unit test? Wikipedia defines it this way: 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, automated tests that verify that the smallest testable unit in a system is functioning correctly. Therefore, the purpose of a unit test is to “verify the responsibilities of the object being tested”. Before writing a unit test, identify the responsibilities of the object being tested so that you know how to write the unit test.

Unit tests can be divided into two broad categories based on who is being tested:

  • Unit testing of components that do not depend on external resources: Use the basic unitTest functionality
  • Unit testing of components that depend on external resources: Mocks are required

Unittest use

See unit tests for python for a basic use of the python unittest library

Please refer to the following materials for specific usage

  1. Unit testing in Python
  2. Ningning. today-Flask Project unit testing practice
  3. Python UnitTest official documentation
  4. Geek Academy – Unit tests
  5. Nicholas – How do YOU write unit tests

mock

Why mock?

I have read many Mocking articles. The best one is Naftuli Kay-an Introduction to Mocking in Python, Mocking in depth by deleting files as An example.

  1. Python unit tests and Mock tests
  2. mock-autospec

Rewrite the qk_log logging module as in this article, with the code qk_log.py 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) ifco ! =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))

Copy the code

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: Unit Test for log module ""

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('the 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' % ('the 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' % ('the 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' % ('the 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' % ('the 2017-10-11 11:08:59'.'error'.'qk_log_test'.12.'any msg'))

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

Copy the code

Views on unit testing

Unit testing was introduced during an overall transformation of the Python statistical analysis project. After writing the unit tests for the common library, the team found that the time spent on unit tests was too much, the common library did not change often, and the business logic was confused, so the team decided to abandon unit testing. There is no need to write unit tests for the projects of startups and start-up teams that go live quickly, because when all changes are possible, the corresponding unit tests will be discarded when the code is discarded, which wastes too much manpower.

Therefore, the start-up team does not recommend writing unit tests, just do a good job of burying the program and monitoring the alarm.


Please give me a thumbs up!

Carefully organized the computer from all directions from the entry, advanced, actual combat video courses and e-books, according to the catalog reasonable classification, always can find you need to learn information, what are still waiting for? Go to download!!

Can’t forget, there will be echoes, friends to help me like it, thank you very much.

I am a senior software engineer of YY with four years of work experience. I refuse to be a slashes programmer.

Listen to me. It’s a lot of progress

If lucky enough to be able to help you, please help me [like], give a attention, if you can along with comments to encourage, will be very grateful.

List of articles: More

All my articles, answers and copyright protection platform cooperation, copyright belongs to the workplace Liangge all, unauthorized, reproduced will investigate!