2011-08-26 26 views
36

私は現在、Pythonデスクトップアプリケーション用の2つの並列コードベースを維持しようとするほど愚かです.1つはPyGObjectイントロスペクションをGTK 3に使用し、もう1つはPyGTKをGTK 2に使用します。私は主にPyGObjectブランチで作業し、 PyGTKブランチに転送します。これらの実装間の小さな違いのため、私はしばしば事態を見落とし、私が逃して誤ってリリースする破損を引き起こし、ユーザーにしか捕まえられません。Python GUIアプリケーションのユニットテストにはどのような方法が推奨されますか?

私は、両方のコードベースで実行するのに適したユニットテストを設計する良い方法を見つけようとしています。それは、過度に複雑なプログラムではありません(それは基本的にライブラリ管理ツールですが、iTunesのように想像する):

- Main Window 
    |- Toolbar with some buttons (add/edit/remove items, configure the program) 
    | 
    |- VPaned 
    |--- Top HPaned 
    |------ ListView (listing values by which a library of items can be filtered) 
    |------ ListView (listing the contents of the library 
    |--- Bottom HPaned 
    |------ Image (displaying cover art for the currently selected item in the library) 
    |------ TextView (displaying formatted text describing the currently selected item) 
- Edit dialog 
- Configuration dialog 
- About dialog 

私はできる限りのモデルからビューを分離しようとしました。これらの項目はそれぞれ独自のクラスに実装されています(上のGTKクラスを継承したクラス)。 ListViewは、ListStoresを継承する他のクラスと結合されています。ライブラリ自体は別のクラスで扱われます。それにもかかわらず、テストする必要があるウィジェット間の相互作用があります。たとえば、フィルタビューで特定の項目を選択し、ライブラリをフィルタ処理した後、フィルタリングされた結果から項目を選択すると、翻訳されたためにテキストのビューに正しいライブラリエントリの情報が表示されます

このようなGUIアプリケーションのための堅牢な単体テストの作成にはどのような方法が推奨されますか?私はこれのためのいくつかのライブラリがあることを見てきましたが、pygtkの主なものは何年も更新されていないので、PyGObjectのイントロスペクションではほとんど確実に失敗します。おそらく、私はPythonのunittestモジュールを使ってそれを行う良い方法を理解するのに十分な創造力を持っていないので、私は提案をすることができます。

+0

誰かが尋ねる前に:pygtkはGTK 3をサポートしていませんが、GTK 2のpygobjectイントロスペクションのサポートがあまりにも不完全で依存していることがわかりました。 –

+1

GUIの使用時に回帰を避ける最良の方法は、マニュアルテストを行うことです。 Unittestは実際にMVCの場合のように仕事関数をテストするのには良いですが、私はあなたがguiに対処する方法がわかりません。 – ykatchou

+0

これは私がやっていることですが、私は明らかにそれほど良くはありませんが、すべてのリリース以来私は何かが恋しいです。 –

答えて

4

ユニット GUIをテストしてもよろしいですか?あなたの複雑さの例には、1つ以上のユニットが含まれているため、統合テストです。

本当に単体テストをしたいのであれば、その依存関係のモックやスタブを提供する単一のクラスをインスタンス化し、その上でメソッドを呼び出すことができます。ユーザーのクリックこれは面倒な作業であり、GUIフレームワークがユーザー入力をクラスにどのように送り出すのかを正確に知る必要があります。

私のアドバイスは、モデルにさらに多くのものを入れることです。あなたの与えられた例では、単一のメソッドの背後にあるすべてのフィルタ/選択/表示の要約を抽象化するFilterManagerを作成することができます。その後、ユニットテストします。 http://ldtp.freedesktop.org/wiki/

それを:

ユルゲンは、その中に正しかったテーマにこだわって
+0

ああ、おそらく私は自分の言葉が間違っている(これは私が学んだ/これのいずれかを使用してからほぼ10年を経た)。純粋に単体テストと定義されているか、または単体テストとして設計可能な統合テストですか?それにもかかわらず、私は多くのことが私の質問のコメントに記載された方法を使用して、私がそれを書いた方法で単体テストすることができると思います。 –

+1

ユニットテストのコアコンセプトは、テストを完全に、シンプルに、速く、失敗を正確に特定できるように、一度に1つのユニットをテストすることです。場合によっては、特にGUIの場合、これは難しい場合もあります。あなたは、非単体テストのためのPythonの単体テストモジュールのいくつかを使うことができるかもしれませんが、あなたはまたいくつかの利点を失います。 –

+1

これは本当の答えではありません...明らかに、彼はPyGTKとの統合テストを望んでいるので、用語を修正するのではなく正しい方向に向けるようにしてください。 – schlamar

2

私は単位テストに興味はなく、統合テスト中に実際に興味がない、私はまた、freedesktop.orgから、このフレームワークを見つけましたアクセシビリティ対応のGUIアプリケーション(GTK、Qt、Swingなど)のさまざまなテストを自動化することができます。

5

PyGTK関数とウィジェットを、忘却への道を辿るアクセプタンス/機能/統合テストフレームワークを経由せずに、直接テストする素晴らしい方法があります。私はthis postでこれについて学びましたが、これはかなり自明です。しかし基本的な考え方は、ウィジェットを関数/クラスとして扱い、直接テストすることができるということです。あなたは、コールバックなどを処理する必要がある場合は、私はここに再現する巧妙なトリックがあります:

import time 
import gtk 

# Stolen from Kiwi 
def refresh_gui(delay=0): 
    while gtk.events_pending(): 
     gtk.main_iteration_do(block=False) 
    time.sleep(delay) 

ブログ記事でmentionnedように、このコードはLGPLです。そうでなければ、あなたがそれについて考えている限り、ウィンドウやウィジェットでない限り、あなたはそれらをすべてテストすることができます。そして、それは実際のものであるかのように動作するはずです。それらは表示されません。

もちろん、ボタンやインタラクティブなウィジェットのインタラクションをボタンなどでclicked()を呼び出すことでシミュレートする必要があります。再びAli Afshar's excellent post about unit testing in PyGTKを参照してください。

0

あなたはX11フレームバッファを使用することができます。これは、マウスやキーボードの入力を待つことになるので、

Xvfb :119 -screen 0 1024x768x16 & 
export DISPLAY=:119 
... run your tests 

は、gtk.main()を入力しないように、注意してください。あなたはgtkのは、すべてのイベントを処理できるように、このパターンを使用することができます。

def refresh_gui(): 
    while gtk.events_pending(): 
     gtk.main_iteration_do(block=False) 

私の知る限り、あなたのアプリケーションを見ることはできませんが、あなたのコールバックをテストすることができます。

関連する問題