こちらは、以前(2021.01.01)に別サービスで展開した内容を Qiita に移行したものです。
はじめに
以前、 「PySide & Pytest での テスト駆動開発 スタートアップ」にて、PySide + pytestする方法をまとめたが、以下のようなものをやっていた。
まずconftest.pyで、fixtureとして次を登録し、
@pytest.fixture
def base_window():
app = QApplication()
mainWindow = QMainWindow()
mainWindow.show()
return mainWindow
テストで、それを利用して、ウィジェットのスモークテストを行う
def test_addWidget(base_widget):
from MyCustomPySideLib,QCustomWidgets import QMyWidget
tagWidget = QMyWidget()
base_widget.setCentralWidget(tagWidget)
ということをしていたが、どうやら別の方法を提供している人もいるらしいという事で調べてみた。
pytest-qtの導入
pytest-qtで、こういったところをシミュレートできる。
pytest-qtは、pytestのプラグインとして扱われる。
インストールは、pipで行える。
pip install pytest-qt
pytest-qtを使って書く
pytest-qtを使ってはじめのテストコードを書き直すとこうなる。
Widgetの追加テスト
def test_addWidget(qtbot):
from MyCustomPySideLib,QCustomWidgets import QMyWidget
myWidget = QMyWidget()
qtbot.addWidget(myWidget)
ここで引数として使用されているqtbot
が、pytest-qtをインストールすることによって使用できる用になるfixtureとなる。
このqtbot
は、人の操作によるテストに加えて、Qt側のもろもろのテストとエラーに対するキャプチャ機能を備えている。
例えば、エラーをキャプチャする際にはこんなかんじ。
with qtbot.capture_exceptions() as exceptions:
qtbot.click(button)
シグナル待ちを含めたテスト
長時間処理を行う場合でのシグナル待ちや別スレッド処理中のシグナル待ちなどを含めたテストを書くこともできる。
def test_long_computation(qtbot):
app = Application()
with qtbot.waitSignal(app.worker.finished, timeout=10000) as blocker:
blocker.connect(app.worker.failed)
app.worker.start()
assert_application_results(app)
特定の状態待ちテスト
例えば、「ウィンドウのステータステキストが『Please input a number』になってなっているか」といったテストを書きたい場合、次のように書ける。
def test_validate(qtbot):
window = MyWindow()
window.edit.setText("not a number")
window.edit.setFocus()
def check_label():
assert window.status.text() == "Please input a number"
qtbot.waitUntil(check_label)
出力はこんな感じ
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def check_label():
> assert window.status.text() == "Please input a number"
E AssertionError: assert 'OK' == 'Please input a number'
E - OK
E + Please input a number
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
> qtbot.waitUntil(check_label)
E pytestqt.exceptions.TimeoutError: waitUntil timed out in 1000 miliseconds
まとめ
PySideのふるまいに関して、それぞれまじめにテストを書くという手もあるが、エラーキャプチャ周りや、スレッド分けしたものを追っていく、またはその方法を作るのは大変なので、このプラグインを使用することによって、その手間を省いてくれるのはありがたい。
ドキュメントを読んでいくと、まだまだ機能がある様なので、いろいろ試してみての恩恵具合を見てみたいところ。