Python自動化テスト、3分間のログでバグを特定する
I. 簡単な使い方
スタートアップの小さな一例
import logging
logging.basicConfig(level=logging.DEBUG, #set level, display according to level
format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s') # set output format
logging.debug('This is a debug log')
logging.info('This is a info log')
logging.warning('This is a warning log')
logging.error('This is a error log')
logging.critical('This is a critical log')
ロギングレベル
5つのログレベルが設定されており、状況に応じて異なるレベルのログが出力されます。
ロガーで設定されたレベルは、このレベル以下のログをフィルタリングします。
import logging
logging.basicConfig(level=logging.WARNING, # set level, display according to level
format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s') # set output format
logging.debug('This is a debug log')
logging.info('This is a info log')
logging.warning('This is a warning log')
logging.error('This is a error log')
logging.critical('This is a critical log')
2020-09-11 17:39:26,667-WARNING-This is a warning log
2020-09-11 17:39:26,669-ERROR-This is エラーログ
2020-09-11 17:39:26,669-CRITICAL-This is critical log
構成
basicConfigメソッドは、以下の設定用キーワードパラメータをサポートしています。
フォーマットルール
ログの出力形式は、以下の形式と自由に組み合わせることができます。
<イグ
共通フォーマット: %(asctime)s-[%(filename)s->line:%(lineno)d]-%(levelname)s:%(message)s
import logging
logging.basicConfig(level=logging.DEBUG, #set level, display according to level
format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s') # set output format
logging.debug('This is a debug log')
[DEBUG]-2020-09-11 17:36:50,125-4:This is debug log
ファイルへのログ記録
を設定するだけです。
filename
パラメータ
import logging
logging.basicConfig(
level=logging.WARNING, #set the level and display it according to the level
filename='example.log'
format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s') # set output format
logging.debug('This is a debug log')
logging.info('This is a info log')
logging.warning('This is a warning log')
logging.error('This is a error log')
logging.critical('This is a critical log')
fielnameを設定した場合、ログはコンソールに出力されないことに注意してください。
II. 高度な使用法
単純なコードであればロギングをそのまま利用できますが、より深く利用するためには、ロギングをオブジェクト指向で利用する必要があります。
ロギングコンポーネント
ロギングモジュールには、以下のコンポーネントが含まれます。
ステップ
1 ロガーの作成
import logging
# The first step creates a logger, which is used to generate logs
logger = logging.getLogger('%s_log' % __name__)
logger.setLevel(logging.DEBUG) # Set the logging level
getLogger メソッドでロガーを作成することができます。名前を指定しないと、ルートロガーが返されることに注意してください。
setLevelでロガーのレベルを設定します。
2 ログプロセッサの作成
# Create a text handler to write the log to a file
file_handler = logging.FileHandler(filename='py34.log',encoding='utf-8')
file_handler.setLevel('WARNING') # Set the logging level of the handler
# Create a console handler to output logs to the console
console_handler = logging.StreamHandler()
console_handler.setLevel('INFO') # Set the console handler's logging level
ログハンドラは、指定された場所にログを送信するものです。
FileHandler
ログをファイルに送信する
StreaHandler
sys.stdout、sys.stderr、または任意のファイルのようなオブジェクトなどのデータストリームにロギング出力を送信するためにそれを送信します。sys.stdoutはデフォルトのコンソールです。
RotatingFileHandler
ログファイルのサイズに応じたローテーションをサポート
TimedRotatingFileHandler
時間を基準にしたログファイルのローテーションに対応
詳しくは公式ドキュメントをご覧ください
3 フォーマッタを作成する
formatter = logging.Formatter(fmt='%(levelname)s %(asctime)s [%(filename)s-->line:%(lineno)d]:%(message)s')
フォーマッタをプロセッサに設定する必要があります。
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
4 フィルタを作成する
フィルタは、指定されたログをフィルタリングするために使用されます。具体的な使用方法は省略され、通常は使用されません。
詳しくは公式ドキュメントをご覧ください
5 プロセッサをロガーに追加する
logger.addHandler(file_handler)
logger.addHandler(console_handler)
6 ログを記録する
logger.info('This is a info')
2020-09-11 22:22:44,095-[->line:1]-INFO:This is a info.
logger.warning('This is a warning')
2020-09-11 22:23:20,337-[->line:1]-WARNING: これは警告です。
III. ロギングモジュールラッパー
機能的な分析
- ロガー名のカスタマイズ機能
- ログファイル名とパスのカスタマイズ機能
- ログファイルのエンコード方式をカスタマイズする機能
- ログフォーマットをカスタマイズする機能
- タイムローテーションプロセッサを使用し、設定できること
関数にラップする
commonディレクトリにlog_handler.pyモジュールを作成し、その中に以下の関数を作成します。
import logging
from logging.handlers import TimedRotatingFileHandler
def get_logger(name, filename, encoding='utf-8', fmt=None, when='d', interval=1, backup_count=7, debug=False):
"""
:param name: the name of the logger
:param filename: the name of the log file (including the path)
:param encoding: character encoding
:param fmt: the format of the log
:param when: log rotation time unit
:param interval: interval
:param backup_count: number of log files
:param debug: debugging mode
:return:
"""
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# The level of the file processor must be higher than the console in general
if debug:
file_level = logging.DEBUG
console_level = logging.DEBUG
else:
file_level = logging.WARNING
console_level = logging.INFO
if fmt is None:
fmt = '%(levelname)s %(asctime)s [%(filename)s-->line:%(lineno)d]:%(message)s'
file_handler = TimedRotatingFileHandler(
filename=filename, when=when, interval=interval, backupCount=backup_count, encoding=encoding)
file_handler.setLevel(file_level)
console_handler = logging.StreamHandler()
console_handler.setLevel(console_level)
formatter = logging.Formatter(fmt=fmt)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
return logger
if __name__ == '__main__':
log = get_logger(name='py41', filename='py41.log', debug=True, when='s')
log.info('I am a general message')
import time
time.sleep(3)
log.warning('I am a warning message')
IV. プロジェクトに応募する
にインポートする
ロガー生成関数は、Excelデータ読み込み関数のように、ユースケースモジュールごとに1回インポートすることはできません。ロガーオブジェクトを返すため、同じロガー名でロガー生成関数を複数回呼び出すと、同じロガーに複数のログプロセッサが追加され、ロガーが重複してしまうからです。
上記の問題を解決するために、共通フォルダに イニット このファイルは common モジュールがインポートされたときに、一度だけ自動的にこのファイルにあるコードを実行します。
での イニット .py ファイルに以下のコードを記述してください。
from .log_handler import get_logger
logger = get_logger('py41', 'py38.log')
そして、プロジェクト内の他のモジュールでは、次のコードでインポートすることができます。
from common import logger
これにより、get_logger メソッドはプロジェクト実行中に一度だけ実行されるようになります。
ログの記録
ログの目的は、プログラムの実行状態を記録し、エラーが発生したときにその場所を特定し、分析するための基礎を提供することです。
いつ、何を記録するかは、各人のプログラムに対する理解や経験に基づいて決定されます。
私たちのプロジェクトでは、プロセスがユースケースの実行の中心にあるため、ロギングもユースケースの実行が中心になっています。
ロギングを使用して、各ユースケースのテストデータ、およびテスト結果を、次のようなコードで記録します。
...
@list_data(*cases)
def test_login(self, case):
"""
Login test
"""
logger.info('Test case [{}] started testing'.format(case['title']))
# 1. test data
# The case parameters passed in
logger.info('Test data for test case [{}] is:{}'.format(case['title'], case))
# 2. test steps
res = login_check(case['username'], case['password'])
logger.info('The result of test case [{}] is:{}'.format(case['title'], res))
# 3. assertion
try:
self.assertEqual(res, case['expect'])
except AssertionError as e:
logger.error('Test case [{}] assertion failed'.format(case['title']))
raise e
else:
logger.info('Test case [{}] asserted successfully'.format(case['title']))
finally:
logger.info('Test case [{}] test ended')
上記は、3分でログを介してバグを見つけるためにPythonの自動化テストの詳細であり、バグを見つけるためにログについての詳細は、スクリプトハウスの他の関連記事に注意を払うしてください
関連
-
[解決済み】Flaskのテンプレートが見つからない【重複あり
-
[解決済み】AttributeError: 'Series'オブジェクトは'reshape'という属性を持っていない。
-
[解決済み] Pythonで関数を前方に宣言することは可能ですか?
-
[解決済み] 仕様エラーに対する解決策:agg()とgroupby()の併用時にネストしたリネーマーがサポートされない。
-
[解決済み] TypeError: 'str' はバッファのインタフェースをサポートしていません。
-
[解決済み] Pythonにおけるusleep
-
[解決済み] OpenCVウェブカメラをKivyのユーザインタフェースに統合する
-
[解決済み] 改行までのtqdm印刷
-
[解決済み] python socket.settimeout()の正しい使い方
-
非対応Pickleプロトコル
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] TypeError: 'DataFrame' オブジェクトは呼び出し可能ではない
-
[解決済み】matplotlibのbbox_to_anchorとloc
-
[解決済み] ピップフリーズとピップリストの比較
-
[解決済み] LabelEncoder: TypeError: '>' は 'float' と 'str' のインスタンスの間でサポートされていません。
-
[解決済み] Python:辞書を添え字可能な配列に変換する方法は?
-
[解決済み] Pythonでdatetime.timeにN秒を追加する標準的な方法は何ですか?
-
[解決済み] ファンクタを呼び出し可能なクラスとして、またはネストされた関数として作成する [終了] 。
-
[解決済み] com.apple.xbs フォルダがありません。
-
長年にわたるPythonで陥った落とし穴~不要な文字の消去について
-
python pip command install pyinstaller failed prompting Installing build dependencies ... error.