專案引入持續整合自動化驗收測試,選用 Selenium WebDriver (瀏覽器自動化) 搭配 AutoIt (Windows 原生視窗處理),本文從 IDE 錄製到程式碼重構完整示範。
| 工具 | 定位 | 優勢 | 適用場景 |
|---|---|---|---|
| Selenium WebDriver | Web UI 自動化 | 多瀏覽器、多語言、W3C 標準、生態豐富 | 網頁操作、驗證、截圖、等待策略 |
| AutoIt | Windows GUI 自動化 | 處理檔案上傳對話框、原生視窗、Flash、驅動程式安裝視窗 | WebDriver 無法觸及的 OS 級視窗 |
[TestFixture]
public class CnblogsSearchTest
{
private IWebDriver _driver;
private StringBuilder _errors;
private const string BaseUrl = "https://www.cnblogs.com/";
[SetUp]
public void Setup()
{
_driver = new FirefoxDriver();
_errors = new StringBuilder();
}
[TearDown]
public void Teardown()
{
try { _driver.Quit(); } catch { }
Assert.AreEqual("", _errors.ToString());
}
[Test]
public void SearchTest()
{
_driver.Navigate().GoToUrl(BaseUrl);
_driver.FindElement(By.Id("zzk_q")).Clear();
_driver.FindElement(By.Id("zzk_q")).SendKeys("熬夜的蟲子");
_driver.FindElement(By.CssSelector("input.search_btn")).Click();
// 可加入斷言驗證結果頁關鍵字
}
private bool IsElementPresent(By by)
{
try { _driver.FindElement(by); return true; }
catch (NoSuchElementException) { return false; }
}
}
WebDriver 無法操作 `` 觸發的 OS 原生對話框,需 AutoIt 協助。
WinWait("[CLASS:#32770]", "", 3) ; 等待開啟檔案對話框 (Win7/10 通用類別)
WinActivate("[CLASS:#32770]")
ControlFocus("[CLASS:#32770]", "", "[CLASS:Edit; INSTANCE:1]")
Send("E:\TestFiles\demo.avi") ; 輸入完整路徑
ControlClick("[CLASS:#32770]", "開啟(&O)", "Button1") ; 點擊開啟按鈕
; 或發送快捷鍵
Send("!o") ; Alt+O
Send("{ENTER}")
using AutoItX3Lib;
public void UploadFile(IWebDriver driver, string filePath)
{
// 觸發上傳對話框
driver.FindElement(By.Id("fileUpload")).Click();
// 等待對話框出現 (隱性等待不適用,需顯性等待或 Thread.Sleep)
Thread.Sleep(1000);
var autoIt = new AutoItX3();
const string dialogTitle = "[CLASS:#32770]";
autoIt.WinWait(dialogTitle, "", 3);
autoIt.WinActivate(dialogTitle);
autoIt.ControlFocus(dialogTitle, "", "[CLASS:Edit; INSTANCE:1]");
autoIt.Send(filePath);
autoIt.Sleep(100);
autoIt.ControlClick(dialogTitle, "開啟(&O)", "Button1");
autoIt.Sleep(100);
autoIt.Send("!o");
autoIt.Send("{ENTER}");
}
// 頁面封裝
public class HomePage
{
private readonly IWebDriver _driver;
private readonly WebDriverWait _wait;
private IWebElement SearchBox => _driver.FindElement(By.Id("zzk_q"));
private IWebElement SearchBtn => _driver.FindElement(By.CssSelector("input.search_btn"));
public HomePage(IWebDriver driver)
{
_driver = driver;
_wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
}
public void Search(string keyword)
{
SearchBox.Clear();
SearchBox.SendKeys(keyword);
SearchBtn.Click();
}
public ResultPage GoToResultPage() => new ResultPage(_driver);
}
// 測試案例
[Test]
public void Search_WithKeyword_ShouldShowResults()
{
var home = new HomePage(_driver);
home.Navigate();
home.Search("Selenium WebDriver");
var result = home.GoToResultPage();
Assert.IsTrue(result.HasResults());
}
自動化測試非銀彈,**維護成本高**、**脆弱性強** (UI 變動即失效)。建議:核心流程 (登入、下單、支付) 自動化,邊緣功能人工驗證;優先投資 API 測試 (成本低、穩定、快)。