In the last chapter of Browser Factory, we learned the concept of Factory Design Pattern and we also learned the importance of hiding complexities from the test and Encapsulating logics with in the Test Automation Framework.

The Thumb Rule of Factory Design Pattern is the avoiding object initialization in the test. Take a look at the current state of the LogInTest.cs :

Notice that the initializing the object of HomePageand LoginPage are still dependent on the Test. This is against the rule of the Factory Design Pattern.

In this chapter, we will learn How to hide the Page Object Initialization within the Test Framework and How to Design Page Generator. But before that we need to understand the concept of Generics and Constraints over Generics in C#.

Generics and Constraints over Generics

What are Generics?

Generics provides us a way to create Classes/Methods/Types and many more without specifying the specific type of parameters. Parameters must be provided at the time of creating the instances. So we can say Generics are only a blueprint/template version and actual type is defined at Runtime.

So let’s first create a simple method say GetPage:

1

2

3

4

privatestaticvoidGetPage<T>()

{

}

Here as you can see, I have created a generic method Page, which will take any PageObject class as a parameter. It can be HomePage class or LoginPage or any other PageObject class. T represent Type, means any Type.

But the question is, that what type of PageObject would it return. If we are not sure of the input PageObject Class, we are not sure of the output as well. So, in this situation it is feasible to use Generic type T as an output as well.

C#

1

2

3

4

privatestaticTGetPage<T>()

{

returnT;

}

What are Constrains?

Constraints are used in Generics to restrict the types that can be substituted for type parameters. When we create a new instance of a generic type we can restrict the type parameters using constraints. Means if any code tries to instantiate your class by using a type that is not allowed by a constraint, the result is a compile-time error. These restrictions are called constraints. Constraints are specified by using the where contextual keyword.

Where Clause

In a generic type definition, the where clause is used to specify constraints on the types that can be used as arguments for a type parameter defined in a generic declaration. The where clause may also include a constructor constraint. It is possible to create an instance of a type parameter using the new operator. The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless or default constructor. For example:

C#

1

2

3

4

5

privatestaticTGetPage<T>()whereT:new()

{

varpage=newT();

returnpage;

}

If we want this method to initialize PageObjects, the code will look like this:

C#

1

2

3

4

5

6

privatestaticTGetPage<T>()whereT:new()

{

varpage=newT();

PageFactory.InitElements(driver,page);

returnpage;

}

Let’s see how the above code will get fit in to our Test Automation Framework.

Page Generator Implementation

Create a new C# class in the PageObjects folder, name it as Page. Write the implementation of the Page class.

Page Class

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

usingOnlineStore.WrapperFactory;

usingOpenQA.Selenium.Support.PageObjects;

namespaceOnlineStore.PageObjects

{

publicstaticclassPage

{

privatestaticTGetPage<T>()whereT:new()

{

varpage=newT();

PageFactory.InitElements(BrowserFactory.Driver,page);

returnpage;

}

publicstaticHomePageHome

{

get{returnGetPage<HomePage>();}

}

publicstaticLoginPageLogin

{

get{returnGetPage<LoginPage>();}

}

}

}

HomePage Page Object Class

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

usingOpenQA.Selenium;

usingOpenQA.Selenium.Support.PageObjects;

namespaceOnlineStore.PageObjects

{

publicclassHomePage

{

privateIWebDriver driver;

[FindsBy(How=How.Id,Using="account")]

[CacheLookup]

privateIWebElementMyAccount{get;set;}

publicvoidClickOnMyAccount()

{

MyAccount.Click();

}

}

}

I hope you noticed that the below code is been removed from the HomePage class. If you go to the previous chapter of Data Driven Technique, you will notice that HomePage class had the below constructor. Now the same duty is assigned to Page Generator class and it is no longer needed.

With the help of Page Generator, calling PageObjects in the Test are really easy. The intellisence will pick up all the PageObject classes and will reflect that in the Page class. Take a look at the below screenshot.

Project Solution Explorer

For more updates on Selenium Tutorial in C#, please Subscribe to our Newsletter.

Please ask any questions on ForumsQA, in case of any issues or doubts.