qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

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

          上一篇: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.waitForPageToLoad("30000");
                       selenium.click("adminHomeForm:_activityold");
                       selenium.waitForPageToLoad("30000");
          }

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

          public void testNew() throws Exception {
                       selenium.open(http://www.test.com);
                       selenium.type(admin.username, "xxxxxxxx");
                       selenium.click(admin.loginbutton);
                       selenium.click(admin.events.createnewevent);
                       selenium.waitForPageToLoad("30000");
                       selenium.click(admin.events.cancel);
                       selenium.waitForPageToLoad("30000");
                       selenium.click(admin.events.viewoldevents);
                       selenium.waitForPageToLoad("30000");
          }

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

          public void testNew() throws Exception {
           
                       // Open app url.
                       selenium.open(http://www.test.com);
           
                       // Provide admin username.
                       selenium.type(admin.username, "xxxxxxxx");
           
                       // Click on Login button.
                       selenium.click(admin.loginbutton);
           
                       // Click on Create New Event button.
                       selenium.click(admin.events.createnewevent);
                       selenium.waitForPageToLoad("30000");
           
                       // Click on Cancel button.
                       selenium.click(admin.events.cancel);
                       selenium.waitForPageToLoad("30000");
           
                       // Click on View Old Events button.
                       selenium.click(admin.events.viewoldevents);
                       selenium.waitForPageToLoad("30000");
          }

            有多種方法可以實現UI映射。可以創建一個類或結構體來存儲字符串變量,每個變量存儲一個定位信息。或者,使用一個文本文件來存儲鍵值對。在Java中,一個包含鍵值對的屬性property文件可能是最好的方法。


           考慮如下屬性文件prop.properties,為上述代碼例子中的UI元素指定了 “別名”:

          admin.username = loginForm:tbUsername
          admin.loginbutton = loginForm:btnLogin
          admin.events.createnewevent = adminHomeForm:_activitynew
          admin.events.cancel = addEditEventForm:_IDcancel
          admin.events.viewoldevents = adminHomeForm:_activityold

            其中定位信息還是指向頁面的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.click("sign-in");
                          selenium.waitForPageToLoad("waitPeriod");
           
                          return new HomePage(selenium);
                  }
          }


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

          /**
           * Page Object encapsulates the Home Page
           */
          public class HomePage {
           
                  private Selenium selenium;
           
                  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
                          return new HomePage(selenium);
                  }
           
                  /*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*/
           
          }

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

          /***
           * Tests login feature
           */
          public class TestLogin {
           
                  public void testLogin() {
                          SignInPage signInPage = new SignInPage(selenium);
                          HomePage homePage = signInPage.loginValidUser("userName", "password");
                          Assert.assertTrue(selenium.isElementPresent("compose button"),
                                          "Login was unsuccessful");
                  }
          }

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

            唯一的應該存在頁面對象中的驗證方法是,驗證頁面、頁面上的重要元素,被正確的加載。這這個驗證應該在頁面初始化時進行。在上面的例子中,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例子從數據庫中檢索數據。

            本文轉載自:http://www.loggingselenium.com/

          相關鏈接:


          posted on 2013-01-28 10:53 順其自然EVO 閱讀(3005) 評論(0)  編輯  收藏 所屬分類: selenium and watir webdrivers 自動化測試學習

          <2013年1月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 广饶县| 曲沃县| 福泉市| 勐海县| 颍上县| 大埔县| 张家界市| 磐安县| 松江区| 宁南县| 搜索| 铜鼓县| 中宁县| 临江市| 莎车县| 江都市| 平阴县| 龙川县| 灌阳县| 合川市| 绥江县| 香河县| 固安县| 白河县| 牟定县| 那坡县| 哈巴河县| 龙南县| 鲜城| 大名县| 揭西县| 罗源县| 凉山| 盐边县| 南昌县| 营口市| 呼和浩特市| 武汉市| 崇仁县| 奉新县| 临武县|