I. 背景Webの誕生以来、UI自動化はテストにおける課題であり続けています。30年近くもの間、Web UIテストの問題を解決する効果的な方法は存在しませんでした。Webドライバーや画像比較ツールは数多く開発されてきましたが、これらのツールの投資収益率は常に疑問視されてきました。自動化率が高くなるほど、メンテナンスコストも高くなります。多くの人は自動化を諦めてしまう一方で、実施すべきかどうか迷っている人もいます。 この記事では、いくつかのオープンソース プロジェクトを組み合わせることで、GPT を使用して UI テストを自動化する可能性を探ります。 II. ソリューションの選択現在のUIの主な問題は、Webdriverを介してブラウザの実行を制御していることです。これらのツールはすべて、まず対応する要素を見つける必要があります。記録されたものであれ、独自に記述したものであれ、UIや要素が変更されるとDOMを再識別して解析するために多大な労力がかかります。この作業は面倒で非効率的です。もう一つの問題は、Sikuliなどの画像からクリック可能であることです。最大の問題は、再利用できないことです。解像度が変更されたり、画像がわずかに変更されたりすると、使用できなくなります。 GPT を使用した UI テストでは、次の 2 つのアプローチが試されました。 1つ目の方法は、HTML要素をGPTに入力する方法です。主なアプローチは、HTMLコードを取得し、HTMLに対して初期縮小処理を施した後、ベクトル化し、GPT4に入力してWebdriverスクリプトを自動生成することです。この方法は一般的に効果が低く、HTMLが比較的大きいため、トークン消費量が非常に高くなります。 2つ目のアプローチは、GPTを人間のように考え、テストさせることです。例えば、人がウェブページを開くとき、まず目でページ上のテキストやアイコンを確認し、次に手を使ってクリックや入力を行い、最後にポップアップやページ上のテキストを見てエラーがないか確認します。これらの動作は脳によって調整されています。 このセクションでは主に 2 番目のタイプについて説明します。 III. 新しいソリューションの実装1. 新計画の概要この新しいソリューションは、主にPlaywright、 SoMビジュアルマークアップ、GPT4Vision、GPT4、AutoGenを統合しています。主な原則は次のとおりです。 Playwright を使用してページ イメージの取得やさまざまなブラウザ操作などブラウザを操作することは、あたかも「手」を持つようなものです。 GPT4Visonは元のページ認識の精度が低いため、SoMによる視覚データラベリングが行われます。Microsoftの論文によると、視覚ラベリングはGPT4Vの認識を補助するために使用でき、これは「目」に相当します。 これらのステップをGPT4+AutoGenで繋ぐことで、「脳」と「神経中枢」に相当する協調制御を実現します。 2. メインアーキテクチャ 3. 実装手順1. Playwrightを使ってJSを挿入するbrowser = playwright.chromium.launch(channel="chrome",headless=False)context = browser.new_context()page = context.new_page()page.goto("http://oa.jd.com/")inject_js ="./pagemark.js"withopen(inject_js,'r')asfile:
コンテンツ = file.read()
page.evaluate(f"{content}")2. SoM視覚キュータグ前述の通り、GPT4VはWeb要素を効果的に認識できません。そのため、GPT4Vを使用する前に画像のタグ付けが必要です。現在、画像のタグ付けには2つの方法があります。1つはAIベースの画像認識によるもので、主に静的画像に使用されます。Webページのタグ付けでは、挿入されたJavaScriptを使用してページ要素を変更します。ここでは、pagemark.jsをブラウザに挿入し、Playwrightを使用してJavaScript関数を実行することでページのタグ付けを完了します。このJavaScriptは、標準的なCocoaアノテーションを実行できます。 // DOM ラベラーレット labels =[];functionunmarkPage(){
for(const ラベルのラベル){
document.body.removeChild(ラベル);
}
ラベル = [];
}
関数markPage(){
ページのマークを解除します();
var bodyRect = document.body.getBoundingClientRect();
var items =Array.prototype.slice.call(
ドキュメント.クエリセレクターAll('*')
).map(関数(要素){
var vw = Math.max(document.documentElement.clientWidth ||0, window.innerWidth ||0);
var vh = Math.max(document.documentElement.clientHeight ||0, window.innerHeight ||0);
var rects =[...element.getClientRects()].filter(bb=>{
var center_x = bb.left + bb.width / 2;
var center_y = bb.top + bb.height /2;
var elAtCenter = document.elementFromPoint(center_x, center_y);
elAtCenter === 要素 || element.contains(elAtCenter) を返します
}).map(bb=>{
定数 rect ={
左: Math.max(0, bb.left)、
上: Math.max(0, bb.top),
右: Math.min(vw, bb.right)、
下: Math.min(vh, bb.bottom)
};
戻る{
...直角、
幅: rect.right - rect.left,
高さ: rect.bottom - rect.top }
});
var area = rects.reduce((acc, rect)=> acc + rect.width * rect.height,0);
戻る{
要素: 要素、
含む:
(element.tagName ==="INPUT"|| element.tagName ==="TEXTAREA"|| element.tagName ==="SELECT")||
(element.tagName ==="BUTTON"|| element.tagName ==="A"||(element.onclick !=null)|| window.getComputedStyle(element).cursor ==="pointer")||
(element.tagName ==="IFRAME"|| element.tagName ==="VIDEO")
、
エリア
長方形、
テキスト: element.textContent.trim().replace(/\s{2,}/g,' ')
};
}).filter(item=>
アイテム.include &&(アイテム.area >=20)
);
// クリック可能な内側の項目のみ保持する
items = items.filter(x=>!items.some(y=> x.element.contains(y.element)&&!(x == y)))
// ランダムな色を生成する関数
関数 getRandomColor(){
var letters ='0123456789ABCDEF';
var color ='#';
for(var i =0; i <6; i++){
色 += 文字[Math.floor(Math.random()*16)];
}
色を返します。
}
// これらの要素の上に常に表示されるフローティング境界線を作成しましょう
items.forEach(function(item, index){
アイテム.rects.forEach((bbox)=>{
新しい要素 = document.createElement("div");
var borderColor =getRandomColor();
newElement.style.outline =`2px 破線 ${borderColor}`;
newElement.style.position="固定";
newElement.style.left = bbox.left +"px";
newElement.style.top = bbox.top +"px";
newElement.style.width = bbox.width +"px";
newElement.style.height = bbox.height +"px";
newElement.style.pointerEvents="なし";
newElement.style.boxSizing="ボーダーボックス";
newElement.style.zIndex = 2147483647;
// newElement.style.background = `${borderColor}80`;
// コーナーにフローティングラベルを追加する
var label = document.createElement("span");
ラベル.textContent = インデックス;
label.style.position="絶対";
ラベルスタイルトップ="-19px";
ラベル.スタイル.左 = 0px;
label.style.background = borderColor;
label.style.color = "白";
label.style.padding="2px 4px";
label.style.fontSize="12px";
label.style.borderRadius="2px";
新しい要素に子要素を追加します(ラベル)。
document.body.appendChild(新しい要素)。
ラベルをプッシュします(新しい要素)。
コンソール.log(インデックス)
});
})
}あるシステムを例にとると、注釈付け後の効果は次の図に示されます。 マークされた要素の位置番号をローカルの coco.json ファイルに保存します。 {
"1":{"x":"10","y":"40","w":"8","h":"10","center_x":"30","center_y":"13"},
"2":{"x":"20","y":"40","w":"16","h":"10","center_x":"30","center_y":"21"},
"10":{"x":"40","y":"80","w":"16","h":"10","center_x":"80","center_y":"21"}}ここで、center_x と center_y は要素の中心点の座標です。 3. GPT4Vの同定プロンプト Web ページのスクリーンショットをアップロードしました。ページ要素には COCO Annotator を使用して番号が付けられています。 この画像を分析し、ウェブページの目的とマークされた各要素の機能を特定してください。分析に基づいて、以下のタスクを完了するための計画的なパスを作成してください。 - 検索バーに ERP と入力します。 - リストが空かどうか確認する タスクを完了するための具体的な手順を説明するには、画像内の番号マーカーを使用してください。 GPT4V応答 この画像は、複数の数値マーカーが付いたウェブページのスクリーンショットです。これらのマーカーに基づいて、ウェブページの目的と各要素の機能を推測することができます。 要求されたタスクを完了するには、次の手順に従います。 1. 10と表示された検索ボックスにERP検索語を入力します。この検索ボックスのラベルは「検索ボックスにerpを入力」となっており、検索語を入力するためのものであることを示しています。 2. 17 とマークされた検索ボタンをクリックします。このボタンには「検索」というラベルが付いており、検索要求を送信するために使用されることを示しています。 3. リストが空かどうかを確認します。この手順では、19でマークされた「リストの内容」というラベルの付いた領域を確認する必要がある場合があります。この領域にコンテンツが表示されない場合、またはリストが空であることを示すメッセージが表示される場合は、検索結果が空です。 上記の手順は、画像内の数値マーカーと要素ラベルに基づいてタスクを完了するための具体的な操作について説明しています。 要素座標の抽出 正規表現を用いて、 GPT4Vレスポンスからクエリ対象要素の境界ボックスID(10、17、19)を抽出します。これをSoMタグに記録されたJSONファイルと組み合わせることで、要素番号10の座標を見つけます。"10":{"x":"40","y":"80","w":"16","h","10","center_x":"80","center_y":"21"} クラス GPT4VRecognize
def get_location(self, クエリ):
coco_json='./coco.json'
ファイルとしてwithopen(coco_json,'r')を実行します:
コンテンツ =file.read()
一致=re.findall(r'\d+',gpt4v_response_content)
数値=-1
iflen(一致)>0:
num = 一致[0]
データ = json.loads(json_str)
center_x = データ[num]["center_x"]
center_y = データ[数値]["center_y"]
center_x、center_yを返す4. 劇作家操作ページPlaywrightはブラウザを操作するための非常に強力なツールです。GPT4Vを使って画像を既に識別しているので、DOMを解析する必要はなく、主に座標を使って要素を制御します。これには、クリック、ダブルクリック、マウスのドラッグ、入力、スクリーンショットの撮影などのアクションが含まれます。 クラスアクション:
ページ=なし
__init__(自分自身、URL):
グローバルページ
ブラウザ = playwright.chromium.launch(channel="chrome",headless=False)
コンテキスト = browser.new_context()
ページ = context.new_page()
page.goto("http://oa.jd.com/")
定義 mouse_move(self,x,y):
page.mouse.move(自分,x,y)
defスクリーンショット(self):
page.screenshot()
定義 mouse_click(self,x,y):
page.mouse.click(自分,x,y)
def input_text(self,x,y,text):
page.mouse.click(自分,x,y)
page.keyboard.type(テキスト)
定義 mouse_db_click(self,x,y):
def select_option(self,x,y,option):
……5. オーケストレーションにAutoGenを使用するAutoGen は、複数の LLM をプロキシして異なるセッション間を切り替えたり、定義済みの関数を自動的に呼び出したり、これらの LLM を調整してタスクを完了したりできるプロキシ ツールです。 上記のプログラムは、次のことを実装しています: 目: GPT4V を介して要素を認識します。手: Playwright を介してさまざまな操作を実行します。その後、タスクを完了するために手と目を調整する脳が必要ですが、これは GPT4 + AutoGen によって実現されます。 config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")assistant= autogen.AssistantAgent(name="assistant",system_message=
「」
あなたは、UI ウィンドウに関連するタスクを完了する責任を負うオーケストレーターです。
提供されている機能を利用して、各アクションの後にスクリーンショットを撮ります。
与えられた機能のみを使用し、手元のタスクに集中することを忘れないでください。
「」、
llm_config={"config_list": config_list},)
user_proxy = autogen.UserProxyAgent(
名前="brain_proxy",
human_input_mode="しない",
code_execution_config={"work_dir":"coding"},
最大連続自動返信数=10、
llm_config={"config_list": config_list},)action = Actions(url)gpt4v=GPT4VRecognize()user_proxy.register_function(
関数マップ={
"get_location": gpt4v.get_location,
"mouse_move":アクション.mouse_move,
"スクリーンショット":action.screenshot,
"mouse_click":アクション.mouse_click,
"mouse_dbclick":アクション.mouse_dbclick,
"select_option":アクション.select_option
def run(message_ask):
user_proxy.initiate_chat(assistant,message=message_ask) __name__ == "__main__" の場合:
run("erp 'wwww30' と入力して検索結果を検索し、空のリストが返されるかどうかを確認します")IV. 問題とフォローアップ1. 現在の主な問題 この記事の主な目的は、人間の思考に完全に基づいたUIテスト手法を提案することで議論を活性化させることです。しかしながら、実験においては依然として多くの課題に対処する必要があります。 1. GPTは中国語のコンテキストではあまりユーザーフレンドリーではありません。実験中、中国語のプロンプトを誤解したため、特にページ上の中国語要素については継続的に最適化する必要があります。 2. AutoGen には定義済みのアクションの処理に関する問題もあり、継続的な最適化が必要です。 3. GPT4V は非常に高価です。 2. 将来のアイデア 1. リクエストごとの画像認識処理をGPT4Vにローカライズし、既存のテスト手法と組み合わせることでトークン数を削減し、実行時間を短縮します。 2. ビジネス指向のGPTには継続的なトレーニングが必要です。システムユーザーマニュアルと既存のPRDドキュメントをGPTに提供することで、GPTのシステム認識およびテスト能力が向上します。 V. 参考文献1. Set-of-Mark Prompting は GPT-4V で並外れた視覚的グラウンディングを実現します 2. Microsoft AutoGen 3. GPT-4V-ACT |