Collection and Generics-Part 1(Arrays and Generics)


In our automation project, we would come across scenarios where we need to deal with a group of items, some examples below
  1. We got employee data from the application, which contains 20+ records and we need to check if a specific employee exists or not
  2. We need test data for testing application, say 20 records of the employee (employee name, Id, Address etc).
And Many more...

Well, you will say, One can use Arrays to deal with a group of items.
You are right.

One can manage a group of items/objects using arrays or collections, we will take look at both in this lecture

Arrays

Arrays are fixed size list of elements that can be accessed using a positional index number.
Arrays are used mostly when the size of the list is known at design time.

We will look at some array operations

Array Declaration 


//Declaration
string[] EmpName;


Here we have declared EmpName Array which will have string elements

Array Initialization

//Initializing Array
EmpName = new string[4];

Here we are initializing array and setting is the size to 4, which means it can hold 4 string elements

Adding Data to Array

//Populating an Array
            EmpName[0] = "Employee1";
            EmpName[1] = "Employee2";

Arrays are zero indexed based, so in our case index values are 0,1,2,3.
We have added elements at 0th and 1st index.

All in one Array Declaration and Initialization 

string[] Emp = new string[] { "Employee1", "Employee2" };

Here it will declare the array and add 2 elements to it.

Iterating an Array

foreach (var item in Emp)
           {
               Console.WriteLine($"Employee is {item}");
 
           }

Here we are iterating an array and printing elements on the console.
Note- For each block is read-only so we cannot change the item value.

That's all for arrays.
Before we talk about collections, let's spend some time to understand generics

Generics

Using Generics allows us to design our classes and methods that defer the specification of one or more types until the classes or method is declared and instantiated by client code.

In simple words, write code without specifying data types which makes our code more generic.

So why would automation tester need to know generics or show me where can I use generics in automation code?

In your automation project, if you are using the page object model design pattern, you can use generics to instantiate page classes in your tests.

In the Page object model, we create separate classes for each page in our application and our tests then use the methods of the page classes.

Below code shows, we have defined Page class called LoginPage, which inherits from the BasePage class. We have also added some methods in the LoginPage class.

public class BasePage
    {
        public BasePage()
        {
            Console.WriteLine("Base page constructor");
                        
        }
   
        //Add Base Page Methods Here     
    }
 
    public class LoginPage:BasePage
    {
        public LoginPage()
        {
            Console.WriteLine("Login page constructor");
        }
   
        //Login Page Methods
        public void Login(string userName,string password)
        {
            Console.WriteLine($"Logging using {userName} and {password}");
        }
        
        public void DoWork()
        {
            Console.WriteLine("Do Work Method Called");
 
        }
    }

 Now say in our tests, we can call LoginPage methods

LoginPage loginPage = new LoginPage();
loginPage.Login("TestUser", "TestPassword");

Well, that's ok however imagine we are having 50+ pages and their respective classes in our project and every time someone wants to access the method of page class, he needs to instantiate the class and then call the respective methods.

Below is a smarter solution using generics

We will add another class that will take care of  creating and providing page class instances to our tests

public static class AutomationMain
   {
       public static class PageFactory<T> where T : BasePage, new()
       {
           private static T _page;
           public static T Instance
           {
               get
               {
                   if (_page == null)
                       _page = new T();
 
                   return _page;
 
               }
           }
       }
 
   }

Here T is a generic type parameter, which can be of type BasePage or its child.
In our above example, LoginPage is inheriting from BasePage.

We have an inner class called PageFactory which takes generic parameter T, it returns an instance of T.

That's it. We are good so far.

PageFactory<T>.Instance is generic and will help to give an instance of BasePage or its child type.

Generics are type safe, means, in our above code if T is not of BasePage type then it will give compile time error.

In our tests, we can get rid of creating an instance of the page class.
The final test will look like something below

AutomationMain.PageFactory<LoginPage>.Instance.Login("TestUser", "TestPassword");
AutomationMain.PageFactory<LoginPage>.Instance.DoWork();

Looks cleaner 👌

Below are some advantages of using generics
  1. Maximize code reuse.
  2. Type safety
  3. Performance
There are many scenarios where we can use Generics, we have covered one such example here.
The most common use of generics is to create collection classes, we will cover this in coming lectures.




Comments

Popular posts from this blog

Specflow -Part3(Working with tables using Specflow.Assist.Dynamic)

Specflow -Part4(Specflow Scenario Outline and Feature Background )

Specflow -Part6(Specflow Hooks)