构建自己的测试框架可能听起来有些吓人,但实际上并没有那么可怕。今天,将迈出创建用于测试Web应用程序的Selenium框架的第一步。在开始之前,建议阅读“Selenium是什么?”的文章,以便至少理解Selenium和WebDriver代码的基础知识。
任何基于Selenium的框架最重要的部分是它能够启动浏览器,并具有启动多种浏览器的灵活性,以覆盖跨浏览器测试。这正是第一个类将要做的事情。与大多数网站在进行框架教程时的做法不同,将为每个类写一篇文章,但确保在文章结束时,理解了正在做的事情、为什么要这样做以及这样做的思路。如果只是给出5个类的示例,而一个都不理解,那么下一篇文章又有什么帮助呢?话虽如此,让开始吧:
C#
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.Net;
using NUnit.Framework;
namespace AutomationFramework.Engine
{
public static partial class Driver
{
public static TimeSpan TimeOut = new TimeSpan(0, 1, 0);
public static TimeSpan PollingInterval = new TimeSpan(0, 0, 2);
public static void SetImplicitTimeout(TimeSpan timeout)
{
DriverBase.Instance.Manage().Timeouts().ImplicitWait = timeout;
}
public static void SetImplicitTimeout()
{
SetImplicitTimeout(TimeOut);
}
public enum DriverType
{
InternetExplorer,
Chrome,
Edge
}
public static void Initialise(DriverType driverType, TimeSpan? implicitWait)
{
var initialiseTimeout = implicitWait ?? TimeOut;
try
{
switch (driverType)
{
case DriverType.InternetExplorer:
var internetExplorerOptions = new InternetExplorerOptions
{ IntroduceInstabilityByIgnoringProtectedModeSettings = true,
AcceptInsecureCertificates = true };
DriverBase.Instance = new InternetExplorerDriver
(TestContext.CurrentContext.TestDirectory, internetExplorerOptions));
break;
case DriverType.Edge:
var edgeExplorerOptions = new EdgeOptions { AcceptInsecureCertificates = true };
DriverBase.Instance = new EdgeDriver(TestContext.CurrentContext.TestDirectory,
edgeExplorerOptions));
break;
case DriverType.Chrome:
var chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("test-type");
chromeOptions.AddArguments("chrome.switches", "--disable.extensions");
DriverBase.Instance = new ChromeDriver
(TestContext.CurrentContext.TestDirectory, chromeOptions, implicitWait);
break;
}
}
catch (WebDriverException)
{
throw new WebDriverException($"Failed to initialise the {driverType.DescriptionAttribute()} web driver for Selenium");
}
DriverBase.Instance.Manage().Window.Maximize();
if (null != implicitWait)
{
SetImplicitTimeout((TimeSpan)implicitWait);
}
}
}
}
创建WebDriver实例的方法有很多,但在这个例子中,将通过一个switch语句来创建,该语句将在框架的另一个点接收一个参数。根据传递的参数,将创建一个特定于浏览器的WebDriver实例,并设置一些选项。但让详细分解每一段代码。
首先,应该解释一下类是一个partial类。partial关键字用于将大类分解成几个小类,分布在几个文件中,纯粹是为了可读性和保持代码整洁。但这是一个更大的类Driver的一部分。稍后将讨论其他partial类。
进入类后,得到这些几行:
public static TimeSpan TimeOut = new TimeSpan(0, 1, 0);
public static TimeSpan PollingInterval = new TimeSpan(0, 0, 2);
public static void SetImplicitTimeout(TimeSpan timeout)
{
DriverBase.Instance.Manage().Timeouts().ImplicitWait = timeout;
}
public static void SetImplicitTimeout()
{
SetImplicitTimeout(TimeOut);
}
这些是将在测试放弃等待某个动作发生之前设置的超时值,以及框架将检查可能即将超时的事件的更新频率。在测试自动化中,有两种类型的等待需要注意,显式和隐式。隐式基本上是告诉测试等待一段设定的时间,可以想象成Thread.Sleep。而显式等待则是根据某些条件告诉测试等待。
显式条件总是首选的等待方式,纯粹是因为隐式等待的累积可能会不必要地增加测试运行时间。过度使用隐式等待也被认为是懒惰的。
在这之后,为不同的Driver类型创建了一个枚举。这纯粹是偏好。可以直接将一个字符串传递给initialise方法,但传递一个枚举类型要整洁得多,也不太可能出错。
接下来是Initialise方法:
public static void Initialise(DriverType driverType, TimeSpan? implicitWait)
{
var initialiseTimeout = implicitWait ?? TimeOut;
try
{
switch (driverType)
{
case DriverType.InternetExplorer:
var internetExplorerOptions = new InternetExplorerOptions
{ IntroduceInstabilityByIgnoringProtectedModeSettings = true,
AcceptInsecureCertificates = true };
DriverBase.Instance = new InternetExplorerDriver
(TestContext.CurrentContext.TestDirectory, internetExplorerOptions));
break;
case DriverType.Chrome:
var edgeExplorerOptions = new EdgeOptions { AcceptInsecureCertificates = true };
DriverBase.Instance = new EdgeDriver
(TestContext.CurrentContext.TestDirectory, edgeExplorerOptions));
break;
case DriverType.Chrome:
var chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("test-type");
chromeOptions.AddArguments("chrome.switches", "--disable.extensions");
DriverBase.Instance = new ChromeDriver
(TestContext.CurrentContext.TestDirectory, chromeOptions, implicitWait);
break;
}
}
catch (WebDriverException)
{
throw new WebDriverException($"Failed to initialise the {driverType.DescriptionAttribute()} web driver for Selenium");
}
DriverBase.Instance.Manage().Window.Maximize();
if (null != implicitWait)
{
SetImplicitTimeout((TimeSpan)implicitWait);
}
}
这是根据传递的driverType设置将创建的Driver版本的地方。这是一个简单的switch语句,将进入并设置一个新的驱动实例并配置可能想要的任何浏览器特定选项。
这些浏览器设置是完全可选的。也不仅限于使用的那些。有很多可以使用,需要的任何设置将完全取决于测试的环境以及测试要求。可以在这里阅读更多关于浏览器特定功能及其含义的信息。
一旦设置了浏览器并进行了一些基本的异常检查以确保它已正确初始化,就对驱动实例做了一个基本的调用以最大化窗口。在这里这样做,而不是稍后,只是为了确保在甚至离开initialised方法之前,浏览器窗口就已经打开并最大化了。
值得注意的是,目前只是创建了一个本地的WebDriver实例,但总有一天,会考虑添加远程功能。