An example of using delegates in C#

 

Delegates hold the references/addresses of functions so that the functions can be invoked in a call back manner. If you are familiar with C++, they are just like function pointers. Here is one example of how delegates can aid in structuring your test cases.

 

Objective

 

Let us say that you have developed a text editor called Editor+ which is the next version of already developed application called Editor. Now your goal is to test backward compatibility, i.e. Editor+ should be able to open and modify files that were created using Editor.

 

To achieve this goal, we need to perform the following 2 tasks:

 

Task 1 : Have a repository called Version 1 Files, which will contain files that were created using

            Editor.

Task 2 : Make an application that will:

a.       open each file in this repository

b.       make different kinds of modifications to the contents

c.       save and close the file.

 

So, you have a set of input, which is constant. But each test case needs to perform a different action on this set.

 

Performing Task 1

 

Making the repository is a 1 time job. You can either do it manually or make it using some tools.

 

Performing Task 2

 

The application will comprise of mainly 2 components.

 

1.       A generic class called Reader which will implement the logic of opening each file from the repository, perform the required set of modification, save and close the file.

2.       Test cases which use the Reader class and implement the actual set of modification as per their requirement. Example of a few test cases could be like the following:

TestCase1: Add letter “x” in the beginning of each file in Version 1 Files using Editor+

TestCase2: Delete the last line in each file in Version 1 Files using Editor+

 

Reader class

 

Let us define a class called Reader, which can do the following:

 

·         Provide a function which can recursively look at each file in repository Version 1 Files

·         Open the file

·         Modify the file according to the user’s request

·         Close the file

 

Here is the pseudo code implementation of such a function in Reader class

 

Function WorkOnFiles (“Version 1 Files”)

{

     For each file in directory “Version 1 Files

     {

           Open (File)

           Modify (File)

           Close (File)

     }
}

 

The logic of opening and closing each file will be the same for all the files and can be left to the Reader class. But the challenge comes in handling the Modify function since each test case wants to modify the files in a different way. Like the first case wants to “add ‘x’ at the beginning of the file” whereas the other wants to “delete the last line” in the each file.

 

Using delegates we can handle such a situation. You just need to define the “Modify” function as a delegate in Reader class so that each test case can initialize this with its own implementation of modify function. Just add the following lines in your Reader class.

 

/// <summary>

/// Delegate that defines the function which will be used to

/// “Make Changes” to a document

/// </summary>

/// <param name="filehandle">The file handle</param>

/// <returns>success/failure</returns>       

public delegate bool modify(Object fileHandle);

 

private modify modifyFunction;

 

/// <summary>

/// Get/Set actions for ModifyFunction so that the test case can call it

/// </summary>

public modify ModifyFunction

{

get {return modifyFunction;}

set { modifyFunction = value;}

}

 

With the introduction of delegate, the WorkOnFiles function in the Reader class will look like the following.

 

public bool WorkOnFiles(string directoryName)

{

     bool result true;

    

     DirectoryInfo info = new DirectoryInfo(directoryName);

     FileInfo[] files = info.GetFiles();

                 

     foreach(FileInfo file in files)

     {

         //Open the file

   object fileHandle = OpenFile(file.Name);

 

         //Do error handling for the returned file handle

         //object        

           

   //Call the function specified by the test case that makes

   //changes to the file

         result &= ModifyFunction(fileHandle);

            

         //Call the function that closes the file

         CloseFile(fileHandle);

     } 

 

         

 

          return result;

}

 

Test Case logic

 

Your test case can now provide its own customized Modify function according to its need. Here is how your test cases would initialize the Reader class and use it.

 

/// <summary>

/// Test case which goes thru each file in a directory,

/// opens each file, adds 'x' in the beginning of the file,

/// saves and closes.

/// </summary>       

public result TestCase1 ()

{

      Reader myReader = new Reader ();

 

      //The function which will add 'x' at the beginning

      myReader.ModifyFunction = MyAddX;       

 

      ...

 

      //Call the function which will recursively open, modify and

      //close the files

      myReader.WorkOnFiles(“Version 1 Files”);

 

      ...

 

/// <summary>

/// Test case which goes thru each file in a directory,

/// opens each file, deletes the last line of the file,

/// saves and closes.

/// </summary>   

public result TestCase2 ()

{

      Reader myReader = new Reader ();

 

      //The function which will delete the last line

      myReader.ModifyFunction = MyDeleteLastLine;  

 

      ...

 

      //Call the function which will recursively open, modify and

      // close the files

      myReader.WorkOnFiles(“Version 1 Files”);

 

      ...

}

/// <summary>

/// Sample MyAddX function

/// </summary>   

public bool MyAddX (object fileHandle)

{

       bool result = true;

       …

       return result;
}

/// <summary>

/// Sample MyDeleteLastLine function

/// </summary>   

public bool MyDeleteLastLine (object fileHandle)

{

       bool result = true;

       …

       return result;
}

(This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm)