[小北De編程手記] : Lesson 08 - Selenium For C# 之 PageFactory & 團隊構建


  本文想跟大家分享的是Selenium對PageObject模式的支持和自動化測試團隊的構建。《Selenium For C#》系列的文章寫到這里已經接近尾聲了,如果之前的文章你是一篇篇的讀下來並動手實踐的話,我相信你應該可以模擬日常工作中80%常見的手動測試用例了。請注意:我的用詞是模擬用例,而不是書寫自動化測試用例。一個企業級的自動化測試的構建不是單靠Selenium一種技術就能Hold住的。所謂模擬指的是只能實現自動化的某個Case,但是不能工程化的使用。在本人所接觸過幾家公司的自動化測試的實踐中,有很多沒有或着不是很合理分層和封裝的自動化測試框架。Test Case中操作頁面驅動的Code隨處看見,無法根據人員的技術能力來分工,無法切換測試環境,只能使用單一的瀏覽器測試,對QA的使用門檻要求較高… …等等問題。

本文將會介紹如下內容:

  • PageObject設計模式介紹。
  • Selenium對PageObject模式的支持。
  • 簡單的測試結構
  • 自動化測試Team成員分工
  • Demo:博客園個人首頁的實現(這個是騙你的... ...)

(一)PageObject設計模式介紹

   Page Object是業界比較流行的自動化測試設計模式,能夠有效的提高自動化測試的可維護性和代碼的復用率。幾乎所有的自動化測試驅動框架都提供了對該模式的支持(Appium ,QTP ,White等)。當然,即使你使用的驅動不支持,我們也完全可以編寫代碼來實現它。畢竟所謂設計模式不過代碼的組織和協作方式而已。

  什么是Page Object模式呢?簡單的說,就是把待測試應用程序的頁面封裝成一個對象,暴露相關的屬性和方法給使用者(具體測試用例的編寫人員)。下圖是針對頁面的封裝:

  可以看到,Page類提供了一個TitleText屬性向用戶返回頁面的Title文本,還提供基本的頁面操作。對於使用者來說,他們不必關心這個頁 面上的元素是如何定位,也不必關心內部使用了怎樣的技術實現(Selenium,還是QTP)。另一個好處就是如果開發對頁面做了元素做了一定的調 整,我們只需要處理PageObject內部的代碼實現,而不需要修改實際測試用例代碼。該模式的好處還有很多,本文就不贅述了。我會在之后的框架實踐相關的文章中進行描述。

(二)Selenium對PageObject模式的支持

  下面我們一起來看一下,Selenium 對PageObject模式的支持。下面的代碼是一個登錄頁面的簡單封裝:

 1     public class SignInPage
 2     {
 3         public IWebDriver Driver { get; set; }
 4         public DashboardSignInPage(IWebDriver driver)
 5         {
 6             this.Driver = driver;
 7             PageFactory.InitElements(driver, this);
 8         }
 9         #region Page elements
10         [FindsBy(How = How.Id, Using = "username")]
11         protected IWebElement txtUserName;
12 
13         [FindsBy(How = How.Id, Using = "password")]
14         protected IWebElement txtPassword;
15 
16         [FindsBy(How = How.XPath, Using = ".//button[text()='Sign in']")]
17         protected IWebElement btnSignIn;
18         #endregion Page elements
19 
20         #region Action for test case
21         /// <summary>
22         /// Sign In for Dashboard
23         /// </summary>
24         /// <param name="userName">User name</param>
25         /// <param name="password">Password</param>
26         public void SignIn(string userName, string password)
27         {
28             this.txtUserName.Clear();
29             this.txtPassword.Clear();
30 
31             this.txtUserName.SendKeys(userName);
32             this.txtPassword.SendKeys(password);
33 
34             this.btnSignIn.Click();
35         }
36 
37         //Other action... ...
38         #endregion
39     }        

  上面的代碼中出現的FindsBy和PageFactory正是Selenium WebDriver提供的針對PageObject模式的支持。

  @PageFactory類

  FageFactory提供了PageObject實例的能力,我們可以看到它本身提供了很多的方法來構建具體的頁面類的實例。它的主要作用的是將我們用FindsBy屬性標記的字段和指定的DOM元素進行映射。而后我們可以直接使用具體屬性操作DOM元素,不必使用FindElement方法來定位。

