Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Create Multiple Files Page Objects with Visual Studio Item Templates

5.00/5 (2 votes)
21 Jan 2017Ms-PL3 min read 6.4K  
Create item template for generating multiple files page objects consisting of separate files for the element maps, page's logic and the asserts.

In my last article Standardize Page Objects with Visual Studio Item TemplatesI showed you how to generate Visual Studio item templates so that you can create predefined page objects' classes with a few clicks. However, I don't think that the standard page objects' classes are the best ones. In my article Page Objects That Make Code More Maintainable I explain how to create more maintainable tests using partial classes to separate the page objects' responsibilities- logic, maps and asserts. So you cannot use the single file item templates to generate these. In this publication, I will explain to you how to modify the standard template so that three files to be generated.

What Problem We Are Trying to Solve?

Regular Page Objects

Below you can find the code of the regular page object used by most people.

public class BingMainPage
{
    private readonly IWebDriver driver;
    private readonly string url = @"http://www.bing.com/";

    public BingMainPage(IWebDriver browser)
    {
        this.driver = browser;
        PageFactory.InitElements(browser, this);
    }

    [FindsBy(How = How.Id, Using = "sb_form_q")]
    public IWebElement SearchBox { get; set; }

    [FindsBy(How = How.Id, Using = "sb_form_go")]
    public IWebElement GoButton { get; set; }

    [FindsBy(How = How.Id, Using = "b_tween")]
    public IWebElement ResultsCountDiv { get; set; }

    public void Navigate()
    {
        this.driver.Navigate().GoToUrl(this.url);            
    }

    public void Search(string textToType)
    {
        this.SearchBox.Clear();
        this.SearchBox.SendKeys(textToType);
        this.GoButton.Click();
    }

    public void ValidateResultsCount(string expectedCount)
    {
        Assert.IsTrue(this.ResultsCountDiv.Text.Contains(expectedCount), "The results DIV doesn't contains the specified text.");
    }
}

More Maintainable Page Objects

This is the class that contains the primary logic that can be executed on the page.

public partial class BingMainPage : BasePage
{
    public BingMainPage(IWebDriver driver) : base(driver)
    {
    }

    public override string Url
    {
        get
        {
            return @"http://www.bing.com/";
        }
    }

    public void Search(string textToType)
    {
        this.SearchBox.Clear();
        this.SearchBox.SendKeys(textToType);
        this.GoButton.Click();
    }
    
    public int GetResultsCount()
    {
        int resultsCount = default(int);
        resultsCount = int.Parse(this.ResultsCountDiv.Text);
        return resultsCount;
    }
}    

Тhis partial class consists only of the elements of the page.

>
public partial class BingMainPage : BasePage
{
    public IWebElement SearchBox
    {
        get
        {
            return this.driver.FindElement(By.Id("sb_form_q"));
        }
    }

    public IWebElement GoButton
    {
        get
        {
            return this.driver.FindElement(By.Id("sb_form_go"));
        }
    }

    public IWebElement ResultsCountDiv
    {
        get
        {
            return this.driver.FindElement(By.Id("b_tween"));
        }
    }
}

I modified thе class a little bit compared to the version presented in my article- Page Objects That Make Code More Maintainable. Now the class is not static, and the methods are not implemented as extension methods on the page itself. Rather this class as the other two is now partial and the methods are not static. This means that you don't have to pass the page as a parameter since you can access the elements directly.

Current Version

public partial class BingMainPage
{
    public void AssertResultsCountIsAsExpected(int expectedCount)
    {
        Assert.AreEqual(this.ResultsCountDiv.Text, expectedCount, "The results count is not as expected.");
    }
}

Previous Version

public static class BingMainPageAsserter
{
    public static void AssertResultsCountIsAsExpected(this BingMainPage page, int expectedCount)
    {
        Assert.AreEqual(page.ResultsCountDiv.Text, expectedCount, "The results count is not as expected.");
    }
}

These are the three classes (files) that we want to generate with a single item template.

Create Multiple Files Item Template

1. Generate single item template. Follow the steps described in my previous article- Standardize Page Objects with Visual Studio Item Templates

