Rational Functional Tester 中可重用的物件識別機制

myattitude發表於2009-05-26

引言

在開發自動化指令碼的過程中,經常會碰到由於頁面元素佈局發生微小改動、新增或者刪除控制元件,導致整套指令碼無法順利執行,同時指令碼的維護工作也由於指令碼需要重寫或者重新錄製而變得繁重。實際上這種問題出現的原因是我們把物件的識別限制在針對某一具體控制元件上,例如一個文字輸入框。本文將闡述利用 IBM automation framework 來實現在更大範圍內物件識別的機制,並利用這套機制解決上述問題。

我們將物件識別範圍擴大到表格 (table),在表格中動態查詢控制元件,那麼上述問題將得到緩解。如果表格也發生變動,我們只要將表格重新抓取,從而以微小的代價實現指令碼無需變動,依然能夠執行。

IBM automation framework 簡介

IBM GUI automation framework 由三部分組成,分別是三層體系結構 (appobjects,tasks 和 testcases)、ibm package 和最佳實踐。三層體系結構的目的是為了將“做什麼”和“怎麼做”分開,從而做到程式碼重用和介面一致的物件識別機制。appobjects 層是用來儲存 GUI 元素的地方,通過呼叫該層的 getter 方法返回 object,用來查詢和操作 GUI 元素;tasks 層是構建可重用公共方法的地方,也是用來儲存查詢和操縱與應用程式相關的複雜控制元件的地方;testcases 層呼叫 tasks 層存在的方法,模擬應用程式的使用,驗證狀態和結果。ibm package 是提取出來的跟應用程式無關的程式碼,包含開發自動化指令碼過程中需要用到的多種常用功能,供 IBM 所有測試 team 使用,能夠大量節省開發 automation 指令碼的工作量。


圖 1. 三層結構示意圖及定製化
三層結構示意圖及定製化

檢視大圖

定義介面

頁面上的常用控制元件包括文字輸入框、單選框、核取方塊、下拉框、連結和按鈕。我們針對不同控制元件型別,定義不同的 getter、setter 方法和一些判斷邊界值的介面。getter 方法是得到表格中的具體控制元件物件,setter 方法是對具體的控制元件設值。另外的一些介面則是一些類似於驗證當前文字框是否包含某些值的判斷操作,或者點選動作等。具體介面定義如下,以控制元件型別劃分,表格的形式呈現。由於以下介面是屬於公共方法,所有對 GUI 介面的操作都可以使用,故在 tasks 層對其進行定義和實現。而這些介面所要操作的表格,則應放在 appobjects 層,作為 GUI 元素存在。


表 1.1 文字輸入框 (text entry) 介面

目的 方法名 返回值 引數
向文字輸入框中填寫指定值 setTextEntryFromTable void StatelessGuiSubitemTestObject table –文字輸入框所在表格
String name –文字輸入框的 name 屬性值
String value –準備向文字輸入框中填寫的值
得到文字輸入框物件 getTextEntryFromTable TextGuiTestObject StatelessGuiSubitemTestObject table –文字輸入框所在表格
String name –文字輸入框的 name 屬性值
得到當前文字輸入框中已經填寫的值 getCurrentTextInTextEntryFromTable String StatelessGuiSubitemTestObject table –文字輸入框所在表格
String name –文字輸入框的 name 屬性值
當前文字輸入框中的值是否與預期值一致 isValidValueInTextEntryFromTable boolean StatelessGuiSubitemTestObject table –文字輸入框所在表格
String name –文字輸入框的 name 屬性值
String value –文字框中的預期值


表 1.2 單選框 (radio button) 介面
目的 方法名 返回值 引數
點選單選框 setRadioButtonFromTable void StatelessGuiSubitemTestObject table –單選框所在表格
String id –單選框的 id 屬性值
得到單選框物件 getRadioButtonFromTable ToggleGUITestObject StatelessGuiSubitemTestObject table –單選框所在表格
String id –單選框的 id 屬性值


表 1.3 下拉框 (drop down list) 介面
目的 方法名 返回值 引數
選擇下拉框中指定值的選項 setComboxFromTable void StatelessGuiSubitemTestObject table –下拉框所在表格
String name –下拉框的 name 屬性值
String value –擬選擇的下拉框值
選擇下拉框中第一個值 setComboxFromTableWithoutValue void StatelessGuiSubitemTestObject table –下拉框所在表格
String name –下拉框的 name 屬性值
得到下拉框物件 getComboxFromTable SelectGuiSubitemTestObject StatelessGuiSubitemTestObject table –下拉框所在表格
String name –下拉框的 name 屬性值
得到當前下拉框中選擇的值 getCurrentSelectionInComboxFromTable String StatelessGuiSubitemTestObject table –下拉框所在表格
String name –下拉框的 name 屬性值
當前下拉框中的值是否與預期值一致 isValidValueInComboxFromTable boolean StatelessGuiSubitemTestObject table –下拉框所在表格
String name –下拉框的 name 屬性值
String value –下拉框當前選項的期望值


表 1.4 連結 (link) 介面
目的 方法名 返回值 引數
點選連結 clickLinkInTable void StatelessGuiSubitemTestObject table –連結所在表格
String textAttribute –連結的 text 屬性值


