Dogtail は、GUIアプリケーション用の自動テストツールです。
スクリプトにより、GUIを自動的に操作させることができます。
Linuxmania製品の出荷時の動作テストにも使用されている技術です。
Dogtail は、GUIアプリケーション用の自動テストツールで、
Python 言語向けモジュールとして提供されています。
バックエンドに AT-SPI(Assistive Technology Service Provider Interface) を
利用しています。
Dogtail のパッケージには、
(1) dogtail モジュール (Python スクリプトから利用されます)
(2) AT-SPI Browser (GUI アプリのツリー構造を表示します)
(3) Dogtail Script Recorder (ユーザの GUI 操作を記録します)
の3つが収録されています。
GUI アプリケーションの部品構成を論理的ツリー構造で表現し、
GUI 部品の情報取得や操作を可能にするものです。
ツリーの各ノードはName(名前), RoleName(GUI部品タイプ), Description(説明),
Actions(許可されている操作), States(GUI部品の状態) などの情報を持ちます。
論理ツリー構造は AT-SPI Browserで見ることができます。
AT-SPI は、スクリーンリーダや拡大鏡、DogtailやLDTPから利用されています。
Dogtail の検索では、Name や RoleName、Description などの情報が利用されています。
手続き指向、オブジェクト指向、いずれの場合でも、ツリーの上から順番にたどっていき、
目標のGUI部品に近づいてから操作する形をとります。
目標GUI部品の上の部品にフォーカスを当ててから、操作(クリックなど)を実行します。
[例] from dogtail.procedural import * ... focus.application('gedit') # (1) アプリケーション focus.frame('test.txt (~) - gedit') # (2) ウィンドウ click('ファイル(F)', roleName='menu') # (3) メニュー click('保存(S)', roleName='menu item') # (4) メニューアイテム
GUI部品に対応するNodeオブジェクトを取得後、Nodeオブジェクトに対し操作を指示します。
[例] from dogtail.tree import * ... gedit = root.application('gedit') # (1) アプリケーション gedit_win = gedit.window('test.txt (~) - gedit') # (2) ウィンドウ gedit_win.child('ファイル(F)', roleName='menu').click() # (3) メニュー gedit_win.child('保存(S)', roleName='menu item').click() # (4) メニューアイテム
Fedora、CentOS、Ubuntu では標準リポジトリに収録されています。
[Fedora, CentOS] # yum install dogtail [Ubuntu] $ sudo apt-get install python-dogtail
Dogtail の初回利用前に、支援技術を有効にする必要があります。
支援技術を有効にするには、[システム]→[設定]→[ユーザ向け]→[支援技術]で
「支援技術を有効にする」にチェックを入れ、一度ログアウトします。
Python スクリプトを作成後、端末から実行します。
スクリプトの作成方法には3つあります。
(1) Dogtail Script Recorder を利用する
(2) 自分で作成する(手続き指向モジュールを利用)
(3) 自分で作成する(オブジェクト指向モジュールを利用)
GNOMEメニュー [アプリケーション]→[プログラミング]→[Dogtail Script Recorder] を実行します。
[●録画] を押すとGUIに対する操作の記録を開始します。[□停止] を押すまでの間、操作が記録されます。
※ただし、マウスカーソルの移動量などは記録できません。
また、一部取りこぼす操作があるため、保存後に少し修正する必要があります。
[演奏] を押すと、記録された操作が自動的に実行されます。
[保存] を押すとスクリプトをファイルに保存できます。
エディタで Python スクリプトを自作します。
手続き指向モジュールを利用する場合は、次のように書き始めます。
#!/usr/bin/env python # -*- encoding:UTF-8 -*- from dogtail.procedural import *
エディタで Python スクリプトを自作します。
オブジェクト指向モジュールを利用する場合は、次のように書き始めます。
#!/usr/bin/env python # -*- encoding:UTF-8 -*- from dogtail.tree import *
1| #!/usr/bin/env python 2| # -*- encoding:UTF-8 -*- 3| from dogtail.procedural import * 4| 5| run('gedit', 'test.txt') 6| focus.application('gedit') 7| focus.frame('test.txt (~) - gedit') 8| type("test") 9| click('ファイル(F)', roleName='menu') 10| click('保存(S)', roleName='menu item') 11| click('ファイル(F)', roleName='menu') 12| click('終了(Q)', roleName='menu item')
3行…dogtail.procedural (手続き指向モジュール) をimport
5行…gedit を起動し、test.txt を開きます
6行…geditにフォーカスを当てます
7行…geditのウィンドウにフォーカスを当てます
8行…文字列「test」を入力
9行…メニュー [ファイル(F)] をクリック
10行…メニューアイテム [保存(S)] をクリックし、ファイルを保存
11行…メニュー「ファイル(F)」をクリック
12行…メニューアイテム「終了(Q)」をクリックし、gedit を終了
1| #!/usr/bin/env python 2| # -*- encoding:UTF-8 -*- 3| from dogtail.tree import * 4| 5| run('gedit test.txt') 6| gedit = root.application('gedit') 7| gedit_win = gedit.window('test.txt (~) - gedit') 8| type("test") 9| gedit_win.child('ファイル(F)', roleName='menu').click() 10| gedit_win.child('保存(S)', roleName='menu item').click() 11| click('ファイル(F)', roleName='menu') 12| click('終了(Q)', roleName='menu item')
3行…dogtail.tree (オブジェクト指向モジュール) をimport
5行…gedit を起動し、test.txt を読み込みます
6行…gedit アプリケーションを指す Application オブジェクトを取得します
7行…gedit ウィンドウを指す Node オブジェクトを取得します
8行…文字列「test」を入力
9行…メニュー [ファイル(F)] をクリック
10行…メニューアイテム [保存(S)] をクリックし、ファイルを保存
11行…メニュー「ファイル(F)」をクリック
12行…メニューアイテム「終了(Q)」をクリックし、gedit を終了
[関数] run(application, arguments='') [引数] application … 起動するコマンド名 (文字列) arguments … 起動時に与える引数 (文字列) [例] run('gedit', arguments='test.txt')
[関数] focus.application(name) [引数] name … アプリケーション名 (文字列) [例] focus.application('soffice')
[関数] focus.frame(name) [引数] name … ウィンドウ名 (文字列) [例] focus.frame('test.txt - gedit')
[関数] focus.dialog(name) [引数] name … ダイアログ名 (文字列) [例] focus.dialog('別名で保存…')
[関数] focus.text(name) [引数] name … テキストエリア名 (文字列) (省略可) [例] focus.text()
[関数] click(name='', roleName='', description='', raw=True, button=1, delay=1.0) [引数] name … クリックしたいアイテムの名前を指定 (デフォルトでは指定なし) roleName … クリックしたいアイテムのroleNameを指定 (デフォルトでは指定なし) description … クリックしたいアイテムの説明文を指定 (デフォルトでは指定なし) button … マウスのどのボタンでクリックするか指定 (1(左)、2(中)、3(右)) delay … クリック後の待ち時間(ディレイ) [例] click('保存(S)', roleName='menu item')
[関数] type(text) [引数] text … 入力するテキスト (文字列) [例] type('hogehoge')
[関数] keyCombo(combo) [引数] combo … 入力するキー入力 (文字列) [例] keyCombo("Return") keyCombo("<Control>s")
AT-SPI ツリーのルートノードを表すクラスです。
Root クラスは Node の派生クラスです。
dogtail.tree.root オブジェクトとして作成済みです。
[メソッド] applications() application(appName) … アプリケーションを検索して Application オブジェクトを返します [引数] appName … アプリケーション名 (文字列)
アプリケーションを表すクラスです。
Application クラスは Node の派生クラスです。
[メソッド] window(windowName, recursive=False) [引数] windowName … ウィンドウ名 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
[メソッド] dialog(dialogName, recursive=False) [引数] dialogName … ダイアログ名 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
GUI部品を表すクラスです。
アプリケーションの構成にあわせ、ツリー構造を形成します。
[メソッド] click(button=1) [引数] button … クリックするボタンを指定 (1(左)、2(中)、3(右)) (省略可)
[メソッド] child(name='', roleName='', description='', recursive=True) [引数] name … GUI部品の名前を指定 (文字列) (省略可) roleName … GUI部品のタイプを指定 (文字列) (省略可) description … GUI部品の説明文を指定 (文字列) (省略可) recursive … 再帰的に検索を行うか指定 (論理値) (省略可) ※name、roleName、description のうちどれか1つは必ず指定する必要があります
[メソッド] typeText(string) [引数] string … 打ち込む文字列 (文字列)
[メソッド] keyCombo(comboString) [引数] comboString … キー入力を指定 (文字列)
[メソッド] menu(menuName, recursive=True) [引数] menuName … メニュー名を指定 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
[メソッド] menuItem(menuItemName, recursive=True) [引数] menuItemName … メニューアイテム名を指定 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
[メソッド] textentry(textEntryName, recursive=True) [引数] textEntryName … テキストエントリ名を指定 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
[メソッド] button(buttonName, recursive=True) [引数] buttonName … ボタン名を指定 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
[メソッド] tab(tabName, recursive=True) [引数] tabName … タブ名を指定 (文字列) recursive … 再帰的に検索するか指定 (論理値) (省略可)
.children … 子ノードのリスト .roleName … 自ノードのroleName .indexInParent … 自ノードが親ノードの何番目の子か .actions … 自ノードが許可するアクションの辞書 .text # テキストをgetしたりsetしたりする .position # Nodeの位置(x,y)をゲットする .size # Nodeのサイズ(w,h)をゲットする .sensitive … 自ノードのGUI部品が有効かどうか .focusable … 自ノードのGUI部品がフォーカス可能かどうか
Dogtail 公式サイト
https://fedorahosted.org/dogtail/
Package dogtail (リファレンス)
https://fedorapeople.org/~zmc/dogtail/epydoc/
「Dogtailによる自動GUIテスト」
https://www.jp.redhat.com/magazine/NO24/
Dogtail's Python Modules (and how to use them)
https://www.redhat.com/magazine/021jul06/features/dogtail/
AT-SPI C Bindings Reference Manual
https://library.gnome.org/devel/at-spi-cspi/
AT-SPI Interfaces and Subinterfaces
https://www.gnome.org/~billh/at-spi-idl/
Python 2.5 公式チュートリアル
http://www.python.jp/doc/release/tut/