2. Open the folder where the template is located. The default location is- ..Users/<username>/Documents/Visual Studio <Version>/My Exported Templates/

3. Unzip the template file

Extracted Item Template Folder

This is the code of the auto-generated template.

<vstemplate type="Item" version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <templatedata>
    <defaultname>SystemTestingFrameworkPage.cs</defaultname>
    <name>SystemTestingFrameworkPage</name>
    <description>Creates system testing framework's page, element map and asserter</description>
    <projecttype>CSharp</projecttype>
    <sortorder>10</sortorder>
    <icon>__TemplateIcon.png</icon>
    <previewimage>__PreviewImage.png</previewimage>
  </templatedata>
  <templatecontent>
    <references>
    <projectitem replaceparameters="true" subtype="" targetfilename="$fileinputname$.cs">TestPage.cs</projectitem>
  </references></templatecontent>
</vstemplate>    

4. Next, you need to create clean file templates for the page, map and the asserter.

Page Clean File Item Template

// <copyright company="Automate The Planet Ltd." file="$safeitemname$.cs">
// Copyright 2016 Automate The Planet Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// <author>Anton Angelov</author>
// <site>http://automatetheplanet.com/</site>

using System;
using OpenQA.Selenium;

namespace $rootnamespace$
{
	public partial class $safeitemname$
	{
		private IWebDriver driver;
		 
        public $safeitemname$(IWebDriver driver) : base(driver)
		{
			this.asserter = asserter;
        }
	
		public void SampleAction()
        {
        }
    }
}

Page Element Map Clean File Item Template

// <copyright company="Automate The Planet Ltd." file="$safeitemname$.Map.cs">
// Copyright 2016 Automate The Planet Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// <author>Anton Angelov</author>
// <site>http://automatetheplanet.com/</site>

using OpenQA.Selenium;

namespace $rootnamespace$
{
	public partial class $safeitemname$
    {
		 /*
        public IWebElement SuccessMessage
        {
            get
            {
                return this.driver.FindElement(By.Id("lblSuccessMessage"));
            }
        }
		*/
	}
}

Page Asserter Clean File Item Template

// <copyright company="Automate The Planet Ltd." file="$safeitemname$.Asserter.cs">
// Copyright 2016 Automate The Planet Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
// <author>Anton Angelov</author>
// <site>http://automatetheplanet.com/</site>

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace $rootnamespace$
{
	public partial class $safeitemname$
	{
		public void AssertSomething()
		{
			Assert.IsTrue(true);
		}
	}
}

The $safeitemname$ will be replaced by the name you specify in the new item window. $rootnamespace$ will be determined by the current folder structure where you place the new file.

5. Copy the three new clean file templates to the template's extracted folder.

Copy Three Files Page Objects

6. Add two new project items to the template pointing the element map and the asserter. The final template should look like the code below.

<vstemplate type="Item" version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <templatedata>
    <defaultname>SystemTestingFrameworkPage.cs</defaultname>
    <name>SystemTestingFrameworkPage</name>
    <description>Creates system testing framework's page, element map and asserter</description>
    <projecttype>CSharp</projecttype>
    <sortorder>10</sortorder>
    <icon>__TemplateIcon.png</icon>
    <previewimage>__PreviewImage.png</previewimage>
  </templatedata>
  <templatecontent>
    <references>
    <projectitem replaceparameters="true" subtype="" targetfilename="$fileinputname$.cs">TestPage.cs</projectitem>
	 <projectitem replaceparameters="true" subtype="" targetfilename="$fileinputname$.Map.cs">TestPage.Map.cs</projectitem>
	<projectitem replaceparameters="true" subtype="" targetfilename="$fileinputname$.Asserter.cs">TestPage.Asserter.cs</projectitem>
  </references></templatecontent>
</vstemplate>

7. Create a zip with all of the template's files

Create Multiple Files Page Objects

After you follow the import steps from my previous article, you will be able to use the modified template.

Add New Multiple Files Page Objects

Three files are generated with file names corresponding to the specified name in the new items' window.

Generated Page Objects

Download the Page Object Item Template

Automation Tools Series

The post Create Multiple Files Page Objects with Visual Studio Item Templates 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)