表 1.5 按鈕 (button) 介面
目的 方法名 返回值 引數
點選圖片按鈕 clickButtonInTable void StatelessGuiSubitemTestObject table –圖片按鈕所在表格
String altAttribute –圖片按鈕的 alt 屬性
點選第 n 個具有相同 alt 屬性的按鈕 clickButtonInTable void StatelessGuiSubitemTestObject table –圖片按鈕所在表格
String altAttribute –圖片按鈕的 alt 屬性
int currentIndex –擬選擇的第 n 個按鈕
點選 submit 按鈕 clickSubmitButtonInTable void StatelessGuiSubitemTestObject table – submit 按鈕所在表格
String attribute –按鈕的 value 屬性值
int currentIndex –擬選擇第 n 個按鈕

介面實現

本部分以文字輸入框為例,具體給出如何實現上述介面。在實現中用到了 ibm package (ibm.jar),這個 package 最後釋出日期是 2007 年 7 月 10 日,IBM 宣告可以給客戶使用,但不再對該這個 jar 包的程式碼提供技術支援,包括處理功能增強和 defect 報告的請求。該包中含有在父物件中查詢子物件的方法。

package common.tasks;
import ibm.widgets.ObjectFactory;
// 向一個文字框中寫入指定的文字
//table –包含文字輸入框的表格
//name –文字輸入框的 .name 屬性值
//value - 擬填入到文字框中的值
public static void setTextEntryFromTable(
StatelessGuiSubitemTestObject table, String name, String value) {
String propertyName = ObjectFactory.gsHtmlTFProp;
String classID = ObjectFactory.gsHtmlTFClass;
try {
TextGuiTestObject textEntry =new TextGuiTestObject(
ObjectFactory.findTestObject(name, 
    propertyName, classID, table));
if(textEntry != null) {
textEntry.waitForExistence();
textEntry.setText(value);
textEntry.unregister();
}
textEntry = null;
} catch(Exception e) {
}
}

// 在表格中找到一個特定的文字輸入框
//table –包含文字輸入框的表格
//name –文字輸入框的 .name 屬性值
public static TextGuiTestObject getTextEntryFromTable(
StatelessGuiSubitemTestObject table, String name) {
String propertyName = ObjectFactory.gsHtmlTFProp;
String classID = ObjectFactory.gsHtmlTFClass;
try {
return new TextGuiTestObject(ObjectFactory.findTestObject(name, 
propertyName, classID, table));
} catch(Exception e) {
}
return null;
}

// 得到當前文字輸入框中當前的文字
//table –包含文字輸入框的表格
//name –文字輸入框的 .name 屬性值
public static String getCurrentTextInTextEntryFromTable (
StatelessGuiSubitemTestObject table, String name) {
String propertyName = ObjectFactory.gsHtmlTFProp;
String classID = ObjectFactory.gsHtmlTFClass;
String currentText = "";
try {
TextGuiTestObject textEntry =new TextGuiTestObject(
ObjectFactory.findTestObject(name, propertyName, classID, table));
if(textEntry != null) {
textEntry.waitForExistence();
currentText = textEntry.getText();
textEntry.unregister();
return currentText;
}
textEntry = null;
} catch(Exception e) {
}
return currentText;
}

// 判斷文字框中的當前值與指定的文字是否一致
//table –包含文字輸入框的表格
//name –文字輸入框的 .name 屬性值
//value - 擬填入到文字框中的值
public static boolean isValidValueInTextEntryFromTable(
StatelessGuiSubitemTestObject table, String name, String value) {
String propertyName = ObjectFactory.gsHtmlTFProp;
String classID = ObjectFactory.gsHtmlTFClass;
String currentText = "";
try {
TextGuiTestObject textEntry =new TextGuiTestObject(
ObjectFactory.findTestObject(name, propertyName, classID, table));
if(textEntry != null) {
textEntry.waitForExistence();
currentText = textEntry.getText();
textEntry.unregister();
if(currentText.equalsIgnoreCase(value)) {
return true;
} else {
return false;
}
}
textEntry = null;
} catch(Exception e) {
}
return false;
}

結果驗證

應用上述介面,當介面發生變化時,能做到指令碼改動最小,並且快速擴充套件指令碼功能。例如在一個 form. 表單中原本有“姓名”和“郵件”兩個輸入框,現在加入一個“地址”輸入框,位置在姓名和郵件之間。頁面的變動會造成已存在控制元件的屬性發生不同程度的改變,在傳統的基於控制元件物件的開發中,將導致物件不可識別。為了保證指令碼順利執行,唯有在 appobjects 層重新抓取所有的控制元件,包括新引入的控制元件,然後在 task 層加入對新控制元件的操作。應用了上述介面之後,我們將發現在 appobjects 層的物件沒有任何改動,只是在 task 層新加入一條語句,用來在表單中找到新引入的控制元件物件並對其進行操作,從而節省了很多繁雜的物件抓取、維護和程式碼改動工作。如下面的程式碼所示。

package tasks;
import common.appobjects.ObjForm;
import common.tasks.TaskTableOperation;
public boolean fillForm() {
StatelessGuiSubitemTestObject formTable = ObjForm.getFormTable();
TaskTableOperation.setTextEntryFromTable(formTable, “name”, “IBMer”);
TaskTableOperation.setTextEntryFromTable(formTable, “locatioin”, “Beijing”);
TaskTableOperation. setTextEntryFromTable (formTable, “email”, “IBMer@cn.ibm.com”);
return true;
}

作者;關 承恩, 軟體工程師, IBM

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14780914/viewspace-604218/,如需轉載,請註明出處,否則將追究法律責任。

相關文章