1     public sealed class PageFactory
2     {
3         public static T InitElements<T>(IElementLocator locator);
4         public static T InitElements<T>(IWebDriver driver);
5         public static void InitElements(ISearchContext driver, object page);
6         public static void InitElements(object page, IElementLocator locator);
7         public static void InitElements(ISearchContext driver, object page, IPageObjectMemberDecorator decorator);
8         public static void InitElements(object page, IElementLocator locator, IPageObjectMemberDecorator decorator);
9     }

  @FindsBy屬性

  FindsBy屬性是用來標記程序中的元素是如何定位的。我們可以使用之前《Lesson 03 - Selenium For C# 之 元素定位》中講到的任何一種定位方式來標記如何定位元素。利用How參數指定定位方式,這是Using參數標識具體的值。如果對如何定位元素不是很清楚,可以查看之前的文章,這里就不再贅述了。

 1     // Summary:
 2     //     Provides the lookup methods for the FindsBy attribute (for using in PageObjects)
 3     public enum How
 4     {
 5         // Summary:
 6         //     Finds by OpenQA.Selenium.By.Id(System.String)
 7         Id = 0,
 8         //
 9         // Summary:
10         //     Finds by OpenQA.Selenium.By.Name(System.String)
11         Name = 1,
12         //
13         // Summary:
14         //     Finds by OpenQA.Selenium.By.TagName(System.String)
15         TagName = 2,
16         //
17         // Summary:
18         //     Finds by OpenQA.Selenium.By.ClassName(System.String)
19         ClassName = 3,
20         //
21         // Summary:
22         //     Finds by OpenQA.Selenium.By.CssSelector(System.String)
23         CssSelector = 4,
24         //
25         // Summary:
26         //     Finds by OpenQA.Selenium.By.LinkText(System.String)
27         LinkText = 5,
28         //
29         // Summary:
30         //     Finds by OpenQA.Selenium.By.PartialLinkText(System.String)
31         PartialLinkText = 6,
32         //
33         // Summary:
34         //     Finds by OpenQA.Selenium.By.XPath(System.String)
35         XPath = 7,
36         //
37         // Summary:
38         //     Finds by a custom OpenQA.Selenium.By implementation.
39         Custom = 8,
40     }

   那么最后,我們來看一下消費者(上層的測試用例編寫人員)將如何使用如何使用這個類,這個Code只是一個使用SignInPage的示例,我們看到這里還是在測試用例中寫入了創建Driver和導航頁面的代碼,按照先前的架構這樣也是存在問題的,這里就不再展開了,期待我后續關於自動化框架設計的文章吧~~~:

 1         private const string cst_DisplayName = "BaseCheck.SignIn";
 2         [Fact(DisplayName = cst_DisplayName + ".Success")]
 3         public void SignIn_Success()
 4         {
 5             var driver = new FrieFoxDriver();
 6             driver.Url = "www.xxx.com/signin";
 7 
 8             var signInPage = new SignInPage(driver);
 9             signInPage.SignIn("your name", "password");
10 
11             //省略Code... ...    
12             driver.Close();
13         }

(三)簡單的測試結構

  讀到這里,即使你是初學者。想必也能明白一些PageObject設計模式為何物,這里我還是描述一下 PageObject的意圖:PageObject模式是為了封裝頁面元素定位,頁面等待、跳轉等操作頁面相關的邏輯。使得使用者在不必關心這些邏輯的情 況下,可以書寫相關的測試用例。我們回顧一下我之前在《Lesson 02 - Selenium For C# 之 核心對象》中提到的一般的企業級測試框架中的結構圖:

   上圖中的紅線圈出來的部分就是PageObject的消費者(編寫測試用例的Tester)。可以看到,下一層的開發人員可以把頁面的封裝成 PageObject,上層的使用者不必關心具體的實現技術是哪一種(Selenium , Appium... ...)。PageObject的消費者可以專注於Test Case的邏輯實現。

