Creating Tags in Silk4Net
Silk4Net introduces the use of Microsoft's Visual Studio 2008/2010 vb.NET and C# (C sharp) languages as scripting languages for use with the SilkTest Open Agent. Like Silk4J, the SilkTest Recorder captures only the raw locator strings and does not create tags in the sense that those familiar with the Classic Agent know about. For someone familiar with the C or C++ languages the obvious answer appears to be to copy the locator strings to a header file and reference the header file in the main solution. However, header files have been made obsolete in C# and were never available in vb.NET. There are three solutions to this problem and which one you chose is dependant upon company practice and to a certain extent, project size and code portability.
The first is to do nothing and live with the raw locator strings. For a single small record-and-playback testcase this would not a problem. To a degree, even adding some verification and logging statements is not going to destroy the script readability. However, as the script gets longer readability will start to suffer and when you get to writing scripts, the approach of using raw locator strings for tagging gets very clumsy and time consuming.
The second option is to place the locator strings into easily-remembered string variable names. This will improve both script construction and readability and removes the necessity to remember the names of the string variables as the Visual Studio Intellisense will kick in, presenting you with the standard dropdown selector box. These string variables can be local to the testcase or can be global to the project's TestClass. Making them global makes them available for all test scripts in that TestClass. The limitation of this approach is that it is not very good for large solutions as it would entail a lot of copying and pasting into new projects. Remember - no header files to share between projects.
For large solutions and for portability between solutions the best approach is the class library. This keeps all of the tags for a given application in a single place and makes them globally available for all solutions. Any changes made to the class library will automatically filter down all solutions as soon as that solution is rebuilt. Included with the SilkTest Sample Applications are a number of Silk4Net scripts. One of these scripts - GreenMountOutpostTest.cs - is a short script that buys a selection of items from the Green Mountain Outpost website. For a standard SilkTest installation this script can be found under:
C:\Documents and Settings\All Users\Documents\SilkTest\samples\Silk4NET\src\Silk4NET.Samples.CSharp\xBrowser
We will take this single script, create a new solution from it and use it to illustrate how to build a class library. The test solution and the class library solution are attached to this article as GMOclasslib.zip.
Before we continue, the Silk4Net .NTF (.Net Testing Framework) has a very useful trick up its sleeve in the form of locator-helpers. The .NTF API is set up so as to reference a specific object you do not have to use the entire locator eg. you can call the third table in the GMO hierarchy as:
This applies to all objects that you would normally use the .Find method to locate.
Although we will be dealing with C# in this article, the steps for both options - including building the class library - are identical in vb.NET.
The String Variable Approach
Fig. 1 below shows a simple recorded script as exported from the SilkTest Recorder into a Silk4Net project.
Fig. 1 - Raw locator strings
We need to take each unique locator string and make it part of a string variable. Fig. 2 below shows this process partly completed. Initially we are declaring all strings as local to the testcase simply because this involves less scrolling around in the test script. Note that already the Visual Studio Intellisense is picking up our string variables and offering them for use.
Fig. 2 - Partial String Conversion showing Intellisense
To make these strings global to the TestClass and, therefore, available to every script you create within this TestClass, move them up to the top of the TestClass.
Fig. 3 - Test class global Strings
Note that these strings are only global to this TestClass. If you have more than one TestClass in the same namespace you will need to copy the strings into each of those TestClasses. This is one area where the class library approach will save time and effort and reduce the probability of typographical errors.
Fig.4 Fig.4 - Replacement Tags
Compare the readability of this test script to the original raw code in fig.1.
The Class Library Approach
For large solutions and code portability the class library is definitely the way to go. Once the class library has been compiled the resulting dll can be referenced from any solution, whether written in vb.NET or in C#. In this respect the class library can be considered as the equivalent of the C/C++ header file or as the SilkTest frame file. It is also possible to structure the class library so that the resulting intellisense selections have a hierarchical structure similar to the SilkTest frame file.
To create the GMO xbrowser solution we are using here the folder:
C:\Documents and Settings\All Users\Documents\SilkTest\samples\Silk4NET\src\Silk4NET.Samples.Csharp
was copied to a new location, then deleted the \flex folder inside it. It was then started by double-clicking on the Silk4NET.Samples.CSharp.csproj icon. Once Visual Studio had started up, all the test scripts were deleted except the GreenMountOutpostTest.cs and saved as a new solution called 'GMO CSharp', finally checking that it all still worked. Do not delete the BrowserType.cs - this is not a test script!
Once that was done, a new Visual Studio project was started in order to create our class library. Creating a class file is a simple process. The following screenshots are taken from Microsoft's Visual Studio 2010 but the process is the same in Visual Studio 2008. In Visual Studio close any existing projects and solutions, then select:
File > New > New Project
From the New Project dialog select:
Visual C# > Windows > Class library
and fill in the Name textfield. Change the Solution name if required and click OK.
Fig. 4 - Starting a new Class Library project
This will give a new blank class structure named, in this case, GMOtags. The full source code for the GMOtags class library can be found in the GMOClassLib.zip archive.
Fig. 5 - The blank class library template
At this point you will need to sit back, study your application under test very carefully and decide just how you want to structure the class library. For the modified GMO xbrowser test Iit was decided to build the classes based on the window types ie. button, listview, checkbox, table etc. Taking this approach allowed the building of classes within classes (these are not sub-classes - that is an entirely different thing) which in the case of tables meant that Intellisense could go down through the table-row-cell tree.
The obvious objects to change first were the many pushbuttons in the xbrowser script. 'Class1' was renamed to 'Buttons' and the following list: was added:
public class Button
public const string Enter="@value='Enter GMO OnLine'";
public const string PlaceAnOrder="@value='Place An Order'";
public const string Proceed="@value='Proceed With Order'";
public const string PlaceTheOrder="@value='Place The Order'";
public const string Home = "@value='Return to Home Page'";
Please note that all variables in the classes have to be 'public const' for two reasons: 'public' means that they will be available for all projects that reference the final dll and 'const' to ensure that the variable cannot be accidently overwritten by any code further down in the class library. In this case that is not likely to happen as there are no additional class libraries but it is better to start with security than to find it all fails later.
Once you have the first couple of objects in the class, it would be a good idea to compile the project and ensure that the test scripts are able to see the resulting dll. In Visual Studio go to Build > Build Solution and ensure that no compile errors are returned. If you now go to the Solution Explorer and expand the bin folder, you should see your new class library dll:
Fig. 6 - The compiled dll in the class library
If it is not in the Debug folder, check the Release folder.
A reference from the xbrowser project to the new dll now needs to be created. In the test project Solution Explorer right click on the References folder and select Add Reference.
Fig. 7 - Add Reference to the test solution
From the dialog box that now comes up select the Browse tab and navigate to where the class library dll was placed. Select the dll and click OK. The class library will now appear in the test project Solution Explorer view.
Fig. 8 - The dll referenced in the test solution
To invoke the class library you will need to trigger the Intellisense by starting with the namespace title. If you refer to fig. 5 you will see that the namespace for the GMOtags solution is just 'GMO'. To enter the Green Mountain Outpost we need to select the 'Enter' button on the homepage. Under xbrowser terminology this is a DomButton, so if we begin typing:
as soon as we reach the full stop the Intellisense will present a list of selections if the class library is both compiled and referenced correctly.
Fig. 9 - The referenced dll is responding
From this screenshot you can see the other available classes in the GMOTags class library. If we now select the Button class, we should get a list of available buttons.
Fig. 10 - Button name selection
Once you know that your class library is responding correctly then you can go back and begin adding to it. As is shown in fig. 10 the GMOtags class library contains classes for buttons, checkboxes, dialog boxes, listboxes, tables and textfields. All except the table class are implemented as individual classes within the library eg.
public class TextField
public const string QtyTents="@name='QTY_TENTS'";
public const string QtySocks="@name='QTY_SOCKS'";
public const string Name="@name='billName'";
public const string Address="@name='billAddress'";
public const string City="@name='billCity'";
public const string State="@name='billState'";
public const string Zipcode="@name='billZipCode'";
public const string Phone="@name='billPhone'";
public const string Email="@name='billEmail'";
public const string CardNo="@name='CardNumber'";
public const string CardDate="@name='CardDate'";
public class ChkBox
public const string SameAsBill="@name='shipSameAsBill'";
public class ListBox
public const string CardType="@name='Cardtype'";
Depending on how you want to structure your Table class, there are three possible ways of doing it. There is the 'mininum' structure where everything is placed under one class and any locator that references the same object (eg. a row or cell number) is used in multiple places. This creates the smallest amount of code but is the most difficult to read. Consider the following:
Fig. 11 - Table class method 1
Both the 'Grand Total' and 'Shipping & Handling' rows have a cell that is called 'Cost'. In both cases Cost has the same cell identifier (cell 2), so we only need one Cell declaration for Cost. The following sequence shows what happens when we want to add the Cost tag to the script as part of an Assert (verify) statement:
Fig. 12 - Tablecell hierarchy selection
However, under other circumstances (for example where you have more than one cell called 'Cost' but each has a different cell number) it would be better to declare each table and its row and cell children as an individual table class. This will also allow you to specifically name a class by the name of the table, thus improving readability in the Intellisense selection. Overall, this method is probably the best of the three.
Fig. 13 - Table class method 2
Finally, there is nothing to prevent you from creating a completely flat hierarchy where table, row and cell all occupy different classes. However, you will need individual names for each object. Again, this is illustrated in the source code for GMOTags.
Fig. 14 - Table class method 3
So far we have dealt exclusively with an object-based class library (buttons, textboxes, listviews, etc.) as this will tend to give the shortest access to any given object. It is also possible to build a 'page-based' class library that will more closely resemble the old SilkTest classic agent frame file.
Fig. 15 - Frame file type hierarchy
The useful thing about class libraries is that you can have multiple objects with the same name as long as they are within different classes. This is similar to the Classic Agent frame file where multiple child windows can have the same name as long as they had a different parent. In the above screenshot we have two item hyperlinks which also appear on the GMO Online Catalog page.
Fig. 16 - Frame file type selection
If (or when) your class library is updated, to ensure that the new classes are available to your current project(s), all you need to do is to rebuild the current project(s). The class library can be copied/moved to a central location available to all testers as Visual Studio is capable of reading files across a network. This may be a more acceptable alternative to leaving the class library with its source code as it reduces the possibility of accidental changes.
To use the attached archives, simply unzip them to a convenient location and doubleclick the .sln file.