ユニットテストとは、Wikipediaで定義されています。ユニットテストは、ソースコードの個々のユニット、1つ以上のコンピュータプログラムモジュールのセット、および関連する制御データ、使用手順、および操作手順をテストする方法です。 [1]直感的には、ユニットをアプリケーションの最小のテスト可能な部分と見なすことができます。つまり、システム内の最小のテスト可能なユニットの機能が正しいかどうかを検証する自動テストです。したがって、ユニットテストの目的は「テスト対象の責任を確認する」ことです。ユニットテストを作成する前に、まずテスト対象の責任を特定してから、このユニットテストの作成方法を理解してください。
テスト対象に応じて、ユニットテストは2つのカテゴリに分類できます。
pythonユニットテストライブラリunittestの基本的な使用法については、[Liao Xuefeng Pythonユニットテスト](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191629979802b566644aa84656b50cd484ec4a7838000)を参照してください。
特定の用途については、以下の情報を参照してください
なぜモックを使うのですか?

多くのモックの説明を読んだ後、最良の説明は[[Naftuli Kay-Pythonでのモックの概要](https://www.toptal.com/python/an-introduction-to-mocking-in-python)です。例としてファイルの削除を取り上げ、モックの使用法を詳しく説明します。その他の情報については、以下を参照してください。
この記事に基づいてqk_logログモジュールを書き直してください。qk_log.pyコードは次のとおりです。
#! /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))
ユニットテストコードは次のとおりです。
#! /usr/bin/env python
# - *- coding: utf-8-*-"""
Created on 10/10/1711: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
classTestQkLog(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()
Pythonデータ統計分析プロジェクトの全体的な変革の中でユニットテストを導入する予定でした。パブリックライブラリのユニットテストを作成した後、ユニットテストに多くの時間が費やされ、パブリックライブラリは頻繁に変更されず、ビジネスロジックがかなり混沌としていたため、チームはユニットテストを中止することを決定しました。すぐにオンラインになるスタートアップやスタートアップチームのプロジェクトの場合、ユニットテストを急いで作成する必要はありません。すべての変更が可能な場合、コードが破棄されるときに対応するユニットテストも破棄されるため、無駄です。人員が多すぎる。
したがって、スタートアップチームは、ユニットテストを作成することをお勧めしません。ポイントを埋め、アラームを監視するだけです。
Recommended Posts