tag:crieit.net,2005:https://crieit.net/tags/unittest/feed
「unittest」の記事 - Crieit
Crieitでタグ「unittest」に投稿された最近の記事
2022-03-13T17:20:40+09:00
https://crieit.net/tags/unittest/feed
tag:crieit.net,2005:PublicArticle/18152
2022-03-13T17:19:46+09:00
2022-03-13T17:20:40+09:00
https://crieit.net/posts/Python-unittest-ResourceWarning-unclosed-file
Pythonのunittest実行時に、「ResourceWarning: unclosed file」が発生する場合の対処方法
<p>Pythonでunittestを実行していた際に、「ResourceWarning: unclosed file」が出力されたので、その対処方法について、記載。</p>
<pre><code>global logins
def log_setting(log_level):
global logins
home = '<ログファイルパス>'
pid = os.getpid()
# create logger
logins = logging.getLogger(__name__)
logins.setLevel(logging.DEBUG)
# create File Handler
fh = logging.FileHandler('{0}/log/log{1}.log'.format(home, pid))
fh.setLevel(logging.INFO)
# create Formatter
fh_formatter = \
logging.Formatter(
'%(asctime)s - %(levelname)s - \
%(filename)s - %(name)s - %(funcName)s - %(message)s')
# set Formatter
fh.setFormatter(fh_formatter)
# add Handler
logins.addHandler(fh)
# test logging
logins.info('logtest:addHandler')
</code></pre>
<p>↑みたいな関数があり、unittest側からは下記でテストメソッド単位で呼び出したとする。</p>
<pre><code>def setUp(self):
logtest.log_setting(logging.DEBUG)`
def tearDown(self):
logtest.logins.handlers = []
</code></pre>
<p>この場合、unittestを実行すると、ログファイル内に「ResourceWarning: unclosed file」が出力される。<br />
理由はログファイルがクローズされていない状態で、ハンドラをクリアしているから。<br />
ハンドラをクリアしている理由は、そうしないとテストメソッドの実行の都度、「log_setting」が呼び出されてハンドラが追加され、ログが重複して出力されてしまうから。</p>
<p>ログファイルをクローズする処理を入れればいいので、下記のようにする。</p>
<pre><code>def tearDown(self):
logtest.logins.handlers[0].close()
logtest.logins.handlers = []
</code></pre>
<p>こうすると、ログファイルをクローズした後にハンドラをクリアするので、警告は出力されない。<br />
ログも重複しない。</p>
<p>本当にいいのは、テスト対象側のプログラムを修正することだと思う。<br />
ファイル出力しかしない想定であれば、addHandlerを使う必要はなく、下記で対応ができる。↓のほうがコード短いし、↑よりもいいかな。</p>
<p>```<br />
def log_setting(log_level):<br />
global logins<br />
home = '/home/aoiro/work/logtest'<br />
pid = os.getpid()</p>
<pre><code># create logger
logins = logging.getLogger(__name__)
log_format = \
'%(asctime)s - {} - %(levelname)s - %(message)s'.format("tester")
logging.basicConfig(
filename='{0}/log/log{1}.log'.format(home, pid),
level=log_level, format=log_format)
</code></pre>
<p>```</p>
ao-iro