Copyright 2004 - 2007 Novell, Inc.
Copyright 2008 - 12 Nagappan Alagappan
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Lesser General Public License, Version 2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Lesser General Public License".
You should have received a copy of the GNU GNU Lesser General Public License along with this documentation; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
(訳)
(この文書を、フリー・ソフトウェア財団発行の GNU 劣等一般公衆利用許諾契約書(バージョン 2 か、それ以降のバージョンから一つを選択)が定める条件の下で複製、頒布、あるいは改変することを許可する。この文書に変更不可部分、表紙表側の文言、表紙裏側の文言は存在しない。この利用許諾契約書の複製物は「GNU 劣等一般公衆利用許諾契約書」という章に含まれている。)
(この文書とともに、GNU 劣等一般公衆利用許諾契約書を一刷受け取ったはずだが、もし受け取っていなければ、フリー・ソフトウェア財団に請求すること。宛先は the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA である。)
著者
Nagappan A <nagappan@gmail.com>
協力者:
Harsha <nharsha@gmail.com>
Premkumar J <prem.jothimani@gmail.com>
Guofu Xu <lavixu@gmail.com>
Surendran M <suren.silverprince@gmail.com>
Vamsi B <vamsi1985@gmail.com>
Linux Desktop Testing Project(LDTP) の狙いは、高品質な自動試験の仕組みを考案し、GNU/Linux デスクトップの試験と改良に使える最先端のツール群を作り出すことである。アプリケーションのユーザ・インタフェイスを調べるにあたっては、アクセシビリティ・ライブラリ(Accessibility libraries)を使用している。この計画は Microsoft Windows や Mac OS X にも広まっており、前者では Cobra、後者では ATOMac として実装済みである。これ故に我々は自信を持って次のように言える。プラットフォームに囚われない GUI 試験ツールを実装し得たと。LDTP は今のところ、Windows / Mac / Linux / Palm Source / Solaris / NetBSD / FreeBSD で動かすことが出来る。
LDTP の core framework では、Appmap という規約と、アプリケーションを試験する定型の試行関数とが使われている。この core 部分は、試行関数の結果を出力してくれる。LDTP は、.NET / GNOME / KDE (QT >=4.8) のアプリケーションのうち、アクセシビリティ機能が有効になっているもの全てで試験を行うことが出来る。例えば、Mozilla、Open Office/Libre Office、Java アプリケーション(ユーザ・インタフェイスに Swing を用いているものに限る)である。
当計画に参加したいという方は歓迎する。Windows/Linux の両デスクトップに対応した、堅牢・安定で信頼できる試験ツールとその仕組みを一緒に開発してほしい。Microsoft / Apple / GNOME アクセシビリティ・チーム及び Sun Microsystems アクセシビリティ・チームの素晴らしい成果と弛まざる支援に感謝する。
本文書は、GUI アプリケーションの UI 制御について少しだけ学んでおり、Windows / Mac OS X / Linux あるいは Unix(Solaris / BSD 系)については最低限の知識を持つ読者を想定している。(訳註:著者の little と few の使い方)
試験(testing)はソフトウェア・システムの缺陥を突き止める作業である。詳しくは、http://en.wikipedia.org/wiki/Software_testing。
アプリケーションを同じ手順で何度も試験する場合、自動処理の方が上手くいくであろう。
LDTP を用いて、アクセシビリティ機能が有効になっているアプリケーションの動作(functionality)を試すことが出来る。
今のところ、LDTP で試験可能なのは .NET / GNOME アプリケーションの中、アクセシビリティ機能が有効になっているもの全てである。Mozilla、Open Office / Libre Office、Java アプリケーション(UI に Swing を用いているものに限る)、及び QT 4.8 を用いる KDE アプリケーション。
http://lists.freedeskto.org/mailman/listinfo/ldtp-dev
#ldtp of irc.freenod.net
最大使用量は 450KB (Linux)、5 MB (Windows)、450 KB (Mac OS X)。
Mac OS x / Windows / RPM / Deb / Gentoo / Solaris の最新パッケージを次の場所からダウンロード「http://ldtp.freedesktop.org/wiki/Download」
試験スクリプトは LDTP API インタフェイスを利用し、同 API は UNIX ソケットあるいは TCP ソケットを使って LDTP エンジンと通信する。LDTP エンジンは AT-SPI ライブラリを使って試験対象のアプリケーション(Application under test - AUT)と対話する。
LDTP クライアントは XML RPC プロトコルを用いて LDTP エンジンと遣り取りする。
LDTP の構想の大部分は、http://safsdev.sf.net を参考にして肉付けした。大多数のコマンドは少なくとも二つの引数をとる。先頭の引数は文脈(context - 作業を行いたいウィンドウのこと)であり、二番目の引数は部品(component - 作業を行いたいオブジェクト、その時点の文脈に則る)である。
例:click ('*-gedit', 'btnNew')
このクリック操作は、「*-gedit」(正規表現で)という名前を持つウィンドウの中の、プッシュ・ボタン型で「New」という名前を持つオブジェクトに対して実行される。
試験スクリプトが始動すると、LDTP クライアントは AF_UNIX / AF_INET を使って LDTP エンジンへの接続を確立する。
スクリプトからコマンドが実行される度に、クライアントは XML データを組み、同データをサーバに送信する。LDTP エンジンは、クライアントから来たコマンド・リクエストを解析し、該当するコンポーネント・ハンドラ(各部品を担当する処理)を呼び出す。
個々の部品(component)のハンドラは、AT-SPI ライブラリを用いて各アプリケーションと通信する。実行結果に基づいて、成功したのか失敗したのかをクライアントに通知する。この返信は XML 形式で記述される。例えば「gettextvalue」のように、要求の基づいて各部品(component)のデータがクライアントに返って来ることもある。
出現時点が予想できないウィンドウ(例:相手による接続のリセット / 接続の時間切れを示すダイアログ)は、コールバック関数を登録しておくことで処理できる。登録してあったタイトル(ウィンドウ名)のウィンドウが現れる度に、該当するコールバック関数が呼び出される。このウィンドウ名の指定は正規表現でも構わない。
「Appmap」[Application Map の略]は、試験中の GUI を文字列で表現したものである。ボタン、テキスト・ボックスなどの各 UI 部品は孰れも、予め定義してある規約(下表に記す)を用いて表す。その際には、同部品の親 UI オブジェクトの情報も援用する。実行時に特定の UI 部品にアクセスするには、試験中の GUI 向けに生成された Appmap を使う。Appmap について詳しく知りたければ http://safdev.sourceforge.net/DataDrivenTestAutomationFrameworks.htm#TheApplicationMap を参照。
Class keywords | appmap で使う慣用表現 |
---|---|
ACCEL_LABEL | |
ALERT | dlg |
ANIMATION | |
ARROW | |
CALENDAR | cal |
CANVAS | cnvs |
CHECK_BOX | chk |
CHECK_MENU_ITEM | mnu |
COLOR_CHOOSER | |
COLUMN_HEADER | |
COMBO_BOX | cbo |
DATE_EDITOR | |
DESKTOP_ICON | |
DESKTOP_FRAME | frm |
DIAL | dial |
DIALOG | dlg |
DIRECTORY_PANE | |
DRAWING_AREA | dwg |
FILE_CHOOSER | dlg |
FILLER | flr |
FONT_CHOOSER | dlg |
FRAME | frm |
GLASS_PANE | |
HTML_CONTAINER | html |
ICON | ico |
IMAGE | img |
INTERNAL_FRAME | |
LABEL | lbl |
LAYERED_PANE | pane |
LIST | lst |
LIST_ITEM | lsti |
MENU | mnu |
MENU_BAR | mbar |
MENU_ITEM | mnu |
OPTION_PANE | opan |
PAGE_TAB | ptab |
PAGE_TAB_LIST | ptl |
PANEL | pnl |
PASSWORD_TEXT | txt |
POPUP_MENU | pop |
PROGRESS_BAR | pbar |
PUSH_BUTTON | btn |
RADIO_BUTTON | rbtn |
RADIO_MENU_ITEM | mnu |
ROOT_PANE | rpan |
ROW_HEADER | rhdr |
SCROLL_BAR | scbr |
SCROLL_PANE | scpn |
SEPARATOR | sep |
SLIDER | sldr |
SPIN_BUTTON | sbtn |
SPLIT_PANE | splt |
STATUS_BAR | stat |
TABLE | tbl |
TABLE_CELL | tbl |
TABLE_COLUMN_HEADER | tch |
TABLE_ROW_HEADER | trh |
TEAROFF_MENU_ITEM | tmi |
TERMINAL | term |
TEXT | txt |
TOGGLE_BUTTON | tbtn |
TOOL_BAR | tbar |
TOOL_TIP | ttip |
TREE | tree |
TREE_TABLE | ttbl |
UNKNOWN | unk |
VIEWPORT | view |
WINDOW | dlg |
EXTENDED | |
HEADER | hdr |
FOOTER | foot |
PARAGRAPH | para |
RULER | rul |
APPLICATION | app |
AUTOCOMPLETE | txt |
CALENDARVIEW | cal |
CALENDAREVENT | cal |
EDITBAR | txt |
ENTRY | txt |
オブジェクトに働きかけるための主要な二つの媒体、「ウィンドウ名」と「オブジェクト名」。
ウィンドウに指示を出すには、ウィンドウ名を知らなければならない。ここで言うウィンドウ名とはウィンドウのタイトルのことである。
ウィンドウ名は、glob パターン( * や ? など)を使って纏めて指定できる。
もしウィンドウのラベル(表示文字列)に空白文字や改行文字が含まれている場合、それらは取り除かれる。
オブジェクト(作業を行いたい部品)は、ラベルそのものとして同定可能であるか、さもなければ附属ラベルによって指定できる。
メニュー、メニュー・アイテム、プッシュ・ボタン、トグル・ボタンのような部品全般は、それらのラベルを通じてアクセスできる。
mnuFile (gedit のメニュー)
mnuNew (gedit のメニュー・アイテム)
btnNew (gedit のツール・バー、プッシュ・ボタン)
tbtnLocation (gedit のファイルを開くダイアログ、トグル・バー部)
テキスト、テーブル、チェック・ボックス、ラジオ・ボタン、スピン・ボタン、コンボ・ボックス、これらの部品は総じて附属ラベルを使わなければアクセスできない。
txtLocation (gedit のファイルを開くダイアログ、テキスト部)
tblFiles (gedit のファイルを開くダイアログ、テーブル部)
choSearchfor (gedit の Find ダイアログ、コンボ・ボックス部)
chkMatchcase (gedit の Find ダイアログ、チェック・ボックス部)
sbtnRightmarginatcolumn (gedit の Preferences ダイアログ、スピン・ボタン部)
ラベルも附属ラベルも無い部品は、番号(index)を用いてアクセス出来る。
txt0 (gedit のテキスト表示領域)
ptl0 (gedit の Preferences ダイアログ、ページ・タブ・リスト部)
ptl0 (gedit では複数のファイルを開いている時、ページ・タブ・リスト部が現れる)
同一ウィンドウ上の複数の場所に同型の部品が存在し、且つそれらのラベルが同じであるという状況も考えられる。その場合、最初の部品は標準の記法でアクセスできるが、二番目以降の部品は「部品の型」「ラベルもしくは附属ラベル」「番号」の形式で記述してアクセスする。この際、番号は 1 から数え始める。
btnAdd - 第一のプッシュ・ボタン部で、ラベルは Add である。
btnAdd1 - 第二のプッシュ・ボタン部で、ラベルは Add である。
btnAdd2 - 第三のプッシュ・ボタン部で、ラベルは Add である。
オブジェクトはウィンドウ ID と一対一で結び付くものと考えて良い。ある時点で実行中のアプリケーション全てを通じて、ウィンドウ ID は唯一無二のものである。これは i18n/l10n の環境でも変わらない。API に渡すオブジェクト名は、先頭に「#」、それに続けてウィジェットを表す唯一無二の数字を書いたものとなる。
#1234 - 「Visual UI Verify」では、Automation ID として使える。
特定ウィンドウにおいて、ウィジェット型を同じくするものの中での番号によって、部品を指定する。オブジェクト名の形式は、LDTP 規約の下でのオブジェクト型、続けて同型オブジェクトの中でのオブジェクト番号(index)、となる。
btn#0 - 特定ウィンドウにおける第一のボタン。
txt#1 - 特定ウィンドウにおける第二のテキスト・ウィジェット
オブジェクトのラベルあるいは附属ラベルに空白、ドット、コロン、アンダースコア、改行の文字が含まれる場合、これらは取り除かれる。
「Search for」は「Searchfor」となる。
「File name 'a_txt' already exist.
Replace」は「Filename'atxt'alreadyexistReplace」となる。
LDTP は、GNOME 環境に備わるアクセシビリティ・ライブラリを利用している。アクセシビリティを使うことで、アプリケーションの情報と、同アプリケーションの状態(プロパティ)に関する情報とを取得できる。アプリケーションの各層を自由に利用できるようにするための唯一無二の条件は、同アプリケーションのアクセシビリティ機能が有効であることである。
GNOME 2.x の場合、GNOME コントロール・センターにて支援技術(訳註:要確認)を開く。
図 1:GNOME コントロール・センターにおける支援技術の設定(訳註:要確認)。
GNOME 3.x: 次のコマンドを打ち込み、アクセシビリティ機能を有効にする。
gsettings set org.gnome.desktop.interface toolkit-accessibility true
Microsoft Windows: 設定を弄る必要は無い。標準でアクセシビリティ機能が有効になっている。
Mac OS X: システム全体のアクセシビリティを有効にしなければならない。「System Preferences」 > 「Universal Access」 > 「補助装置を使用可能にする」(Enable access for assistive devices)。有効化に失敗したときは、何らかのモジュールの使用時に例外「ErrorAPIDisabled」が発生する。
図 2:支援技術設定画面のスクリーン・ショット(訳註:要確認)
from ldtputils import *
玄論:「import ldtp」ではなく上記の形式で取り込むのには理由がある。上の方法を選べば、ldtp の全ての関数が関数名だけで直接呼び出せるようになるからである。モジュールを「import ldtp」で取り込んだ場合、先と同じ関数を呼び出すのに「ldtp.<関数名>」と書かなければならない。
from ldtp import *
selectmenuitem ('*-gedit', 'mnuFile;mnuNew')
import ldtp
ldtp.selectmenuitem ('*-gedit', 'mnuFile;mnuNew')
LDTP は大抵、指定したウィンドウの中の特定のオブジェクトに働きかける。
メニュー・アイテムを選ぶには、関数 selectmenuitem を呼び出す。例を挙げると、アプリケーション「gedit」でメニュー・アイテムの「Open」を選択するには次の関数を呼び出す。
上の関数呼び出しを行うと、新しいダイアログ・ボックスが出て来る。ウィンドウが開いたかどうかは、guiexist もしくは waittillguiexist を使って確かめることができる。
ウィンドウ中のプッシュ・ボタンに働きかけたい場合、関数 click を用いる。
GTK の「開くファイルを選ぶ画面」において、「Cancel」ボタンを押すには、
上の操作を行うと、GTK のファイル選択画面が消える。実際にウィンドウが消えたか否かを確認するには、関数 waittillguinotexist を用いる。
gedit では開いたファイルに手を加えると、そのウィンドウのタイトルも変更される。同じウィンドウで作業を続けるには、作業の文脈(context)を切り替える必要がある。理由:察しの通り、LDTP は個々のウィンドウを対象に据えて動作する。それゆえ、ウィンドウのタイトルが変更されると、ウィンドウの文脈(context)も変わる。対策は、関数 setcontext を用いること、及び文脈が不要になったら releasecontext を用いることである。
開いたファイルのうち、現在表示されているものを編輯するには、
これによって、ウィンドウのタイトルが変わる。上記操作を行う前のタイトルが「Unsaved Document 1 - gedit」であれば、編輯後のタイトルは「*Unsaved Document 1 - gedit」のようになる。同じウィンドウに対して続けて操作を行うには、
これによって、同じウィンドウ名を使い続けることができるようになる。例えば、
この関数で GTK の保存画面(save dialog box)が呼び出される。
動作を齎す関数(selectmenuitem、click、settextvalue など)が蹉跌した場合、例外が発生する。この例外はプログラム側で処理しなければならず、実行中の操作を続けるか、あるいは単に停止するか、どちらかの措置をとる。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> guiexist ('*-gedit')
1
>>> guiexist ('frmUnsavedDocument1-gedit')
1
>>> guiexist ('frmUnsavedDocument1-*')
1
>>> guiexist ('frm*-gedit')
1
>>> guiexist ('Unsaved Document 1 - gedit')
1
gedit のウィンドウの中にあるオブジェクトに働きかけるには、オブジェクトの情報を知っておく必要がある。
gedit のツール・バーの一部であるプッシュ・ボタン「Open」をクリックするには、click というAPI を用いる。この際、第一引数にはウィンドウ名を、第二引数にはオブジェクト名を指定する。下のコマンドではクリック操作を行っている。利用する情報はウィンドウ名「Unsaved Document 1 - gedit」とプッシュ・ボタン部名「Open」である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> click ('*-gedit', 'btnOpen')
1
ウィンドウ中のメニューの下に表示されるメニュー・アイテムを選択するには、API selectmenuitem を用いる。
必要な情報は、ウィンドウ名「Unsaved Document 1 - gedit」、メニュー部「File」、メニュー・アイテム部「New」である。
メニューは、階層構造を踏まえて扱わなければならない。メニュー・アイテム「New」を利用するには、メニュー部「File」も必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> selectmenuitem ('*-gedit', 'mnuFile;mnuNew')
1
トグル・ボタンにクリック操作を施すために必要な情報は、ウィンドウ名「OpenFiles...」(訳註:訳者の環境では「OpenFiles」)とトグル・ボタン部「Type a file name」である。(訳註:トグル・ボタン部の上にマウスを載せると「ファイル名を入力してください」「Type a file name」などと出る)
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> click ('dlgOpenFiles...', 'tbtnTypeafilename')
1
テキスト・ボックスに文字列を入力するには、ウィンドウ名「Open Files...」(訳註:訳者の環境では「Open Files」)、テキスト部附属ラベル「Location:」、書き込むべき文字列「Class1.cs」が要る。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> settextvalue ('dlgOpenFiles...', 'txtLocation', 'Class.cs')
1
GTK のファイルを開く画面において選択肢の一覧から一つ選ぶには、ウィンドウ名「Open Files...」(訳註:訳者の環境では「Open Files」)、テーブル名(Files - 青い円で印されたファイル群)、選択する行「Class1.cs」といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> selectrow('dlgOpenFiles...', 'tblFiles', 'Class1.cs')
1
ファイル名を選択した後、ファイルの中身を開くには、プッシュ・ボタン部「Open」をクリックする必要がある。この操作には、ウィンドウ名「Open Files...」(訳註:訳者の環境では「Open Files」)、プッシュ・ボタン・ラベル名「Open」といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> click ('dlgOpenFiles...', 'btnOpen')
1
チェック・ボックス部をクリックするには、ウィンドウ名「gedit Preferences」、チェック・ボックス附属ラベル名「Display line numbers」といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> click ('dlggeditPreferences', 'chkDisplaylinenumbers')
1
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> check ('dlggeditPreferences', 'chkEnabletextwrapping')
1
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> uncheck ('dlggeditPreferences', 'chkDisplaylinenumbers')
1
スピン・ボタンに働きかけるには、ウィンドウ名「gedit Preferences」、スピン・ボタン部の名前「Right margin at column」といった情報が要る。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> getvalue ('dlggeditPreferences', 'sbtnRightmarginatcolumn')
80.0
>>> setvalue ('dlggeditPreferences', 'sbtnRightmarginatcolumn', '81')
1
>>> setvalue ('dlggeditPreferences', 'sbtnRightmarginatcolumn', '80')
1
ページ・タブの列(page tab list)に働きかけるには、ウィンドウ名「gedit Preferences」、ページ・タブ列の名(ここで取り上げるページ・タブ列部品にはラベルや附属ラベルが無いため、「ptl0」となる)、ページ・タブの名前か要素番号(index)といった情報が必要である。ページ・タブの番号は 0 から始まる。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> gettabcount ('dlggeditPreferences', 'ptl0')
5
>>> selecttabindex ('dlggeditPreferences', 'ptl0', 2)
1
>>> selecttab ('dlggeditPreferences', 'ptl0', 'Editor')
1
チェック・メニュー・アイテムに働きかけるには、ウィンドウ名「Unsaved Document 1 - gedit」、メニュー名「View」、チェック・メニュー・アイテム名「Side Pane」といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> selectmenuitem ('*-gedit', 'mnuView;mnuSidePane')
1
>>> menuuncheck ('*-gedit', 'mnuView;mnuSidePane')
1
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> menucheck ('*-gedit', 'mnuView;mnuStatusbar')
1
ラジオ・メニュー・アイテム部に働きかけるには、ウィンドウ名「Unsaved Document 1 - gedit」、メニュー名「Documents」、メニュー・アイテム名「Class1.cs」(Class1.cs を開いているものと仮定)といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> selectmenuitem ('*-gedit', 'mnuDocuments;mnuClass1.cs')
1
>>> menucheck ('*-gedit', 'mnuDocuments;mnuClass1.cs')
1
コンボ・ボックスから下に表示されるメニュー・アイテムを選ぶには、ウィンドウ名「Open Files...」(訳註:訳者の環境では「Open Files」)、コンボ・ボックス名「Character Coding」(訳註:訳者の環境では「Character Encoding」)、メニュー・アイテム名「Current Locale云々」(訳註:この場所は空白文字を省くと失敗する)といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> comboselect ('dlgOpenFiles...', 'cboCharacterCoding', 'Current Locale (UTF-8)')
1
コンボ・ボックス部の下に表示されるリスト・アイテムに働きかけるには、ウィンドウ名「Find」、コンボ・ボックス部の名前「Search for」、リスト・アイテム中の選択肢の名前あるいはリスト・アイテムの要素番号あるいは新しいアイテム名「OdbcMetaDataCllectionNames.cs」といった情報が必要である。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> settextvalue ('dlgFind', 'cboSearchfor', 'OdbcMetaDataCollectionNames.cs')
1
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> comboselect ('dlgFind', 'cboSearchfor', 'ObdcMetaDataCollectionNames.cs')
1
LDTP API の「launchapp」を用いて、試験対象のアプリケーションを起動することが出来る。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> launchapp ('gedit')
1
API「guiexist」を用いて、GUI(即ちウィンドウ)の有無を確認することができる。API には類似の関数「waittillguiexist」「waittillguinotexist」も用意されている。
「GUI timeout」は、制限時間の初期値であり、二つの関数「waittillguiexist」「waittillguinotexist」で用いられる。関数「guitimeout」を使うと、ウィンドウが現れるか消えるかするのを指定した秒数の間だけ待つことが出来る。制限時間の初期値は 30 秒である。
この制限時間の初期値は、以下の方法で変更することが出来る。
例 1
export GUI_TIMEOUT=30
例 2
waittillguiexist ('*-gedit', guiTimeOut=30)
waittillguinotexist ('dlgOpenFiles...', guiTimeOut=30)
例 3
guitimeout (30)
例 4
ldtp -g 30
「OBJ timeout」は、制限時間の初期値であり、ウィンドウの内部で用いられる。関数 objtimeout を使えば、ウィンドウ中の対象オブジェクトが現れるのを指定した秒数の間だけ待つことが出来る。制限時間の初期値は 5 秒である。
制限時間の初期値は、以下の方法で変更することが出来る。
例 1
export OBJ_TIMEOUT=5
例 2
objtimeout (5)
例 3
ldtp -o 5
操作しようとしているウィンドウのアクセシビリティ機能が有効でないこともあるし、表示を伴わないキー入力を生成しなければならないこともある(ALT、CTRL、ENTER、BACKSPACE、ESC、F1-F12、SHIFT、CAPSLOCK、TAB、PAGE UP、PAGE DOWN、HOME、END、RIGHT / LEFT / UP / DOWN ARROW KEYS、INS、DEL)。関数 generatekeyevent や関数 enterstring を用いて、利用者が打ち込んだかのようにキー・イベントを模造することができる。付記:表示しない文字は全て山型括弧で囲う。
例 1
<ctrl>lwww.google.co.in<enter>
例 2
<alt><f1>
例 3
<control>s
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> launchapp ('gedit')
1
>>> waittillguiexist ('*-gedit')
1
>>> enterstring ('<alt><tab>')
1
>>> enterstring ('*-gedit', 'txt0', '<caps>Testing enterstring API<enter>')
1
>>> generatekeyevent ('<alt><tab>')
1
b1c、b1d、b2c、b2d、b3c、b3d といった素のマウス・イベントを発生させるには、スクリーン座標の X と Y を決める必要がある。ここでの b はボタン、c は単クリック、d はダブル・クリックである。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> generatemouseevent (100, 200) # 何も指定しなければ b1c
1
>>> generatemouseevent (100, 200, 'b1d') # ダブル・クリックを作り出す
1
getapplist を呼び出すと、アクセシビリティ機能を組み込んだアプリケーションの中、その時実行中であったものの名前を全て取得できる。ウィンドウの中、ローカル・キャッシュにアプリケーション・マップが存在するものの一覧を取得するには、getwindowlist を用いる。あるウィンドウに属するオブジェクトの一覧を取得するには、API「getobjectlist」を用いる。あるオブジェクトに属するプロパティの中、利用可能なものの一覧を取得するには、getobjectinfo を用いる。あるオブジェクトのあるプロパティを取得するには、getobjectproperty を用いる。
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> getapplist ()
[u'gnome-session', u'gnome-power-manager', u'gnome-settings-daemon', u'Libbonoboui-Gtk-Module-init-info', u'nautilus', u'GnomeApplicationBrowser', u'/usr/lib/zen-updater/ZenUpdater.exe', u'gaim', u'gtk-window-decorator', u'gedit', u'xchat', u'gnome-panel', u'gnome-volume-manager', u'resapplet', u'nm-applet', u'soffice.bin']
>>> getwindowlist ()
[u'frmUnsavedDocument1-gedit']
>>> getobjectlist ('*-gedit')
...
>>> getobjectinfo ('*-gedit', 'btnNew')
[u'child_index', u'class', u'description', u'parent', u'label']
>>> getobjectproperty ('*-gedit', 'btnNew', 'class')
'New'
何時表示されるのか予測がつかないウィンドウも、これを使えば簡単に処理できる。例えば、Evolution のパスワード・ダイアログ・ボックス、相手方による接続のリセットを告げるダイアログ、アプリケーションが壊れたことを告げるダイアログなど。
from ldtp import *
import threading
# スレッドの作成
callbackRunning = threading.Event ()
callbackRunning.clear ()
callbackState = threading.Event ()
callbackState.clear ()
# コールバックの定義
def cb ():
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> log ('test script', 'debug')
1
>>> log ('test script', 'warning')
1
>>> log ('test script', 'error')
1
>>> log ('test script', 'cause')
1
from ldtp import *
from ldtputils import *
try:
作業ディレクトリに下記のファイルを入れる。
python のスクリプトを実行する
$ python <script file name.py>
例
操作対象機にて LDTP エンジン(ldtp バイナリ)を起動する。二通りのやり方がある。(訳註:訳者の環境では「-s」「-p」ではなく「s」「p」である - ldtp-3.5.0)
選択肢 1
$ldtp -s
選択肢 2
$ldtp -p <起動するポート・番号> # 未設定なら 4118 となる。
コマンド・ラインから CobraWinLDTP.exe を実行する。
コマンド・ラインから ldtp を実行する。
クライアント側から LDTP エンジンと通信するには、二つのやり方がある。
選択肢 1
export LDTP_SERVER_ADDR=<ホスト名> もしくは <IP アドレス>
export LDTP_SERVER_PORT=<通信するポート番号、LDTP エンジン側で定めたもの>
python <スクリプト・ファイルの名前>.py もしくは ldtprunner test-runner.xml
選択肢 2
export LDTP_SERVER_ADDR=<ホスト名> もしくは <IP アドレス>
python <スクリプト・ファイルの名前>.py もしくは ldtprunner test-runner.xml # この場合、初期設定のポート番号を使う
LDTP のコマンドを実行した時に何が行われているのかを知りたい場合、下記の手順に従う。
片方の端末から
$ export LDTP_DEBUG=2 # bash shell の場合(Linux/Mac OS X)
C:¥> set LDTP_DEBUG=1 (Microsoft Windows の場合)
$ ldtp # (Linux/Mac OS X の場合) Windows では CobraWinLDTP.exe を実行
Client packet len: 82
i = 0
Data read 82, packet-len = 82, bytes read = 82, data: <?xml version="1.0"?
><REQUEST><ACTION>124</ACTION><ID>MainThread124</ID></REQUEST>
PACKET LENGTH: 0
Received packet [<?xml version="1.0"?
><REQUEST><ACTION><124</ACTION><ID>MainThread124</ID></REQUEST>] through 15
Node: ACTION
action name: 124
Node: ID
request_id: MainThread124
Command: 124
Accessible application name: Thunderbird
Accessible application name: gnome-panel
Accessible application name: xchat
Accessible application name: nm-applet
Accessible application name: nautilus
Accessible application name: gaim
Accessible application name: acroread
Accessible application name: soffice.bin
Accessible application name: gtk-window-decorator
Accessible application name: gedit
LIST: <?xml version="1.0" encoding="utf-8"?
><OBJECTLIST><OBJECT>nautilus</OBJECT><OBJECT>gaim</OBJECT><OBJECT>gtk-window-decorator</OBJECT><OBJECT>gedit</OBJECT><OBJECT>xchat</OBJECT><OBJECT>gnome-panel</OBJECT><OBJECT>Thunderbird</OBJECT><OBJECT>nm-applet</OBJECT><OBJECT>soffice.bin</OBJECT><OBJECT>acroread</OBJECT></OBJECTLIST>
resp_len = 117
Sending...
538
Response packet: <?xml version="1.0" encoding="utf-8"?
><RESPONSE><ID>MainThread124</ID><STATUS><CODE>0</CODE><MESSAGE>Successfully completed</MESSAGE></STATUS><DATA><LENGTH>325</LENGTH><VALUE><!
[CDATA[<?xml version="1.0" encoding="utf-8"?
><OBJECTLIST><OBJECT>nautilus</OBJECT><OBJECT>gaim</OBJECT><OBJECT>gtk-window-decorator</OBJECT><OBJECT>gedit</OBJECT><OBJECT>xchat</OBJECT><OBJECT>gnome-panel</OBJECT><OBJECT>Thunderbird</OBJECT><OBJECT>nm-applet</OBJECT><OBJECT>soffice.bin</OBJECT><OBJECT>acroread</OBJECT></OBJECTLIST>]]></VALUE></DATA><RESPONSE>
Msg:
Bytes sent: 542
もう片方の端末にて
$ export LDTP_DEBUG=2 # bash の場合
nags@nags:~> python
Python 2.5 (r25:51908, Nov 25 2006, 15:39:45)
[GCC 4.1.2 20061115 (prerelease) (SUSE Linux)] on Linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ldtp import *
>>> getapplist()
124 ( )
Send packet <?xml version="1.0"?
><REQUEST><ACTION>124</ACTION><ID>MainThread124</ID></REQUEST>
Received packet size 538
Received response Packet <?xml version="1.0" encoding="utf-8"?
><RESPONSE><ID>MainThread124</ID><STATUS><CODE>0</CODE><MESSAGE>Successfully completed</MESSAGE></STATUS><DATA><LENGTH>325</LENGTH><VALUE><!
[CDATA[<?xml version="1.0" encoding="utf-8"?
><OBJECTLIST><OBJECT>nautilus</OBJECT><OBJECT>gaim</OBJECT><OBJECT>gtk-window-decorator</OBJECT><OBJECT>gedit</OBJECT><OBJECT>xchat</OBJECT><OBJECT>gnome-panel</OBJECT><OBJECT>Thunderbird</OBJECT><OBJECT>nm-applet</OBJECT><OBJECT>soffice.bin</OBJECT><OBJECT>acroread</OBJECT></OBJECTLIST>]]></VALUE></DATA><RESPONSE>
[u'nautilus', u'gaim', u'gtk-window-decorator', u'gedit', u'xchat', u'gnome-panel', u'Thunderbird', u'nm-applet', u'soffice.bin', u'acroread']
>>>
http://en.wikipedia.org/wiki/Software_testing
http://safsdev.sf.net