(四)自動化測試Team成員分工

  之前有很多公司或是朋友跟我探討過如何組建自動化測試團隊。無一例外都談到了(糾結於)這些問題:需要QA Team有很強的編碼能力,他們要學習各種驅動(Selenium , QTP , Appium... ...)的使用 , 了解一些JavaScript、HTML、CSS相關的知識,具有OOP思維... ...等等等。最終的結論就是構建自動化測試對QA的人員提出了很高的要求。在我看來,如果一個QA可以具有了上述能力我想他已經是一個開發人員了(這個要求不切實際)。那可不可以讓開發團隊來完成這件事情呢?這個當然不行了,理由有N多。這里我只提兩條。第一,開發團隊的視角往往不是站在用戶角度的,因此會極大的提升項目風險。第二,一個自動化測試構建的成功與否?合理的測試計划往往是決定性因素,但是測試計划的制定卻不是開發人員所擅長的。(這里沒有歧視開發的意思。嘻嘻~~本人也是開發~~~不喜勿噴)。那么,如何構建呢?這個其實也是我們要構建測試框架,分層,使用PageObject模式的原因了,針對上一節我畫出的簡單結構而言,團隊中可以有如下幾個角色:

@功能測試人員:

  主要是由手工測試人員和懂一些簡單編程語法的測試人員組成,他們是PageObject和測試框架的直接使用者(消費者)。使用已經完成的PageObject和測試框架進行測試用例的編寫,以及測試計划的制定。以我個人的經驗,一般的QA簡單的培訓一下即可以勝任這樣的工作,而他們所完成的卻是很大的一部份工作。功能測試人員專注與邏輯的測試,而不易關心技術細節。

@PageObject編寫人員:

  這部分人員可以由測試團隊中技術(編程技術)較高或是開發人員來擔當,要求如下:

  • 熟悉相關的驅動的使用(Selenium、QTP... ....),不熟悉也沒關系,看看我的《Selenium For C#》系列哈~~~
  • 熟悉Web編程,JavaScript、HTML、CSS相關的知識。(基於B/S的測試構建,要是桌面或是手機端還要其他的知識)
  • 熟悉OOP思想,能針對頁面做出合理的封裝。

  因此,這部分同學專注與提供好用的頁面類,而不必須關系紛繁復雜的業務邏輯。這部分人也是測試人員的一個職業發展方向(技術型測試)。

@測試架構師:

  這個就需要資深一些的同學來做了,架構師的要求嘛就比較多了。他在團隊中主要的任務就是構建測試的基礎設施。比如頁面導航的管理,提供ORM機制供測試人員使用,日志的輸出,測試報告的生成,環境切換,瀏覽器切換,提供一些炫酷而簡單的使用功能,還有就是最一些文檔的輸出。這樣一來,測試架構師也可以關心他所需要完成的技術難題,而不關心業務和具體的頁面類的實現。

 

  總結一下,有了這三種分工其實工作在不同的層面上。各自完成所擅長的那一部分。於此同時也提供生了整個測試的可維護性。比如:頁面做了修改,只需要PageObject人員去修改自己的封裝。而業務邏輯出現了變更(頁面不變的話),也只是需要用例編寫人員修改一下自己的測試用了而已。

(五)寫在最后的... ...

  本來是想做一個Demo給大家的。但是... ...過年了... ... 老媽催着回家過年,收拾行李去呀,有機會再補上吧 ... ... 今天就任性一把 哈哈 , 各位小伙伴,新年快樂!

  前面講了分工,現在的你是哪個級別呢?能一篇篇把我的系列文章看到這一篇的,估計多數還是沒有構建測試框架能力的小伙伴。所以,后面如果時間允許的話我會寫一個關於自動化測試框架構建的系列,記得關注哦~~~

《Selenium For C#》的相關文章:Click here.

說明:Demo地址:https://github.com/DemoCnblogs/Selenium

 

如果您認為這篇文章還不錯或者有所收獲,可以點擊右下角的 【推薦】按鈕,因為你的支持是我繼續寫作,分享的最大動力!
作者:小北@North
來源:http://www.cnblogs.com/NorthAlan
聲明:本博客原創文字只代表本人工作中在某一時間內總結的觀點或結論,與本人所在單位沒有直接利益關系。非商業,未授權,貼子請以現狀保留,轉載時必須保留此段聲明,且在文章頁面明顯位置給出原文連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM