Python
pytest

pytestとマルチバイト文字問題のTips

環境

  • Cygwin
  • Python 2.7.14
  • pytest-3.3.2

テストコードにマルチバイト文字を使うときは注意

test_app.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

def test_1():
    a = "あああ"
    b = "あああ"
    assert a == b

def test_2():
    a = "あああ"
    b = "いいい"
    assert a == b

def test_3():
    a = u"あああ"
    b = u"いいい"
    assert a == b
terminal
$ pytest test_app.py
======================================= test session starts ========================================
platform cygwin -- Python 2.7.14, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /cygdrive/c/Users/foo/bar/pytest, inifile:
collected 3 items

test_app.py .FF                                                                           [100%]

============================================= FAILURES =============================================
______________________________________________ test_2 ______________________________________________

    def test_2():
        a = "あああ"
        b = "いいい"
>       assert a == b
E       AssertionError: assert '\xe3\x81\x82...2\xe3\x81\x82' == '\xe3\x81\x84\...4\xe3\x81\x84'
E         - \xe3\x81\x82\xe3\x81\x82\xe3\x81\x82
E         ?            ^           ^           ^
E         + \xe3\x81\x84\xe3\x81\x84\xe3\x81\x84
E         ?            ^           ^           ^

test_app.py:12: AssertionError
______________________________________________ test_3 ______________________________________________

    def test_3():
        a = u"あああ"
        b = u"いいい"
>       assert a == b
E       AssertionError: assert 'あああ' == 'いいい'
E         - あああ
E         + いいい

test_app.py:17: AssertionError
================================ 2 failed, 1 passed in 0.21 seconds ================================

test_2とtest_3の結果を見てわかるように、マルチバイト文字列の中身を読める形で表示するにはUnicode文字列を使う必要があるようです。

conftest.pyとマルチバイトでハマった

ということは、こういうこともあります。
例えばテスト結果のヘッダに日本語を使いたいとして(勧められるものではないかもしれませんが)、以下のようなconftest.pyを書いたとしましょう。先ほどのtest_app.pyと同じフォルダに置きます。

conftest.py
# -*- coding: utf-8 -*-

def pytest_report_header(config):
    return "テストヘッダ"

これでテストを実行します。どうなるでしょう。

terminal
$ pytest test_app.py
======================================= test session starts ========================================
platform cygwin -- Python 2.7.14, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
������������������
rootdir: /cygdrive/c/Users/foo/bar/pytest, inifile:
collected 3 items

test_app.py .FF

============================================= FAILURES =============================================
(以下略)

文字化けしてお話になりません。
実は、こちらもUnicode文字列を返すように変更してやれば直ります。

conftest.py
# -*- coding: utf-8 -*-

def pytest_report_header(config):
    return u"テストヘッダ"
terminal
$ pytest test_app.py
======================================= test session starts ========================================
platform cygwin -- Python 2.7.14, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
テストヘッダ
rootdir: /cygdrive/c/Users/foo/bar/pytest, inifile:
collected 3 items

test_app.py .FF

============================================= FAILURES =============================================
(以下略)

他にも文字化けが現れるパターンはいろいろありそうですが、まずはUnicodeを疑ってみると幸せになれるかもしれません。

Python3だと大丈夫かも

もっとも、これら一連の話はPython2だから気を遣うのであって、文字列がデフォルトでUnicode扱いになるPython3ではそれほど問題にならない疑惑。