本文想跟你們分享的是Selenium對PageObject模式的支持和自動化測試團隊的構建。《Selenium For C#》系列的文章寫到這裏已經接近尾聲了,若是以前的文章你是一篇篇的讀下來並動手實踐的話,我相信你應該能夠模擬平常工做中80%常見的手動測試用例了。請注意:個人用詞是模擬用例,而不是書寫自動化測試用例。一個企業級的自動化測試的構建不是單靠Selenium一種技術就能Hold住的。所謂模擬指的是隻能實現自動化的某個Case,可是不能工程化的使用。在本人所接觸過幾家公司的自動化測試的實踐中,有不少沒有或着不是很合理分層和封裝的自動化測試框架。Test Case中操做頁面驅動的Code隨處看見,沒法根據人員的技術能力來分工,沒法切換測試環境,只能使用單一的瀏覽器測試,對QA的使用門檻要求較高… …等等問題。html
本文將會介紹以下內容:git
Page Object是業界比較流行的自動化測試設計模式,可以有效的提升自動化測試的可維護性和代碼的複用率。幾乎全部的自動化測試驅動框架都提供了對該模式的支持(Appium ,QTP ,White等)。固然,即便你使用的驅動不支持,咱們也徹底能夠編寫代碼來實現它。畢竟所謂設計模式不過代碼的組織和協做方式而已。github
什麼是Page Object模式呢?簡單的說,就是把待測試應用程序的頁面封裝成一個對象,暴露相關的屬性和方法給使用者(具體測試用例的編寫人員)。下圖是針對頁面的封裝:編程
能夠看到,Page類提供了一個TitleText屬性向用戶返回頁面的Title文本,還提供基本的頁面操做。對於使用者來講,他們沒必要關心這個頁 面上的元素是如何定位,也沒必要關心內部使用了怎樣的技術實現(Selenium,仍是QTP)。另外一個好處就是若是開發對頁面作了元素作了必定的調 整,咱們只須要處理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模式的支持。架構
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屬性是用來標記程序中的元素是如何定位的。咱們可使用以前《Lesson 03 - Selenium For C# 之 元素定位》中講到的任何一種定位方式來標記如何定位元素。利用How參數指定定位方式,這是Using參數標識具體的值。若是對如何定位元素不是很清楚,能夠查看以前的文章,這裏就再也不贅述了。ide
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和導航頁面的代碼,按照先前的架構這樣也是存在問題的,這裏就再也不展開了,期待我後續關於自動化框架設計的文章吧~~~:post
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的邏輯實現。
以前有不少公司或是朋友跟我探討過如何組建自動化測試團隊。無一例外都談到了(糾結於)這些問題:須要QA Team有很強的編碼能力,他們要學習各類驅動(Selenium , QTP , Appium... ...)的使用 , 瞭解一些JavaScript、HTML、CSS相關的知識,具備OOP思惟... ...等等等。最終的結論就是構建自動化測試對QA的人員提出了很高的要求。在我看來,若是一個QA能夠具備了上述能力我想他已是一個開發人員了(這個要求不切實際)。那可不可讓開發團隊來完成這件事情呢?這個固然不行了,理由有N多。這裏我只提兩條。第一,開發團隊的視角每每不是站在用戶角度的,所以會極大的提高項目風險。第二,一個自動化測試構建的成功與否?合理的測試計劃每每是決定性因素,可是測試計劃的制定卻不是開發人員所擅長的。(這裏沒有歧視開發的意思。嘻嘻~~本人也是開發~~~不喜勿噴)。那麼,如何構建呢?這個其實也是咱們要構建測試框架,分層,使用PageObject模式的緣由了,針對上一節我畫出的簡單結構而言,團隊中能夠有以下幾個角色:
主要是由手工測試人員和懂一些簡單編程語法的測試人員組成,他們是PageObject和測試框架的直接使用者(消費者)。使用已經完成的PageObject和測試框架進行測試用例的編寫,以及測試計劃的制定。以我我的的經驗,通常的QA簡單的培訓一下便可以勝任這樣的工做,而他們所完成的倒是很大的一部份工做。功能測試人員專一與邏輯的測試,而不易關心技術細節。
這部分人員能夠由測試團隊中技術(編程技術)較高或是開發人員來擔當,要求以下:
所以,這部分同窗專一與提供好用的頁面類,而沒必要須關係紛繁複雜的業務邏輯。這部分人也是測試人員的一個職業發展方向(技術型測試)。
這個就須要資深一些的同窗來作了,架構師的要求嘛就比較多了。他在團隊中主要的任務就是構建測試的基礎設施。好比頁面導航的管理,提供ORM機制供測試人員使用,日誌的輸出,測試報告的生成,環境切換,瀏覽器切換,提供一些炫酷而簡單的使用功能,還有就是最一些文檔的輸出。這樣一來,測試架構師也能夠關心他所須要完成的技術難題,而不關心業務和具體的頁面類的實現。
總結一下,有了這三種分工其實工做在不一樣的層面上。各自完成所擅長的那一部分。於此同時也提供生了整個測試的可維護性。好比:頁面作了修改,只須要PageObject人員去修改本身的封裝。而業務邏輯出現了變動(頁面不變的話),也只是須要用例編寫人員修改一下本身的測試用了而已。
原本是想作一個Demo給你們的。可是... ...過年了... ... 老媽催着回家過年,收拾行李去呀,有機會再補上吧 ... ... 今天就職性一把 哈哈 , 各位小夥伴,新年快樂!
前面講了分工,如今的你是哪一個級別呢?能一篇篇把個人系列文章看到這一篇的,估計多數仍是沒有構建測試框架能力的小夥伴。因此,後面若是時間容許的話我會寫一個關於自動化測試框架構建的系列,記得關注哦~~~
《Selenium For C#》的相關文章:Click here.
說明:Demo地址:https://github.com/DemoCnblogs/Selenium