天天看點

Selenium自動化測試用例設計注意事項(二)

ui映射

  一個ui映射是一種機制,它存儲所有的定位器的測試套件在一個地方,友善修改ui元素的路徑辨別符或改變在aut。測試腳本,然後使用ui地圖定位以被測試的元件。基本上,ui地圖是一個存儲庫的測試腳本對象,對應于被測試的應用程式的ui元素。

  是什麼讓一個ui地圖有幫助嗎?其主要目的是測試腳本的管理更加容易。當定位需要編輯,有一個中央位置輕松地找到對象,而不是通過搜尋測試腳本代碼。此外,它允許改變的辨別符在一個地方,而不是在多個地方,以使更改在測試腳本,或為此事,在多個測試腳本。

  總之,一個ui地圖有兩個顯着的優點。

  ● ui對象使用一個集中的位置,而不是讓他們分散在整個腳本。這使得腳本維護更高效。

  ● 神秘的html辨別符和名稱可以被賦予了更多的人類可讀的名字,提高測試腳本的可讀性。

  考慮下面很難了解的測試代碼(java語言)。

public void testnew() throws exception {

             selenium.open(http://www.test.com);

             selenium.type("loginform:tbusername", "xxxxxxxx");

             selenium.click("loginform:btnlogin");

             selenium.click("adminhomeform:_activitynew");

             selenium.waitforpagetoload("30000");

             selenium.click("addediteventform:_idcancel");

             selenium.click("adminhomeform:_activityold");

}

  該代碼很難被那些不熟悉待測應用(aut)頁面源代碼的人了解。即使是待測應用的固定使用者可能也很難了解這段腳本代碼的作用。一個更好的腳本可能是:

             selenium.type(admin.username, "xxxxxxxx");

             selenium.click(admin.loginbutton);

             selenium.click(admin.events.createnewevent);

             selenium.click(admin.events.cancel);

             selenium.click(admin.events.viewoldevents);

  使用備注和空格換行、再加上ui映射辨別,下面的代碼更加易讀:

             // open app url.

             // provide admin username.

             // click on login button.

             // click on create new event button.

             // click on cancel button.

             // click on view old events button.

  有多種方法可以實作ui映射。可以建立一個類或結構體來存儲字元串變量,每個變量存儲一個定位資訊。或者,使用一個文本檔案來存儲鍵值對。在java中,一個包含鍵值對的屬性property檔案可能是最好的方法。

 考慮如下屬性檔案prop.properties,為上述代碼例子中的ui元素指定了 “别名”:

  其中定位資訊還是指向頁面的html對象,但我們在測試腳本和ui元素之間引入一層抽象層。測試類從屬性檔案中讀取定位資訊,進而實作ui映射。

  頁面對象設計模式

  頁面對象設計模式,可以提高自動化測試腳本的維護性、減少代碼重複,越發流行。頁面對象是一個面向對象的類,作為待測應用對外提供的接口。測試代碼在需要和ui頁面互動時,使用此頁面對象類的方法。這樣做的好處是,如果ui頁面發生變化,測試代碼本身并不需要改變,隻需要改變相應的頁面對象的代碼。為适應新ui頁面的所有更改,都位于一個地方。

  頁面對象設計模式具有以下優點:

  1、測試代碼和頁面相關的代碼,比如頁面元素定位資訊(若使用ui映射,也包括定位資訊的應用),頁面布局等,完全分離;

  2、可以維護單一的儲存庫來存儲頁面提供的服務或操作,而不是把他們分散在測試代碼中。

  在這兩種情況下,這使得任何由于ui界面變化導緻的修改,都可以在一個地方進行修改。關于該技術的更多有用資訊,可以在衆多的部落格上找到。我們也鼓勵讀者去閱讀更多。 許多人寫這樣的設計模式和超出本使用者指南的範圍,可以提供有用的提示。不過,為了讓你開始,我們将舉例說明頁面對象的一個簡單的例子。

  首先,考慮一個例子,典型的自動化測試,不使用頁面對象。

/***

 * tests login feature

 */

public class login {

        public void testlogin() {

                selenium.type("inputbox", "testuser");

                selenium.type("password", "my supersecret password");

                selenium.click("sign-in");

                selenium.waitforpagetoload("pagewaitperiod");

                assert.asserttrue(selenium.iselementpresent("compose button"),

                                "login was unsuccessful");

        }

  這種方法有兩個問題。

  1、沒有分離測試代碼和待測應用的定位器(在這個例子中是id);兩者都交織在一個單一方法中。如果待測應用ui改變了它的辨別,布局,或登入輸入和處理的方式變化,測試代碼本身必須改變。

  2、id定位資訊分散在多個測試代碼中,所有的測試不得不使用此登入頁面。

  使用頁面對象技術,上述測試代碼可以按如下方式重寫,為登入頁面的頁面對象例子:

/**

 * page object encapsulates the sign-in page.

public class signinpage {

        private selenium selenium;

        public signinpage(selenium selenium) {

                this.selenium = selenium;

                if(!selenium.gettitle().equals("sign in page")) {

                        throw new illegalstateexception("this is not sign in page, current page is: "

                                        +selenium.getlocation());

                }

        /**

         * login as valid user

         *

         * @param username

         * @param password

         * @return homepage object

         */

        public homepage loginvaliduser(string username, string password) {

                selenium.type("usernamefield", username);

                selenium.type("passwordfield", password);

                selenium.waitforpagetoload("waitperiod");

                return new homepage(selenium);

 首頁的頁面對象可能會是這個樣子:

 * page object encapsulates the home page

public class homepage {

        public homepage(selenium selenium) {

                if (!selenium.gettitle().equals("home page of logged in user")) {

                        throw new illegalstateexception("this is not home page of logged in user, current page" +

                                        "is: " +selenium.getlocation());

        public homepage manageprofile() {

                // page encapsulation to manage profile functionality

        /*more methods offering the services represented by home page

        of logged user. these methods in turn might return more page objects

        for example click on compose mail button could return composemail class object*/

  現在,使用上述兩個頁面對象的登入測試代碼,如下所示。

public class testlogin {

                signinpage signinpage = new signinpage(selenium);

                homepage homepage = signinpage.loginvaliduser("username", "password");

  怎麼樣使用頁面對象進行設計有很大的靈活性,但也有一些基本的規則以保證得到測試代碼具有所需的可維護性。頁面對象本身不應該被驗證或斷言。這應該是測試的一部分,并應始終在測試代碼中去驗證或斷言,而不要放在頁面對象内。頁面對象将包含頁面展現,方法的形式表示頁面提供的服務,但不需要包含應該在測試代碼中維護的代碼。

  唯一的應該存在頁面對象中的驗證方法是,驗證頁面、頁面上的重要元素,被正确的加載。這這個驗證應該在頁面初始化時進行。在上面的例子中,signinpage 和 homepage 的構造函數檢查了期望的頁面是否可用,是否準備好接受測試代碼的請求。

  頁面對象并不一定要代表整個頁面。頁面對象設計模式可用于表示頁面上元件。在待測應用上的一個頁面若有多個元件,每個元件對應一個頁面對象可以提高可維護性。

  在測試時,還會遇到其他的測試設計模式。有些人用一個頁面工廠模式來執行個體化頁面對象。讨論所有的這些測試模式,超出了本文檔的的範圍。在這裡,我們隻為大家介紹概念,使讀者知道這些東西可以些什麼。正如前面提到的,很多人都在部落格上讨論這個話題,我們鼓勵讀者搜尋這些話題。

  資料驅動測試

  資料驅動測試是指相同的測試(或測試集)可以使用不同的資料多次執行。這些資料集往往來自外部檔案,如csv檔案,文本檔案,或者是從資料庫加載。資料驅動測試是一種常用的自動化測試技術,使用不同的輸入對應用程式進行多次驗證。當測試被針對不同的資料進行設計時,所輸入的資料就可以擴充,基本上不需要修改測試代碼就可以進行更多的測試。

# collection of string values

source = open("input_file.txt", "r")

values = source.readlines()

source.close()

# execute for loop for each string in the values array

for search in values:

    sel.open("/")

    sel.type("q", search)

    sel.click("btng")

    sel.waitforpagetoload("30000")

    self.failunless(sel.is_text_present("results * for " + search))

 上面的python代碼打開一個文本檔案,這個檔案每行包含不同的搜尋字元串。然後代碼儲存字元串到一個字元串數組,對數值進行周遊,使用搜尋字元串進行查詢,并進行斷言。

  這是一個非常簡單的例子,但其中的思路表明,可以很簡單的使用程式設計、腳本語言進行資料驅動的測試。有關更多示例,請參閱 selenium rc wiki 來了解如何從電子表格讀取資料或使用testng的提供資料。此外,這是一個在自動化測試的專業人士圈内衆所周知的話題之一,包括那些不使用selenium的自動化圈子,是以搜尋網際網路上的“資料驅動測試”,會得到許多關于這一主題的部落格。

  資料庫驗證

  另一種常見的測試類型是,比較使用者界面上的資料和存儲在背景資料庫中的資料。因為你也可以使用一種程式設計語言進行資料庫查詢,假設你有資料庫相關的函數,你可以用它們來檢索資料,然後使用這些資料來驗證頁面上所顯示的資料是正确的。

  考慮如下例子,從資料庫中進行檢索注冊電子郵件位址,然後再和界面上的資料進行比較。代碼如下,先建立一個資料庫連接配接,并從資料庫中檢索資料,使用的是java語言:

// load microsoft sql server jdbc driver.

class.forname("com.microsoft.sqlserver.jdbc.sqlserverdriver");

// prepare connection url.

string url = "jdbc:sqlserver://192.168.1.180:1433;databasename=test_db";

// get connection to db.

public static connection con =

drivermanager.getconnection(url, "username", "password");

// create statement object which would be used in writing ddl and dml

// sql statement.

public static statement stmt = con.createstatement();

// send sql select statements to the database via the statement.executequery

// method which returns the requested information as rows of data in a

// resultset object.

resultset result =  stmt.executequery

("select top 1 email_address from user_register_table");

// fetch value of "email_address" from "result" object.

string emailaddress = result.getstring("email_address");

// use the emailaddress value to login to application.

selenium.type("userid", emailaddress);

selenium.type("password", secretpassword);

selenium.click("loginbutton");

selenium.waitforpagetoload(timeout);

assert.asserttrue(selenium.istextpresent("welcome back" +emailaddress), "unable to log in for user" +emailaddress)

  這是一個簡單的java例子從資料庫中檢索資料。

====================================分割線================================

最新内容請見作者的github頁:http://qaseven.github.io/