LoginSignup
14

More than 5 years have passed since last update.

Pythonプログラムの標準出力をテストする

Posted at

対象の読者

  • ソフトウェア開発者
  • 競技プログラミング参加者

記事概要

  • 競技プログラミングなどでは、計算結果を標準出力に出力することが求められる場合があります。
  • これらを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メソッドを用いることで、行単位の判定ができます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14