Click here to Skip to main content
15,881,821 members
Articles / DevOps / Testing

5 Reasons You Should Use the Brand-New C# 7.0 in Your WebDriver Tests

Rate me:
Please Sign up or sign in to vote.
4.88/5 (8 votes)
26 Feb 2017Ms-PL3 min read 12.5K   4   3
Learn how to use the brand-new C# 7.0 to make your WebDriver tests even better. Utilise the power of local functions, digit separators and much more.

I believe that you need to always play with the latest technologies to be great in what you are doing. As I promised in my last article Enhanced Selenium WebDriver Tests with the New Improved C# 6.0, now I am going to share with you how you can utilize the power of the brand-new C# 7.0. I am not going to cover all of the features because I don't like some of them or I don't see how we can use them in the tests. You can find even more cool tips and tricks about automated testing in my WebDriver Series.

Quick Navigation

Digit Separator

Prior C# 7.0

There are lots of times where we use number literals in our code. Because of the many zeroes for me, it is hard to distinguish what is the value of the timeout.

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

Another example when we use digits in our tests is when we pass expected values.

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

C# 7.0 Version

You can put digit separator _ wherever you want between digits, to improve readability. They have no effect on the value.

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

Local Functions

Prior C# 7.0

There are many times when we create private methods that are just called in a single method in our class so that we can improve the readability. However, when the class is too long, you need to jump back and forth between different methods to get the big picture. In the example, we pass the purchase order objects to the private method so that the expected values are formatted in the proper way.

C#
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 Version

Now we can declare methods that can be used only in the current block scope (e.g. current method). The previous private method now is part of the Assert. I think this improvement makes the Assert much more readable.

C#
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);
        }
    }
}

Extended Expression Bodied Constructor

Prior C# 7.0

C#
public partial class ShippingAddressPage
{
    private readonly IWebDriver driver;

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

    // some other actions
}

C# 7.0 Version

If the constructor of the page is so simple, we can convert it to just a single line instead of three!

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

    // some other actions
}

Extended Expression Bodied Properties

Prior C# 7.0

Sometimes, it can make sense not to return the whole element instead to make the element's property of type string. This way, you can only assign and get values. This can improve the API usability (all other WebDriver's properties and methods are restricted). The drawback here is that you need eight lines of code for each getter and setter.

C#
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 Version

Now, you can use extended bodied expressions for both the getters and the setters. We reduced the code from eight lines to just two.

C#
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 Expressions

Prior C# 7.0

We need to guard our code (methods/constructors). I believe that test code is a production code so it should be treated like such. Here, if the driver is null, we throw an exception.

C#
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 Version

Now you can throw an exception inside the constructor's extended bodied expression. With the new syntax, we saved seven lines!

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

So Far in the 'Pragmatic Automation with WebDriver' Series

References

The post 5 Reasons You Should Use the Brand-New C# 7.0 in Your WebDriver Tests appeared first on Automate The Planet.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
CEO Automate The Planet
Bulgaria Bulgaria
CTO and Co-founder of Automate The Planet Ltd, inventor of BELLATRIX Test Automation Framework, author of "Design Patterns for High-Quality Automated Tests: High-Quality Test Attributes and Best Practices" in C# and Java. Nowadays, he leads a team of passionate engineers helping companies succeed with their test automation. Additionally, he consults companies and leads automated testing trainings, writes books, and gives conference talks. You can find him on LinkedIn every day.

Comments and Discussions

 
QuestionLike it Pin
Member 1115704226-Feb-17 19:17
Member 1115704226-Feb-17 19:17 
AnswerRe: Like it Pin
Anton Angelov26-Feb-17 20:01
Anton Angelov26-Feb-17 20:01 
Sure. I have something even better. My team and I have developed a new tool on top of NUnit- Distributed NUnit. Specifically designed to execute tests in parallel (distributed on multiple remote machines). It has tonnes of other features too. I am waiting for my company's approval to publish it as open source. Once this is done, I will write an article about it. Smile | :)
GeneralRe: Like it Pin
Member 111570423-Mar-17 5:38
Member 111570423-Mar-17 5:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.