添付図面を参照し、本発明の実施形態について説明する。本明細書における実質的に全ての複数の及び/又は単数の用語の使用に関して、当業者は、文脈及び/又は用途に応じて、適宜、複数を単数に変換できる、且つ/又は単数を複数に変換できる。本明細書においては、わかり易さを目的として、様々な単数又は複数の順列(permutations)が明示的に記述されている場合がある。
図1は、本明細書に記述されている少なくとも1つの実施形態に従って構成された例示用のソフトウェアテストツール100を示している。ソフトウェアテストツール100は、テストドライバ102と、テストプロキシ104と、1つ又は複数のテストダブルプロキシ(test double proxies)106A〜106N(集合的に(collectively)、「テストダブルプロキシ106」)とを含んでもよい。ソフトウェアテストツール100は、テスト対象関数108をテスト又は検証するように構成されてもよい。
テスト対象関数108は、検証及び/又はその他のテストを受けるソースコード及び/又はソフトウェア製品に含まれた関数であってもよい。テスト対象関数108及び/又は対応するソースコード又はソフトウェア製品は、C++(登録商標)、C#(登録商標)、Java(登録商標)、又はその他のプログラミング言語を含む様々なプログラミング言語のうちのいずれかであってもよい。テスト対象関数108は、1つ又は複数の被呼出し関数110A〜110N(集合的に、「被呼出し関数110」)に対する関数呼出しを含んでもよい。
テストドライバ(test driver)102は、テスト入力パターンと呼ばれる1つ又は複数の入力の複数の組を生成するように、且つ、テスト入力パターンを使用することによってテスト対象関数108を実行するように、構成されてもよい。テスト対象関数108は、それぞれのテスト入力パターンごとに結果を出力してもよい。それぞれのテスト入力パターンごとに、テストドライバ102は、結果が予想結果と整合しているか否かをチェックするように構成されてもよい。結果が予想結果と整合している場合、テストドライバ102は、対応するテスト入力パターンによって実行された際にテスト対象関数108が合格したと判定してもよい。その一方で、結果が予想結果と整合していない場合、テストドライバ102は、対応するテスト入力パターンによって実行された際にテスト対象関数108が不合格となったと判定してもよい。これは、テスト対象関数108を含むソースコード又はソフトウェア製品におけるバグ又は誤りを示している。テスト対象関数108を含むソースコード又はソフトウェア製品の開発者等のユーザは、不合格について通知されてもよく、且つ、バグ又は誤りを訂正するための改善策(remedial measures)を施してもよい。
いくつかのソフトウェアテストツールは、テストプロキシを使用することなしに、ソースコード又はソフトウェア製品を検証する。このようなソフトウェアテストツールは、テスト入力パターンの全てに共通する初期化をそれぞれが含んでもよい複数のテスト入力パターンと、テスト入力パターンのうちの対応するテスト入力パターンに固有の1つ又は複数のテストパラメータと、関数呼出しとを生成してもよい。テスト入力パターンは、複数のテストケースを生成するために、1つ又は複数のアサーション(assertion)又は事前条件(precondition)をそれぞれのテストパターンに手動で追加しうる開発者又はその他のユーザによってレビューされてもよい。テスト入力パターンに対するアサーションの手動による追加は、面倒であるとともに時間を浪費する処理となろう。
図2Aは、本明細書に記述されている少なくとも1つの実施形態に従って構成された開発者又はその他のユーザによって手動で追加されたアサーションを含む例示用のテストケース200を示している。テストケース200は、初期化202と、1つ又は複数のテストパラメータ204と、関数呼出し206と、アサーション208とを含んでもよい。
初期化202は、foo及びbarという2つの引数を含むテスト対象関数fut()用の複数のテストケースのそれぞれに共通したものであってもよい。初期化202は、テストケースのそれぞれに共通したものであってもよい様々なグローバル変数の割当、メモリの割当、又はその他の初期化を含んでもよい。
テストパラメータ204は、図示のテストケース200に固有のものであってもよく、且つ、異なるテストケースにおいては、異なるテストパラメータが使用されてもよい。例えば、図2Aにおいては、テストパラメータ204は、xに対して、且つ、拡大すれば(by extension)、fooに対して、1の値を割り当てている。ここで、xは、fooが指し示しているオブジェクトのメンバであり、且つ、barに対して2の値を割り当てている。その他のテストケース200におけるテストパラメータは、foo及びbarに対して異なる値を割り当ててもよい。
関数呼出し206は、引数foo及びbarによってfut()を呼び出している。
初期化202、テストパラメータ204、及び関数呼出し206は、テスト入力パターンとしてテストドライバによって生成されてもよい。
例えば、意図するfut()の動作方式に関する知識等の製品仕様に関する知識を有する開発者又はその他のユーザが、テスト入力パターンをレビューしてもよく、且つ、テストケース200を生成するためにアサーション208を追加してもよい。例えば、開発者は、テストパラメータ204がfut()に提供された際に123という値を返すようにfut()が意図されていることを知っていてもよい。この知識は、開発者によって追加されるアサーション208において、反映されていてもよい。
動作の際に、且つ、テストケース200を使用することにより、fut()が呼び出されてもよく、且つ、fut()には、引数foo及びbar用のテストパラメータ204が提供されてもよい。次いで、fut(foo,bar)の出力をアサーション208に照らしてチェックし、fut()がテストパラメータ204に伴って合格しているか又は不合格であるかを判定してもよい。
上述のように、テストケース200等のテストケースを生成するための複数のテスト入力パターンに対するアサーションの手動による追加は、面倒であるとともに時間を浪費する処理となろう。図1のテストプロキシ104等の単一のテストプロキシが、手動で追加されたアサーションを有する複数のテストケースの代わり(substitute)として、実装されてもよい。図2Bは、本明細書に記述されている少なくとも1つの実施形態に従って構成された例示用のテストプロキシ210を示している。テストプロキシ210は、初期化212と、1つ又は複数のシンボリックテストパラメータ(symbolic test parameter)214と、関数呼出し216と、シンボリックアサーション(symbolic assertion)218とを含んでもよい。テストプロキシ210は、図1のテストプロキシ104の一例である。
例えば、fut()等の図2Aに関して記述されている同一のテスト対象関数の場合、図2Bのテストプロキシ210の初期化212及び関数呼出し216は、形態及び機能において、図2Aのテストケース200の初期化202及び関数呼出し206と同一であってもよい。
シンボリックテストパラメータ214は、シンボリック変数(symbolic variable)p1及びp2としてパラメータ化された図2Aのテストパラメータ204を含んでもよい。同様に、シンボリックアサーション218も、シンボリック変数p1及びp2の関数としてシンボリックにアサートされた図2Aのアサーション208を含んでもよい。
初期化212及びシンボリックテストパラメータ214は、fut()用のテストコンテキストを集合的に形成してもよい。
図1及び図2Bの組合せを参照することにより、テストドライバ102は、テストプロキシを伴わないテストのために生成されるテスト入力パターンとは異なる複数のテスト入力パターンを生成してもよい。具体的には、テストプロキシを伴わないソフトウェアテストツールによって使用されるテスト入力パターンは、図2Aの初期化202、テストパラメータ204、及び関数呼出し206等の初期化、テスト入力パターンに固有のテストパラメータ、及び関数呼出しを含んでもよい。対照的に、図1のテストプロキシ104又は図2Bのテストプロキシ210等のテストプロキシとともに使用されるテストドライバ102によって生成されるテスト入力パターンは、初期化及び関数呼出しを省略してもよい。その理由は、初期化及び関数呼出しは、テストプロキシにおいて、シンボリックテストパラメータとともに含まれてもよいからである。この代わりに、テストドライバ102によって生成されるテスト入力パターンは、テストプロキシにおいて、シンボリックテストパラメータのシンボリック変数の代わりに代用されうる様々な特定の値を含む異なるテストパラメータを含んでもよい。
図1のテストプロキシ104及び/又は図2Bのテストプロキシ210等のテストプロキシの生成に関する態様については、2013年3月14日付けで出願された米国特許出願第13/828,886号明細書に開示されており、この特許出願は、引用により、その全てが本明細書に包含される。
図1を再度参照すれば、上述のように、テスト対象関数108は、被呼出し関数110を呼び出してもよい。テストのためにテスト対象関数108を良好に隔離するべく、ソフトウェアテストツール100は、テストダブルプロキシ106を含んでもよい。テストダブルプロキシ106は、テストダブルプロキシ106が同一の入力を受け付ける、且つ/又は同一の出力を提供するように、被呼出し関数110と同一のインターフェイスを含んでもよい。さらに詳しくは、テストダブルプロキシ106Aは、被呼出し関数110Aと同一のインターフェイスを含んでもよく、テストダブルプロキシ106Bは、被呼出し関数110Bと同一のインターフェイスを含んでもよく、且つ、テストダブルプロキシ106Nは、被呼出し関数110Nと同一のインターフェイスを含んでもよい。しかしながら、テストダブルプロキシ106は、被呼出し関数110よりも単純であってもよい。一例として、被呼出し関数110Aは、1つ又は複数の入力を受け付けてもよく、入力を使用することによっていくつかの複雑な計算を実行してもよく、且つ、複雑な計算に基づいて1つ又は複数の出力を返してもよい。対照的に、テストダブルプロキシ106Aは、同一の入力を受け付けてもよく、且つ、なんらの計算をも実行することなしに特定の値を出力として返してもよく、或いは、出力を生成して返すべく、入力を使用することによって相対的に単純な計算を実行してもよい。
いくつかの実施形態においては、テストダブルプロキシ106は、被呼出し関数110用の単純なダミー関数として機能してもよい。この代わりに、又はこれに加えて、テストプロキシ104は、テスト対象関数108がテストダブルプロキシ106を呼び出すのか又は被呼出し関数110を呼び出すのかを特定するために、使用されてもよい。図1のテストダブルプロキシ106等のテストダブルプロキシの動作及び生成に関する更なる態様については、2014年1月31日付けで出願された「TEST DOUBLE GENERATION」という名称の同時係属中の米国特許出願第14/170,208号明細書に記述されており、この特許出願は、引用により、その全てが本明細書に包含される。
本明細書に記述されている実施形態は、図1のテストプロキシ104のテストコンテキスト及び/又は図2Bのテストプロキシ210のテストコンテキスト等のテストプロキシ用のテストコンテキストの生成に関する。図2Bの説明において既に言及したように、テストコンテキストは、図2Bの初期化212及びシンボリックテストパラメータ214等の初期化及び1つ又は複数のシンボリックテストパラメータを含んでもよい。
テストコンテキストは、手動で、半自動(semi−automatically)で、且つ/又は、自動で生成されてもよい。本明細書に記述されているいくつかの実施形態は、最小限の手動による介入を伴ってヒューマンフレンドリーなテストコンテキストを生成する。テストコンテキストは、テストパラメータの数及び/又はその内部に含まれている初期化対象の変数の数を極小化(minimizing)することにより、判読可能である等のように、ヒューマンフレンドリーであるとされてもよい。テストコンテキストの生成は、対応するソフトウェア製品又は特定のテスト対象関数において、ユーザが利用可能であるとともに黙示的(implicit)ではない全てのコンテキスト情報を除いて、可能な程度に自動化されてもよい。本明細書に記述されている実施形態は、最小限の初期テストコンテキストを自動的に生成してもよく、且つ、次いで、本明細書に記述されているように、初期化及びパラメータを追加することにより、テストコンテキストを反復的に増強してもよい。これらの及びその他の実施形態においては、テストコンテキストは、インターリーブされた方式により、自動的に且つ手動により、増強されてもよい。
図3は、本明細書に記述されている少なくとも1つの実施形態に従って構成されたテスト対象関数用のテストプロキシにおいて、1つ又は複数のテストコンテキスト302を生成するように構成された例示用のテストコンテキストジェネレータ300のブロックダイアグラムである。さらに詳しくは、テストコンテキストジェネレータ300は、テスト対象関数306を含むソースコード304に基づいて、且つ、ユーザ入力308に基づいて、テストコンテキスト302を生成するように構成されてもよい。
テスト対象関数306は、図1のテスト対象関数108に対応したものであってもよく、或いは、図1のテスト対象関数108を含んでもよい。
テストコンテキスト302は、初期テストコンテキスト302Aを少なくとも含んでもよい。テストコンテキスト302は、初期テストコンテキスト302A又は先行する増強されたテストコンテキスト302Bを増強することにより、順番に生成された1つ又は複数の増強されたテストコンテキスト302B−1〜302B−N(集合的に、「増強されたテストコンテキスト302B」)をさらに含んでもよい。例えば、第1の増強されたテストコンテキスト302B−1は、初期テストコンテキスト302Aを増強することにより、生成されてもよく、第2の増強されたテストコンテキスト(図示せず)は、直前の第1の増強されたテストコンテキスト302B−1を増強することにより、生成されてもよく、且つ、以下同様であり、最後の増強されたテストコンテキスト302B−Nは、直前の最後から2番目の増強されたテストコンテキスト(図示せず)を増強することにより、生成されてもよい。最後の増強されたテストコンテキスト302B−Nは、全ての増強されたテストコンテキスト302Bの中における最大の機能拡張を含んでもよく、且つ、図1のテストプロキシ104及び/又は図2Bのテストプロキシ210等のテストプロキシに含まれてもよい。この代わりに、又はこれに加えて、初期テストコンテキスト302A又は増強されたテストコンテキストのうちの別のもの302Bがテストプロキシに含まれてもよい。機能拡張は、自動的に生成されうるコンテキスト機能拡張及び/又はユーザ入力308に応答して生成される手動による機能拡張を含んでもよい。
テストコンテキストジェネレータ300は、テストコンテキストモジュール310、拡張シンボリック実行モジュール312、ユーザインターフェイスモジュール314、及び差分モジュール316(集合的に、「モジュール310、312、314、及び316」)を含んでもよい。テストコンテキストジェネレータ300及び/又はモジュール310、312、314、及び316のうちの1つ又は複数は、ハードウェア、ソフトウェア、又はこれらの組合せにおいて、実装されてもよい。例えば、テストコンテキストジェネレータ300及び/又はモジュール310、312、314、及び316のうちの1つ又は複数は、本明細書に記述されている機能及び動作を実行するように構成された1つ又は複数のASIC(Application−Specific Integrated Circuit)及び1つ又は複数のFPGA(Field−Programmable Gate Array)において、実装されてもよい。
この代わりに、又はこれに加えて、モジュール310、312、314、及び316を含むテストコンテキストジェネレータ300は、本明細書に記述されている機能及び動作を実行するためにプロセッサが実行可能であるコンピュータ命令を含んでもよい。コンピュータ命令は、非一時的なコンピュータ読み取り可能な媒体内に格納されてもよく、その例については、さらに詳細に後述する。本明細書に記述されている実施形態は、プロセッサと、プロセッサに通信可能に結合されたメモリ等の非一時的なコンピュータ読み取り可能な媒体とを含むコンピュータ等の装置を含んでもよい。非一時的なコンピュータ読み取り可能な媒体は、本明細書に記述されている機能及び動作を実行するためにプロセッサが実行可能であるテストコンテキストジェネレータ300及び/又はモジュール310、312、314、及び316のうちの1つ又は複数を格納して含んでもよい。次に、モジュール310、312、314、及び316について説明する。
テストコンテキストモジュール310は、テスト対象関数306の初期テストコンテキスト302Aを生成するように構成されてもよい。初期テストコンテキスト302Aは、テスト対象関数306の関数引数を初期テストコンテキストにおいて、一定値に等しくなるように設定することにより、生成されてもよい。例えば、関数引数のそれぞれは、0という一定値又はなんらかのその他の一定値に設定されてもよい。全ての関数引数は、同一の一定値に設定されてもよく、或いは、それぞれが、異なる一定値に設定されてもよく、或いは、いくつかが同一の一定値に設定される一方で、その他は、異なる一定値に設定されてもよい。
また、テストコンテキストモジュール310は、1つ又は複数のコンテキスト機能拡張(context enhancement)とともに現在のテストコンテキストを増強(enhance)するように、且つ、1つ又は複数のヒントを現在のテストコンテキストに追加するように、構成されてもよい。現在のテストコンテキストは、初期テストコンテキストを含むか又は初期テストコンテキストから導出されたテストコンテキストを含んでもよい。現在のテストコンテキストは、テストコンテキストジェネレータ300の動作の際の所与の時点において、現在存在しているテストコンテキストを含んでもよい。例えば、現在のテストコンテキストは、初期テストコンテキスト302Aの生成の後であるとともにその任意の機能拡張の前である時点における初期テストコンテキスト302Aを含んでもよい。初期テストコンテキスト302Aの機能拡張の後に、現在のテストコンテキストは、第1の増強されたテストコンテキスト302B−1を含んでもよい。増強されたテストコンテキスト302Bのうちの対応する増強されたテストコンテキスト302Bの機能拡張の後に、現在のテストコンテキストは、増強されたテストコンテキスト302Bのうちの対応する後続の増強されたテストコンテキスト302Bを含んでもよい。
コンテキスト機能拡張及びヒントは、拡張シンボリック実行モジュール312によって識別されてもよく、且つ、テストコンテキストモジュール310に提供されてもよい。拡張シンボリック実行モジュール312は、現在のテストコンテキストを使用することにより、テスト対象関数306の拡張シンボリック実行を実施し、コンテキスト機能拡張及びヒントを識別するように構成されてもよい。拡張シンボリック実行の態様については、後程、図4Cに関して、さらに詳述する。
ユーザインターフェイスモジュール314は、拡張シンボリック実行モジュール312によって識別されるとともにテストコンテキストモジュール310によって現在のテストコンテキストに追加されたヒントを含む現在のテストコンテキストを表示するように構成されてもよい。いくつかの実施形態においては、ユーザインターフェイスモジュール314は、テストコンテキストジェネレータ300を実行してもよいコンピュータのモニタ又はその他の表示装置上に、現在のテストコンテキストを表示させてもよい。ユーザインターフェイスモジュール314は、手動による機能拡張とともに現在のテストコンテキストを増強するために有効でありうるユーザ入力308を受信(receive)するように、さらに構成されてもよい。手動による機能拡張は、現在のテストコンテキストにおけるユーザによって特定された変数の指定を含んでもよい。
差分モジュール316は、現在のテストコンテキストにおいて、ユーザによって特定された変数を識別するように構成されてもよい。ユーザによって特定された変数は、直前のテストコンテキストと現在のテストコンテキストの間におけるテキストの差分を判定するために、現在のテストコンテキストと直前のテストコンテキストの間におけるテキスト比較によって識別されてもよい。拡張シンボリック実行モジュール312は、現在のテストコンテキストに対する後続の自動的な機能拡張によってユーザによって特定された変数が上書きされないように、ユーザによって特定された変数を優先するように構成されてもよい。
図4Aは、本明細書に記述されている少なくとも1つの実施形態に従って構成されたテスト対象関数用のテストプロキシにおいて、ヒューマンフレンドリーなテストコンテキストを生成するための例示用の方法400Aのフローチャートである。方法400Aは、いくつかの実施形態において、図3のテストコンテキストジェネレータ300を実行するコンピュータ等のコンピュータ又はその他の装置によって実装されてもよい。別個のブロックとして示されているが、様々なブロックは、望ましい実装形態に応じて、更なるブロックに分割されてもよく、さらに少ない数のブロックに組み合わせられてもよく、或いは、省略されてもよい。
方法400Aは、テスト対象関数の初期テストコンテキストを生成するブロック402において、開始される。テスト対象関数の初期テストコンテキストの生成は、テスト対象関数の1つ又は複数の関数引数を初期テストコンテキストにおいて、一定値と等しくなるように設定することを含んでもよい。
ブロック404において、現在のテストコンテキストが新しいコンテキスト機能拡張とともに増強されてもよい。現在のテストコンテキストは、初期テストコンテキストを含んでもよく、或いは、初期テストコンテキストから導出されてもよい。ブロック406において、ヒントが現在のテストコンテキストに追加されてもよい。
当業者であれば、本明細書に記述されているこの及びその他の処理及び方法においては、処理及び方法において実行される機能は、異なる順序において実装されてもよいことを理解するであろう。さらには、概説されているステップ及び動作は、例として提供されたものに過ぎず、且つ、ステップ及び動作のうちのいくつかは、開示されている実施形態の本質を逸脱することなしに、任意選択であってもよく、さらに少ない数のステップ又は動作に組み合わせられてもよく、或いは、更なるステップ及び動作に拡張されてもよい。
例えば、方法400Aは、図4B及び/又は図4Cに関して、さらに詳細に記述される更なるステップ又は動作を含んでもよい。
図4Bは、本明細書に記述されている少なくとも1つの実施形態に従って構成されたテスト対象関数用のテストプロキシにおいて、ヒューマンフレンドリーなテストコンテキストを生成するための別の例示用の方法400Bのフローチャートである。方法400Bは、いくつかの実施形態において、図3のテストコンテキストジェネレータ300を実行するコンピュータ等のコンピュータ又はその他の装置によって実装されてもよい。別個のブロックとして示されているが、様々なブロックは、望ましい実装形態に応じて、更なるブロックに分割されてもよく、さらに少ない数のブロックに組み合わせられてもよく、或いは、省略されてもよい。
方法400Bは、図4Aの方法400Aと重複(overlap)してもよい。例えば、図4Bの方法400Bは、図4Aのブロック402、404、及び406のみならず、様々なその他のブロックをも含む。次に、方法400Bについて説明する。
テスト対象関数の初期テストコンテキストを生成した後に(ブロック402)、方法400Bは、ブロック408において、現在のテストコンテキストを使用することにより、テスト対象関数の拡張シンボリック実行を実施し、1つ又は複数の新しいコンテキスト機能拡張及び1つ又は複数のヒントを識別することをさらに含んでもよい。
ブロック410において、方法400Bは、なんらかの新しいコンテキスト機能拡張が識別されたか否かを判定してもよい。少なくとも1つの新しいコンテキスト機能拡張が拡張シンボリック実行によって識別されている場合(ブロック410における「Yes」)、方法400Bは、プロック404に進んでもよい。ここで、現在のテストコンテキストが、新しいコンテキスト機能拡張とともに増強される。ブロック404に続いて、方法400Bは、ブロック408に戻ってもよい。ここで、拡張シンボリック実行の先行する反復(iteration)(例えば、直前の反復)において、識別された新しいコンテキスト機能拡張を含む現在のテストコンテキストを使用することにより、再度、テスト対象関数の拡張シンボリック実行が実行される。
少なくとも1つの新しいコンテキスト機能拡張が拡張シンボリック実行において識別されていない場合(ブロック410における「No」)、方法400Bは、ブロック406に進んでもよい。ここで、拡張シンボリック実行によって識別されたヒントが、現在のテストコンテキストに追加されてもよい。ヒントは、例えば、現在のテストコンテキストにおいて変数をシンボリックにすることにより、ユーザが現在のテストコンテキストを修正するための示唆(suggestion)を含んでもよい。
ブロック412において、方法400Bは、ユーザが、ヒントに応答して手動による機能拡張とともに現在のテストコンテキストを増強することを所望しているか否かを判定してもよい。ユーザは、テスト対象関数の又はテスト対象関数を含むソースコード又はソフトウェア製品の開発者を含んでもよい。ユーザが、現在のテストコンテキストを増強することを所望していない場合(ブロック412における「No」)、方法400Bは、ブロック414において終了してもよく、且つ、現在のテストコンテキストは、テスト対象関数をテストするために、対応するテストプロキシに含まれてもよい。
ユーザが、ヒントに応答して現在のテストコンテキストを増強することを所望している場合(ブロック412における「Yes」)、ブロック416において、ユーザは、ヒントに基づいて現在のテストコンテキストを増強するための入力を提供してもよい。例えば、ユーザは、ヒントに含まれている示唆を実装するための入力を提供してもよい。方法400Bにおいて、ブロック412及び416は、ユーザによって手動で実行されてもよく、その他のブロックは、例えば、コンピュータにより、自動的に実行されてもよい。
ブロック418において、現在のテストコンテキストを増強するために有効であるユーザ入力が受信されてもよい。ユーザ入力は、シンボリックなものとして、又は一定値を有するものとして、現在のテストコンテキストにおけるユーザによって特定された変数の指定を含んでもよい。
ブロック420において、ユーザによって特定された変数が、現在のテストコンテキストにおいて識別されてもよい。現在のテストコンテキストにおけるユーザによって特定された変数の識別は、ユーザによって特定された変数の指定の前に存在している直前の先行するテストコンテキストと、ユーザによって特定された変数の指定の後に存在している現在のテストコンテキストとの間におけるテキストの差分を判定することを含んでもよい。
図4Bには示されていないが、方法400Bは、現在のテストコンテキストに対する後続の自動的な機能拡張によって、ユーザによって特定された変数が上書きされないように、ユーザによって特定された変数を優先することをさらに含んでもよい。例えば、ユーザによって特定された変数は、さもなければ、現在のテストコンテキストにおいて修正されうる新しいコンテキスト機能拡張として識別されることを回避するために、タグ付け(tagged)されてもよく、或いは、メモリ内に記録されてもよく、或いは、さもなければ、優先されてもよい。
図4Cは、本明細書に記述されている少なくとも1つの実施形態に従って構成された現在のテストコンテキストを使用することにより、テスト対象関数の拡張シンボリック実行を実施するための例示用の方法408Aのフローチャートである。方法408Aは、図4Bのブロック408の例示用の実施形態に対応したものであってもよく、或いは、図4Bのブロック408の例示用の実施形態を含んでもよい。方法408Aは、いくつかの実施形態においては、図3のテストコンテキストジェネレータ400を実行するコンピュータ等のコンピュータ又はその他の装置によって実装されてもよい。別個のブロックとして示されているが、様々なブロックは、望ましい実装形態に応じて、更なるブロックに分割されてもよく、さらに少ない数のブロックに組み合わせられてもよく、或いは、省略されてもよい。
方法408Aは、ブロック422において始まってもよく、このブロックにおいて、テスト対象関数は、テスト対象関数の分岐(branch)又は終わり(end)に到達するまで、シンボリックに実行されてもよい。いくつかの実施形態によるシンボリックな実行の態様については、2012年8月16日付けで出願された米国特許出願第13/587,423号明細書に開示されており、この特許出願は、引用により、本明細書に包含される。
ブロック424において、実体変数(concrete variable)の依存関係(dependence)がトレース(traced)されてもよい。依存関係は、終わり又は分岐に到達するまでシンボリックに実行されるテスト対象関数の一部分に含まれている実体変数についてトレースされてもよい。依存関係は、さらに後述するように、方法408Aにおける後続の使用のために、少なくとも一時的に格納されてもよい。
ブロック426において、終わり又は分岐に到達するまでシンボリックに実行されたテスト対象関数の一部分の制約(constraints)が解決(solved)されてもよい。
ブロック428において、方法408Aは、テスト対象関数が、分岐又は終わりに到達するまで実行されたか否かを判定してもよい。分岐に到達している場合(ブロック428における「分岐」)、方法428は、ブロック430に進んでもよい。終わりに到達している場合(ブロック428の「終わり」)、方法428は、ブロック438に進んでもよい。
ブロック430において、方法408Aは、分岐が実行可能であるか否かを判定してもよい。分岐が実行可能である場合(ブロック430における「Yes」)、方法408Aは、ブロック422に戻ってもよい。ここで、テスト対象関数と、さらに具体的には、ブロック430において実行可能であると判定された分岐が、テスト対象関数の分岐(例えば、別の分岐)又は終わりに到達するまで、シンボリックに実行されてもよい。分岐が実行可能ではない場合(ブロック430における「No」)、方法408Aは、ブロック432に進んでもよい。
分岐が実行可能であるか否かのブロック430における判定は、制約及び現在のテストコンテキストに基づいたものであってもよい。例えば、現在のテストコンテキストは、ブロック426において、制約が解決される実体変数の値を特定してもよい。さらには、ブロック426における分岐に到達するまでシンボリックに実行されるテスト対象関数の一部分の制約の解決は、分岐の経路条件(path condition)を満たす実体変数の1つ又は複数の値を識別することを含んでもよい。これらの及びその他の実施形態においては、分岐は、経路条件を満たす実体変数の1つ又は複数の値が現在のテストコンテキストにおいて特定された実体変数の値に等しくないと判定された場合、或いは、さらに一般的には、経路条件を満たす実体変数の1つ又は複数の値が現在のテストコンテキストと矛盾(inconsistent)している場合、制約及び現在のテストコンテキストに基づいて実行可能ではないと判定されてもよい。その一方で、分岐は、経路条件を満たす実体変数の1つ又は複数の値が現在のテストコンテキストにおいて特定された実体変数の値と等しいか又は一貫性を有する(consistent with)と判定された場合、制約及び現在のテストコンテキストに基づいて実行可能であると判定されてもよい。
ブロック432において、分岐が実行可能ではないことを判定することに応答して(例えば、ブロック430における「No」)、方法408Aは、従属実体変数(dependent concrete variable)をシンボリック変数としてマーキングする(marking)ことを含んでもよい。この代わりに、又はこれに加えて、方法408Aは、ブロック432の前に、実体変数が従属しているか又は従属していないかを判定することを含んでもよい。実体変数は、分岐を実行する能力が実体変数に従属している場合、従属しているとみなされてもよい。
ブロック434において、例えば、現在のテストコンテキストにおけるユーザによって特定された変数である等のように、ユーザによって特定されたシンボリック変数としてマーキングされた実体変数は、もはやシンボリック変数としてマーキングされていない状態となるように、マーキング解除(unmarked)されてもよい。図4Bの説明に記述されているように、ユーザによって特定された変数は、例えば、ユーザによって特定された変数をタグ付けするか又はメモリ内に記録するか、或いは、さもなければ、ユーザによって特定された変数を優先することにより、優先順位付けされてもよい。したがって、図4Cには示されていないが、方法408Aは、ブロック434において、ユーザによって特定された変数を含むマーキングされた実体変数をマーキング解除することの前に、ブロック432において、シンボリック変数としてマーキングされた実体変数が、ユーザによって特定された変数を含んでいるか否かを判定することを含んでもよい。
ブロック436において、方法は、このようにブロック432においてマーキングされたシンボリック変数のうちのいくつか又は全てのシンボリック変数の1つ又は複数の事前条件を判定することを含んでもよい。ブロック436におけるシンボリック変数の1つ又は複数の事前条件の判定は、シンボリック変数の条件が交わる(intersect)ことを含んでもよい。事前条件は、テスト対象関数において黙示的である際には、自動的に判定されてもよい。例えば、テスト対象関数が、変数iによってインデックス付け(indexed)されたサイズ2の配列(array)a[]を入力として受け付け、且つ、変数iが、5つの要素の配列にアクセスするためのインデックスとしても使用されうる場合、変数iの条件は、0<=i<=1及び0<=i<=4を含んでもよい。0<=i<=1と0<=i<=4の交わり(intersection)は、0<=i<=1である。これは、この例においては、ブロック436において判定されてもよい。ブロック436から、方法408Aは、ブロック422、424、426、及び428に戻ってもよい。
ブロック428において、且つ、上述のように、方法408Aは、テスト対象関数が、分岐又は終わりに到達するまで実行されたか否かを判定してもよい。方法408Aは、テスト対象関数の全ての分岐が実行されている場合、ブロック428において、テスト対象関数が、終わりに到達するまで実行されたと判定してもよい。この代わりに、方法408Aは、シンボリック変数としてマーキングされた実体変数(例えば、ブロック434においてマーキング解除されていないブロック432においてマーキングされた変数)がテスト対象関数に対してアクセス可能ではない場合、ブロック428において、テスト対象関数が、終わりに到達するまで実行されたと判定してもよい。一般には、変数の、且つ、具体的には、シンボリック変数としてマーキングされた実体変数の、アクセス可能性は、変数のアクセス可能性を設定する任意のアクセス修飾子(access modifier)に基づいて、或いは、明示的な(explicit)アクセス修飾子が存在していない状態においては、プログラミング言語の対応する既定(default)のアクセス可能性に基づいて、判定されてもよい。
C++プログラミング言語におけるアクセス修飾子の例は、最も制限的なものから最も制限の少ないものに至る順序において、「private」、「protected」、及び「public」を含み、且つ、明示的なアクセス修飾子が存在しない場合における既定のアクセス可能性は、「private」アクセス修飾子と同一であってもよい。「private」に対応しているアクセス可能性(明示的なアクセス修飾子によって設定されているのか又は既定として設定されているのかを問わず)は、アクセスを同一クラス内に制限している場合がある。C#及びJava(登録商標)プログラミング言語は、両方とも、C++におけると同一のアクセス可能性を有する「private」アクセス修飾子を含む。したがって、シンボリック変数(例えば、ブロック432においてシンボリック変数としてマーキングされ、且つ、ブロック434においてマーキング解除されていない実体変数)が、これらの言語のうちのいずれかにおける「private」のアクセス可能性を有し、且つ、テスト対象関数がシンボリック変数とは異なるクラスに含まれている場合、シンボリック変数は、テスト対象関数に対してアクセス可能ではないと判定されてもよい。この代わりに、又はこれに加えて、C++、C#、Java(登録商標)、及び/又はその他のプログラミング言語におけるその他のアクセス修飾子及び/又は既定の設定は、シンボリック変数がテスト対象関数に対してアクセス可能ではないことを示している場合もある。
ブロック438において、且つ、シンボリック変数がテスト対象関数に対してアクセス可能であることを判定することに応答して、アクセス可能なシンボリック変数及び/又はその事前条件は、コンテキスト機能拡張として識別されてもよい。次いで、図4A〜図4Cの組合せを参照すれば、現在のテストコンテキストは、方法400A及び400Bのブロック404において識別されたコンテキスト機能拡張とともに増強されてもよい。識別されたコンテキスト機能拡張とともに現在のテストコンテキストを増強することは、現在のテストコンテキストにおいて、対応する実体変数をシンボリックとすることを含んでもよい。この代わりに、又はこれに加えて、識別されたコンテキスト機能拡張とともに現在のテストコンテキストを増強することは、対応するシンボリック変数(例えば、現在のテストコンテキストにおいて、シンボリックとされた実体変数)の1つ又は複数の事前条件を現在のテストコンテキストに追加することを含んでもよい。
図4Cを再度参照すれば、ブロック440において、且つ、シンボリック変数としてマーキングされた実体変数がテスト対象関数に対してアクセス可能ではないことを判定することに応答して、シンボリック変数としてマーキングされたアクセス可能ではない実体変数は、ヒントとして識別されてもよい。次いで、図4A〜図4Cの組合せを参照すれば、現在のテストコンテキストは、方法400A及び400Bのブロック406において、追加されたヒントを有してもよい。現在のテストコンテキストに対するヒントの追加は、ユーザが現在のテストコンテキストにおいて、シンボリック変数としてマーキングされた対応する実体変数をシンボリックとするための示唆を、現在のテストコンテキストに追加することにより、ヒントを現在のテストコンテキストに追加することを含んでもよい。
図4Cを再度参照すれば、ブロック442において、方法408Aは、終了してもよい。ブロック442における方法408Aの終了は、図4Bの方法400Bのブロック410に戻るという結果をもたらしてもよい。したがって、本明細書に記述されているいくつかの実施形態は、図4Bのブロック402におけると同様にテスト対象関数用の初期テストコンテキストを生成することと、ヒントに対応するコンテキスト機能拡張及び/又は手動による機能拡張とともに現在のテストコンテキストを反復的に増強することとを含む。コンテキスト機能拡張及び/又はヒントは、現在のテストコンテキストを使用することによってテスト対象関数の拡張シンボリック実行を実施することにより、識別される。
図5A〜図5Eは、本明細書に記述されている少なくとも1つの実施形態に従って構成されたテスト対象関数Foo()及び関係するテストコンテキスト502A〜502E(集合的に、「テストコンテキスト502」)を含む例示用のソースコード500を示している。テストコンテキスト502は、図4A〜図4Cの方法400A、400B、及び/又は408Aに従って生成されてもよい。
図5A〜図5Eに示されているように、関数Foo()は、サイズ2の配列a[]及び配列a[]をインデックス付けする整数iを含む関数引数を受け付けている。関数Foo()は、Exampleというクラスに属しており、且つ、ソースコード500は、クラスExampleの外部であるとともに「private」というアクセス可能性を有する整数memberをさらに定義している。関数Foo()は、様々な「if」ステートメント(statements)に対応する様々な分岐を含む。
次に、図4B及び図4Cをさらに参照し、図5A〜図5Eのそれぞれについて説明する。図5Aのテストコンテキスト502Aは、それぞれ、関数引数a[0]、a[1]、及びiをテストコンテキスト502Aにおいて、0という一定値に等しくなるように設定することによってブロック402において、生成されうる初期テストコンテキストを含んでもよい。したがって、関数引数a[0]、a[1]、及びiは、テストコンテキスト502Aにおいて実体変数であってもよい。
図4Bのブロック408において、拡張シンボリック実行を関数Foo()上で実施し、コンテキスト機能拡張及び/又はヒントを識別してもよい。さらに詳しくは、関数Foo()は、if(a[i]!=1)というifステートメントを含むソースコード500の行504における関数Foo()の第1分岐に到達するまで、ブロック422において、テストコンテキスト502Aを使用することによってシンボリックに実行されてもよい。ソースコード500の行504における第1分岐は、第1分岐の経路条件が満たされた際に、且つ、さらに具体的は、a[i]!=1が真(true)として判断された際に、選択(followed)されてもよい。第1分岐は、ソースコード500の行506において、return 1というステートメントをさらに含んでもよい。
ブロック424において、実体変数a[0]、a[i]、及びiの依存関係がトレースされる。ブロック426において、実体変数a[0]、a[i]、及びiの制約が第1分岐について解決される。例えば、ブロック426は、a[0]及びa[1]の値として1を除く任意の整数を、且つ、第1分岐の経路条件(例えば、a[i]!=1)を満たすiの値として整数0及び1を、識別することを含んでもよい。
ブロック428において、(関数Foo()の終わりではなく)第1分岐に到達したことが判定されてもよい。
ブロック430において、第1分岐が、制約及び現在のテストコンテキストに基づいて実行可能であるか否かが判定されてもよい。例えば、制約が、現在のテストコンテキストによって許容されているか、含まれているか、或いは、さもなければ、現在のテストコンテキストと一貫性を有するか否かが判定されてもよい。第1分岐の制約は、a[0]=1を除く任意の整数と、a[1]=1を除く任意の整数とを含み、且つ、図5Aのテストコンテキスト502Aは、a[0]=0とa[1]=0とを含むことから、第1分岐が実行可能であると判定されてもよく、且つ、方法408Aは、ブロック422に戻ってもよい。
ブロック422の現在の反復において、関数Foo()は、こちらもif(a[i]!=1)というifステートメントを含むソースコード500の行504における関数Foo()の第2分岐に到達するまで、テストコンテキスト502Aを使用することよってシンボリックに実行されてもよい。行504における第2分岐は、第2分岐の経路条件が満たされた際に、且つ、さらに詳しくは、a[i]!=1が偽(false)として判断された際に、選択されてもよい。第2分岐は、ソースコード500の行508において、if(member!=3)というステートメントをさらに含んでもよい。
ブロック424の現在の反復において、実体変数a[0]、a[i]、及びiの依存関係がトレースされる(或いは、予めトレースされた依存関係が再使用されてもよい)。ブロック426の現在の反復において、実体変数a[0]、a[i]、及びiの制約が、第2分岐について解決される。例えば、ブロック426は、整数1をa[0]及びa[1]の値として、且つ、整数0及び1を第2分岐の経路条件(例えば、a[i]!=1が偽である)を満たすiの値として識別することを含んでもよい。
ブロック428の現在の反復において、(関数Foo()の終わりではなく)第2分岐に到達したと判定されてもよい。
ブロック430の現在の反復においては、第2分岐が、制約及び現在のテストコンテキストに基づいて実行可能であるか否かが判定されてもよい。第2分岐の制約は、a[0]=1及びa[1]=1を含んでおり、これらの値は、図5Aのテストコンテキスト502Aにおけるステートメントa[0]=0及びa[1]=0と矛盾していることから、第2分岐は、実行可能ではないと判定されてもよく、且つ、方法408Aは、ブロック432に進んでもよい。
ブロック432において、第2分岐が実行可能ではないことを判定することに応答して、且つ、実体変数a[0]、a[1]、及びiが従属実体変数であることを判定することに応答して、実体変数a[0]、a[1]及びiは、シンボリック変数としてマーキングされてもよい。実体変数a[0]、a[1]及びiは、ブロック424においてトレースした依存関係に基づいて、従属実体変数であると判定されてもよい。
シンボリック変数としてマーキングされた実体変数a[0]、a[1]、及びiが、ユーザによって特定された実体変数ではないことから、ブロック434はスキップ(skipped)されてもよい。
ブロック436において、シンボリック変数(例えば、シンボリック変数としてマーキングされた実体変数a[0]、a[1]、及びi)の事前条件が判定されてもよく、これには、シンボリック変数としてマーキングされた実体変数iが、0及び1を含む0〜1の範囲の整数であると判定することが含まれる。この時点から、方法408Aは、アクセス可能である場合、シンボリック変数としてマーキングされた実体変数a[0]、a[1]、及びi、並びに、それらの事前条件(例えば、0<=i<=1)が、新しいコンテキスト機能拡張としてブロック438において識別されるまで、少なくとも実行されてもよい。次いで、図5Aのテストコンテキスト502Aは、図4Bのブロック404において、図5Bのテストコンテキスト502Bに示されているように、実体変数a[0]、a[1]、及びiのそれぞれを現在のテストコンテキストにおいてシンボリックとすることにより、且つ、事前条件を現在のテストコンテキストに追加することにより、新しいコンテキスト機能拡張とともに増強されてもよい。
この代わりに、又はこれに加えて、ブロック436におけるシンボリック変数の事前条件の判定の後に、方法408Aは、ブロック422に戻ってもよい。
ブロック422の現在の反復において、関数Foo()は、if(member!=3)というifステートメントを含むソースコード500の行508における関数Foo()の第3分岐に到達するまで、テストコンテキスト502A(又は、502B)を使用することによって実行されてもよい。行508における第3分岐は、第3分岐の経路条件が満たされた際に、且つ、さらに具体的には、member!=3が真と判断された際に、選択されてもよい。第3分岐は、ソースコード500の行510において、return 2というステートメントをさらに含んでもよい。
ブロック424の現在の反復において、実体変数memberの依存関係がトレースされる。ブロック426の現在の反復において、実体変数memberの制約が、第3分岐について解決される。例えば、ブロック426は、第3分岐の経路条件(例えば、member!=3)を満たす実体変数memberの値として、3を除く任意の整数を識別することを含んでもよい。
ブロック428の現在の反復において、(関数Foo()の終わりではなく)第3分岐に到達したと判定されてもよい。
ブロック430の現在の反復において、第3分岐が、制約及び現在のテストコンテキストに基づいて実行可能であると判定されてもよい。第3分岐の制約は、実体変数memberについて3を除く任意の整数を含んでおり、且つ、テストコンテキスト502A(又は、502B)は、実体変数memberに関して情報を提供しない(silent)ことから、第3分岐が実行可能ではないと判定されてもよく、且つ、方法408Aは、ブロック432に進んでもよい。
ブロック432の現在の反復において、第3分岐が実行可能ではないことを判定することに応答して、且つ、実体変数memberが従属実体変数であることを判定することに応答して、実体変数memberが、シンボリック変数としてマーキングされてもよい。
シンボリック変数としてマーキングされた実体変数memberは、ユーザによって特定された実体変数ではなく、且つ、なんらの事前条件をも有していないことから、ブロック434及び436は、スキップされてもよく、且つ、方法408Aは、ブロック422、424、426、及び428に戻ってもよい。
ブロック428の現在の反復において、シンボリック変数としてマーキングされた実体変数memberが、関数Foo()を含むクラスExampleの外部の実体変数memberの「private」アクセス可能性の観点において、関数Foo()に対してアクセス可能ではないことから、ソースコード500の終わりに到達したと判定されてもよい。
アクセス可能である場合、ブロック438を上述のように実行し、シンボリック変数としてマーキングされた実体変数a[0]、a[1]、及びi及びそれらの事前条件を新しいコンテキスト機能拡張として識別してもよく、或いは、既に実行されている場合、ブロック438は、スキップされてもよい。
ブロック440において、シンボリック変数としてマーキングされた実体変数memberは、関数Foo()に対してアクセス可能ではないことから、ヒントとして識別されてもよい。次いで、ヒントは、図5Cのテストコンテキスト502Cの行512において示されているように、図4Bのブロック406において、シンボリック変数としてマーキングされた実体変数memberをユーザがシンボリックにするための示唆を追加することにより、図5Aのテストコンテキスト502A(又は、図5Bのテストコンテキスト502B)に追加されてもよい。
図5Bのブロック412において、ユーザは、行512におけるヒントに基づいて、図5Cのテストコンテキスト502Cを増強するか否かを判定してもよい。図4Bのブロック416において、ユーザは、ヒントに基づいて図5Cのテストコンテキスト502Cを増強するための入力を提供してもよい。ブロック418において、テストコンテキスト502Cを増強するために有効であるユーザ入力が、受信されてもよく、この結果、行514におけるユーザによって特定された変数を含む図5Dのテストコンテキスト502Dが得られる。具体的には、テストコンテキスト502Cは、テストコンテキスト502Cの行512におけるヒントを、整数mと実体変数memberとをシンボリックにするテストコンテキスト502Dの行514におけるステートメントによって置換することにより、増強されている。
図4Bのブロック420において、図5Dのテストコンテキスト502Dのユーザによって特定された変数は、例えば、図5Dのテストコンテキスト502Dと図5Cのテストコンテキスト502Cの間におけるテキストの差分を判定することにより、識別されてもよく、且つ、図4Bの方法400Bは、ブロック408に、或いは、さらに詳しくは、図4Cの方法408Aのブロック422に、戻ってもよい。
ブロック422の現在の反復において、関数Foo()は、こちらもif(member!=3)というifステートメントを含むソースコード500の行508における関数Foo()の第4分岐に到達するまで、図5Dのテストコンテキスト502Dを使用することによって実行されてもよい。行508における第4分岐は、第4分岐の経路条件が満たされた際に、且つ、さらに詳しくは、member!=3が偽であると判断された際に、選択されてもよい。第4分岐は、ソースコード500の行516におけるh=global+1というステートメントと、ソースコード500の行518におけるif(h!=2)というステートメントとをさらに含んでもよい。
テストコンテキスト502Dにおけるシンボリック変数としてのmemberにより、方法408Aは、ブロック424、426、428、及び430と進み、ブロック422に戻ってもよい。
ブロック422の現在の反復において、関数Foo()は、if(h!=2)というifステートメントを含むソースコード500の行518における関数Foo()の第5分岐に到達するまで、図5Dのテストコンテキスト502Dを使用することによってさらに実行されてもよい。行518における第5分岐は、第5分岐の経路条件が満たされた際に、且つ、さらに詳しくは、h!=2が真として判断された際に、選択されてもよい。
ブロック424の現在の反復において、実体変数hが、テストコンテキスト502Dにおいて特定されていない実体変数globalに従属していると判定するために、実体変数hの依存関係がトレースされる。実体変数h及びglobalの制約が、ブロック426において解決され、第5分岐に到達したとブロック428において判定され、且つ、第5分岐が、制約及びテストコンテキスト502Dに基づいて実行可能ではないとブロック430において判定される。実体変数globalは、第5分岐について従属していると判定され、且つ、実体変数globalは、ブロック432において、シンボリック変数としてマーキングされる。シンボリック変数としてマーキングされた実体変数globalが、ユーザによって特定されてはおらず、且つ、なんらの事前条件を含んでいないことから、ブロック434及び436は、スキップされてもよい。この時点から、方法408Aは、アクセス可能である場合、シンボリック変数としてマーキングされた実体変数globalが新しいコンテキスト機能拡張としてブロック438において識別されるまで、少なくとも実行されてもよい。図示の実施例は、これに該当している。次いで、図5Dのテストコンテキスト502Dは、図5Eのテストコンテキスト502Eに示されているように、図4Bのブロック404において、シンボリック変数としてマーキングされた実体変数globalをシンボリックにすることにより、新しいコンテキスト機能拡張とともに増強されてもよい。図4Bの方法400B及び/又は図4Cの方法408Aは、関数Foo()の残りの部分を通じて且つ/又はブロック414及び/又は442における終了のまで、継続してもよい。
図5A〜図5Eの例は、テストプロキシのテストコンテキストが、自動的に生成されるヒントに応答して実行される手動による機能拡張とインターリーブ(interleaved)された自動的なコンテキスト機能拡張の反復的処理を通じて生成されうる方式を示している。これにより、このようなテストコンテキストは、テストコンテキストが完全に又は主に手動的な方式によって生成される場合と比べて、迅速に且つ又は少ない努力によって生成される。
本明細書に記述されている実施形態は、後程詳述するように、様々なコンピュータハードウェア又はソフトウェアモジュールを含む特殊目的又は汎用のコンピュータの使用を含んでもよい。
本明細書に記述されている実施形態は、格納されたコンピュータ命令又はデータ構造を担持するか又は有するためのコンピュータ読み取り可能な媒体を使用することにより、実装されてもよい。このようなコンピュータ読み取り可能な媒体は、汎用又は特殊目的コンピュータによってアクセスされうる任意の入手可能な媒体であってもよい。一例として、且つ、限定を伴うことなしに、このようなコンピュータ読み取り可能な媒体は、RAM、ROM、EEPROM、CD−ROM、又はその他の光ディスクストレージ、磁気ディスクストレージ、又はその他の磁気ストレージ装置、或いは、コンピュータ命令又はデータ構造の形態において、望ましいプログラムコードを担持又は格納するために使用されうるとともに汎用又は特殊目的コンピュータによってアクセスされうる任意のその他のストレージ媒体を含む非一時的なコンピュータ読み取り可能なストレージ媒体を含んでもよい。また、上述の組合せは、コンピュータ読み取り可能な媒体の範囲に含まれてもよい。
コンピュータ命令は、例えば、汎用コンピュータ、特殊目的コンピュータ、又は特殊目的処理装置に特定の機能又は機能のグループを実行させる命令及びデータを含む。主題は、構造的な特徴及び/又は方法の動作に固有の言語において記述されているが、添付の請求項に定義されている主題は、必ずしも、上述の具体的な特徴又は動作に限定されるものではないことを理解されたい。むしろ、上述の具体的な特徴及び動作は、請求項を実装する例示用の形態として開示されたものである。
本明細書において使用されている「モジュール」又は「コンポーネント」という用語は、演算システム上において稼働するソフトウェアオブジェクト又はルーチンを意味してもよい。本明細書に記述されている様々なコンポーネント、モジュール、エンジン、及びサービスは、演算システム上において稼働するオブジェクト又は処理として(例えば、別個のスレッドとして)実装されてもよい。本明細書に開示されているシステム及び方法は、好ましくは、ソフトウェアとして実装されるが、ハードウェアにおける又はソフトウェアとハードウェアの組合せにおける実装も、可能であり、且つ、想定される。この説明においては、「演算エンティティ」は、以上において定義されている任意の演算システム又は演算システム上において稼働する任意のモジュール又はモジュールの組合せであってもよい。
本明細書に記述されている全ての例及び条件に関する言語は、本発明と、当技術分野の発展に寄与する本発明者による概念とを理解する際に読者を支援するための教育的な目的を意図したものであり、且つ、これらの具体的に記述されている例及び条件に対する限定を伴うものではないものと解釈されたい。本発明の実施形態について詳細に説明したが、本発明の精神及び範囲を逸脱することなしに、これらに対して様々な変化、置換、及び修正が実施可能であることを理解されたい。