対象の読者
- ソフトウェア開発者
- 競技プログラミング参加者
記事概要
- 競技プログラミングなどでは、計算結果を標準出力に出力することが求められる場合があります。
- これらをUnittestフレームワークを用いて、End-to-Endにテストするコードを紹介します。
前提条件
- Python 3.5 以降で動作検証しています。
テスト対象
- 次のようなコードをテスト対象にするとします。
test_target.py
# -*- coding: utf-8 -*-
def print_something(value):
print('{0}'.format(value))
return
やりかた
シンプルな方法
Pythonの標準ライブラリに、テスト用に標準出力をキャプチャする機能があるので、それをUnittestフレームワーク内で使います。
test_sample1.py
from unittest import TestCase
from test.support import captured_stdout
from .test_target import print_something
class StdoutCaptureTestCase(TestCase):
def test_print_something(self):
test_value = 'Hello'
with captured_stdout() as stdout: # captured_stdout() yields stream that contain strings of stdout.
print_something(value=test_value)
self.assertEqual(stdout.getvalue(), 'Hello\n') # stdout.getvalue() returns the entire contents of stdout includes Line Feed.
問題点
- 改行コードも含めて1つの文字列としてキャプチャされるため、プラットフォームの差異の影響を受ける。
- 行単位の判定ができない
改良した方法
stdout.getvalueが返す文字列の.splitlinesメソッドを呼び出し、配列に格納した上で判定します。
test_sample2.py
class StdoutCaptureTestCase(TestCase):
def test_multiple_lines(self):
with captured_stdout() as stdout:
print_something(value='Hello')
print_something(value='World')
lines = stdout.getvalue().splitlines() # Splitlines method divide strings to an array, Line Feed will disappear.
self.assertEqual(lines[0], 'Hello')
self.assertEqual(lines[1], 'World')
この方法であれば、改行コードを気にすることなく、かつ行ごとに判定できます。
まとめ
- Pythonの標準ライブラリで、標準出力もテストできます。
- splitlinesメソッドを用いることで、行単位の判定ができます。