Click here to Skip to main content
14,175,662 members
Click here to Skip to main content
Add your own
alternative version

Stats

9.2K views
4 bookmarked
Posted 26 Feb 2017
Licenced Ms-PL

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

, 26 Feb 2017
Rate this:
Please Sign up or sign in to vote.
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.

[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.

[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.

[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);
}

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.

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.

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

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!

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.

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.

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.

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!

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)

Share

About the Author

Anton Angelov
CEO Automate The Planet
Bulgaria Bulgaria
Anton Angelov is an IT Consultant and Quality Assurance Architect at Innovative Lab. He is passionate about automation testing and designing test harness and tools, having the best industry development practices in mind. In addition, he is an active blogger and the founder of Automate The Planet. He strives to make the site one of the leading authorities in Automation Testing by presenting compelling articles, inspiring ardent discussions amongst the community. He is also one of the most-rated-answer authors of questions about Test Automation Frameworks (WebDriver) on Stack Overflow.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionLike it Pin
Member 1115704226-Feb-17 19:17
memberMember 1115704226-Feb-17 19:17 
Like it as per all your series.

I know it's not related to this article but I have not seen any article on selenium -specflow-Nunit run tests in parallel.
Do you have any planned?

thanks and great article
AnswerRe: Like it Pin
Anton Angelov26-Feb-17 20:01
memberAnton Angelov26-Feb-17 20:01 
GeneralRe: Like it Pin
Member 111570423-Mar-17 5:38
memberMember 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.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190525.1 | Last Updated 26 Feb 2017
Article Copyright 2017 by Anton Angelov
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid