65.9K
CodeProject 正在变化。 阅读更多。
Home

在 WebDriver 测试中使用全新 C# 7.0 的 5 大理由

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (8投票s)

2017年2月26日

Ms-PL

3分钟阅读

viewsIcon

13537

学习如何使用全新的 C# 7.0 来改进你的 WebDriver 测试。利用本地函数、数字分隔符等强大功能。

我相信你需要不断尝试最新的技术才能在你的工作中做到最好。正如我在上一篇文章 通过全新改进的 C# 6.0 增强 Selenium WebDriver 测试 中承诺的那样,现在我将与你分享如何利用全新的 C# 7.0 的强大功能。 我不会涵盖所有功能,因为我不喜欢其中的一些功能,或者我不知道如何在测试中使用它们。 你可以在我的 WebDriver 系列 中找到更多关于自动化测试的酷技巧。

快速导航

数字分隔符

C# 7.0 之前

很多时候我们在代码中使用数字字面量。 由于有很多零,我很难区分超时的值是多少。

[TestInitialize]
public void SetupTest()
{
    driver = new FirefoxDriver();
    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(30000);
}

在我们的测试中使用数字的另一个例子是当我们传递期望的值时。

[TestMethod]
public void SearchTextInBing_First()
{
    var bingMainPage = new BingMainPage(driver);
    bingMainPage.Navigate();
    bingMainPage.Search("Automate The Planet");
    bingMainPage.AssertResultsCount(236000);
}

C# 7.0 版本

你可以在数字之间放置任何你想要的数字分隔符 _ ,以提高可读性。 它们对值没有影响。

[TestInitialize]
public void SetupTest()
{
    driver = new FirefoxDriver();
    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30_000);
}
[TestMethod]
public void SearchTextInBing_First()
{
    var bingMainPage = new BingMainPage(driver);
    bingMainPage.Navigate();
    bingMainPage.Search("Automate The Planet");
    bingMainPage.AssertResultsCount(236_000);
}

本地函数

C# 7.0 之前

很多时候,我们创建 private 方法,这些方法只是在我们的类中的单个方法中调用,以便我们可以提高可读性。 但是,当类太长时,你需要在不同的方法之间来回跳转才能获得全局视图。 在示例中,我们将采购订单对象传递给 private 方法,以便以正确的方式格式化期望的值。

public partial class ShippingAddressPage
{
    public void AssertPurchaseOrders(List<PurchaseOrder> purchaseOrders)
    {
        for (int i = 0; i < purchaseOrders.Count; i++)
        {
            Assert.AreEqual(GetFormattedPurchaseOrder(purchaseOrders[i]), PurchaseOrderRows[i].Text);
        }
    }

    private string GetFormattedPurchaseOrder(PurchaseOrder purchaseOrder)
    {
        return $"Your product: {purchaseOrder.ProductName} costs {purchaseOrder.Price}";
    }
}

C# 7.0 版本

现在我们可以声明只能在当前块范围(例如,当前方法)中使用的方法。 前面的 private 方法现在是 Assert 的一部分。 我认为这种改进使 Assert 更具可读性。

public partial class ShippingAddressPage
{
    public void AssertPurchaseOrders(List<PurchaseOrder> purchaseOrders)
    {
        string GetFormattedPurchaseOrder(PurchaseOrder purchaseOrder) => 
            $"Your product: {purchaseOrder.ProductName} costs {purchaseOrder.Price}";
        for (int i = 0; i < purchaseOrders.Count; i++)
        {
            Assert.AreEqual(GetFormattedPurchaseOrder(purchaseOrders[i]), PurchaseOrderRows[i].Text);
        }
    }
}

扩展的表达式体构造函数

C# 7.0 之前

public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;

    public ShippingAddressPage(IWebDriver browser)
    {
        this.driver = browser;
    }

    // some other actions
}

C# 7.0 版本

如果页面的构造函数如此简单,我们可以将其转换为只有一行而不是三行!

public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;
    public ShippingAddressPage(IWebDriver driver) => this.driver = driver;

    // some other actions
}

扩展的表达式体属性

C# 7.0 之前

有时,不返回整个元素而是使元素的属性类型为 string 更有意义。 这样,你只能分配和获取值。 这可以提高 API 的可用性(所有其他 WebDriver 的属性和方法都受到限制)。 这里的缺点是你需要为每个 getter 和 setter 提供八行代码。

public partial class ShippingAddressPage
{
    public string Country
    {
        get
        {
            return new SelectElement
            (driver.FindElement(By.Name("enterAddressCountryCode"))).SelectedOption.Text;
        }
        set
        {
            new SelectElement(driver.FindElement
             (By.Name("enterAddressCountryCode"))).SelectByText(value);
        }
    }

    public string FullName
    {
        get
        {
            return driver.FindElement(By.Id("enterAddressFullName")).Text;
        }
        set
        {
            driver.FindElement(By.Id("enterAddressFullName")).SendKeys(value);
        }
    }

    // other elements
}

C# 7.0 版本

现在,你可以将扩展的表达式体用于 getter 和 setter。 我们将代码从八行减少到只有两行。

public partial class ShippingAddressPage
{
    public string Country
    {
        get => new SelectElement(driver.FindElement
        (By.Name("enterAddressCountryCode"))).SelectedOption.Text;
        set => new SelectElement(driver.FindElement
        (By.Name("enterAddressCountryCode"))).SelectByText(value);
    }

    public string FullName
    {
        get => driver.FindElement(By.Id("enterAddressFullName")).Text;
        set => driver.FindElement(By.Id("enterAddressFullName")).SendKeys(value);
    }
}

Throw 表达式

C# 7.0 之前

我们需要保护我们的代码(方法/构造函数)。 我认为测试代码是生产代码,所以应该像对待生产代码一样对待它。 在这里,如果驱动程序是 null,我们会抛出一个异常。

public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;

    public ShippingAddressPage(IWebDriver driver)
    {
        if (driver == null)
        {
            throw new ArgumentNullException(nameof(driver));
        }
        this.driver = driver;
    }
}

C# 7.0 版本

现在你可以在构造函数的扩展表达式体中抛出一个异常。 使用新的语法,我们节省了七行!

public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;
    public ShippingAddressPage(IWebDriver driver) => 
      this.driver = driver ?? throw new ArgumentNullException(nameof(driver));
}

到目前为止,'使用 WebDriver 进行务实的自动化' 系列

参考文献

文章 在 WebDriver 测试中使用全新 C# 7.0 的 5 大理由 首次出现在 Automate The Planet 上。

© . All rights reserved.