[WinAppDriver] 使用 Page Object Pattern 重構測試程式碼

上一篇 [Appium][WinAppDriver] Appium + WinAppDriver 測試 Windows 桌面應用程式 UI,介紹如何使用 Appium + WinAppDriver 進行桌面應用程式的測試,但那個測試程式有點醜,我想要用 Page Object 重構一下,由於目前沒有工具可以協助,所以得一個一個敲

開發環境

  • VS 2017
  • .NET Framework 4.7.2
  • Windows 10 Enterprise ver.1803 ,OS build 17134.648

重構前

先看看原本的面貌,我要做的動作就是把 FindElement 搬到 Page Object 

[TestMethod] public void 輸入帳號密碼_按下登入_預期得到一個彈跳視窗並呈現Hiyao()
{
    WindowsDriver.FindElementByAccessibilityId("Id_TextBox").SendKeys("yao");
    WindowsDriver.FindElementByAccessibilityId("Password_TextBox").SendKeys("123456");
    WindowsDriver.FindElementByAccessibilityId("Login_Button").Click();
 
    var messageBox = WindowsDriver.FindElementByClassName("#32770");
    var title = messageBox.Text;
    var messageText = messageBox.FindElementByXPath("//Text[@Name='Hi~yao']").Text;
 
    Assert.AreEqual("Title", title);
    Assert.AreEqual("Hi~yao", messageText);
 
    WindowsDriver.FindElementByXPath("//Button[@Name='OK']").Click();
}
Page Object 是為了隔離網頁結構的物件,讓測試程式碼不會出現 FindElment 這樣的代碼,提升測試程式碼的可讀性,請參考 https://martinfowler.com/bliki/PageObject.html

 

重構

首先建立 Page Object

internal class LoginPage
{
    protected internal WindowsDriver<WindowsElement> _driver;
 
    public LoginPage(WindowsDriver<WindowsElement> driver)
    {
        this._driver = driver;
    }
}

 

UI 上有三個控制項,分別為它們建立 IWinAppDriver 欄位,設定控制項狀態

// id
 
public WindowsElement IdElement => this._driver.FindElementByAccessibilityId("Id_TextBox");
 
public LoginPage SetId(string id)
{
    this.IdElement.SendKeys(id);
    return this;
}
 
// password
 
public WindowsElement PasswordElement => this._driver.FindElementByAccessibilityId("Password_TextBox");
 
public LoginPage SetPassword(string password)
{
    this.PasswordElement.SendKeys(password);
    return this;
}
 
// login
 
public WindowsElement LoginElement => this._driver.FindElementByAccessibilityId("Login_Button");
 
public LoginPage ClickLogin()
{
    this.LoginElement.Click();
    return this;
}
 

 

測試程式碼

[TestMethod]
public void 輸入帳號密碼_按下登入_預期得到一個彈跳視窗並呈現Hiyao()
{
    var loginPage = new LoginPage(WindowsDriver);
    loginPage.SetId("yao")
             .SetPassword("123456")
             .ClickLogin();

    var messageBox = WindowsDriver.FindElementByClassName("#32770");
    var title = messageBox.Text;
    var messageText = messageBox.FindElementByXPath("//Text[@Name='Hi~yao']").Text;

    Assert.AreEqual("Title", title);
    Assert.AreEqual("Hi~yao", messageText);

    WindowsDriver.FindElementByXPath("//Button[@Name='OK']").Click();
}

 

彈跳視窗的OK的 Element

// ok button
public WindowsElement OkElement => this._driver.FindElementByXPath("//Button[@Name='OK']");
 
public LoginPage ClickOK()
{
    this.OkElement.Click();
    return this;
}

 

彈跳視窗的 Element、驗證

// messagebox
public WindowsElement MessageBoxElemnt => this._driver.FindElementByClassName("#32770");
 
public LoginPage VerifyMessageBoxByName(string expected)
{
    var messageText = this.MessageBoxElemnt.FindElementByXPath($"//Text[@Name='{expected}']").Text;
    Assert.AreEqual(expected, messageText);
    return this;
}
 
public LoginPage VerifyMessageBoxByTitle(string expected)
{
    var messageText = this.MessageBoxElemnt.Text;
    Assert.AreEqual(expected, messageText);
    return this;
}
 

 

測試程式碼最後變成這樣,看起來乾淨多了呢

[TestMethod]
public void 輸入帳號密碼_按下登入_預期得到一個彈跳視窗並呈現Hiyao()
{
    var loginPage = new LoginPage(WindowsDriver);
    loginPage.SetId("yao")
             .SetPassword("123456")
             .ClickLogin();
 
    loginPage.VerifyMessageBoxByTitle("Title")
             .VerifyMessageBoxByName("Hi~yao");
 
    loginPage.ClickOK();
}

 

完整的 Page Object
https://github.com/yaochangyu/sample.dotblog/blob/master/Test/WinAppDriver/Lab.WinAppDriverTest/App.UnitTest/LoginPage.cs

完整測試程式
https://github.com/yaochangyu/sample.dotblog/blob/master/Test/WinAppDriver/Lab.WinAppDriverTest/App.UnitTest/PageObjectUnitTest.cs

範例專案
https://github.com/yaochangyu/sample.dotblog/tree/master/Test/WinAppDriver/Lab.WinAppDriverTest

 

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo