In Part 1a, I mentioned that the Test Editor had 3 inputs and 1 output for a given application under test (AUT). Let me explain using code. This is how I load Test Editor,
private void Form1_Load(object sender, EventArgs e)
{
library1.ActualRootPath = @"c:\TestEditor";
var keywordPath = library1.ActualRootPath + @"\keywords\";
var testsPath = library1.ActualRootPath + @"\Tests\";
var resourcesPath = library1.ActualRootPath + @"\Resources\";
library1.LoadTestCategories(testsPath);
library1.Grid.TestRootActual = testsPath;
library1.Grid.LoadKeywords(keywordPath);
}
Test Editor is a blank form that contains 1 user control, library1. This control contains standard controls such as Treeview, ListView, DatagridView as well as another custom control, which is the Grid where you edit test steps and add keywords. So this could be used standalone, if required.
The first thing I do is tell TestEditor where the physical root path for my application(s) assets are stored. This path maps to the “All Plans” root node in the Test Categories treeview in Test Editor. So all tests within sub-folders of the root path are loaded into Test Editor.
Next, I specify the locations for the 3 inputs. These are currently hard-coded, but I will move it all out into config files. Then I won’t be forced to store multiple application assets under the root path. It is highly likely that you would want to work with multiple application test files that are stored in various locations. For example, API tests will not be stored in the same place as QTP tests, but you may wish to create a test that uses keywords from both frameworks.
Finally we populate the Tree with test categories and load the Grid with keywords, filtered by Application. I’ll discuss Resources in a bit, when we talk about keyword files.
Tests
When you select a test category in the tree the tests that belong to that category are displayed in the list. When you select a test in the list, Test Editor will work out where the test lives and will de-serialise the test file, which has a .test extension. Or in simpler terms, it will load the .test file into the Grid. The test is de-serialisedinto a Test object that has these properties,
public string Name { get; set; }
public string Author { get; set; }
public string Description { get; set; }
public string Path { get; set; }
public List<TestStep> Steps { get; set; }
Pretty basic. A TestStep is another object that a test may have many of. It is also basic and contains only a few properties,
public int Index { get; set; }
public int LoopCount { get; set; }
public string Engine { get; set; }
public Keyword Action { get; set; }
A test step only has 1 keyword,
public string Name { get; set; }
public List<KeywordParameter> Parameters { get; set; }
Name is the name of the VBScript method and the keyword may contain many parameters.
So to load tests I de-serialise the test into a Test object that is then bound to the Grid. To save a test I serialise the Test object into a .test file. The Test object will be created on the fly using whatever data currently exists in the Grid.
Keywords
Clearly without keywords you cannot have tests. Keyword files are .xml files that may look something like this,
<?xml version="1.0"?>
<Keyword>
<Name>flight_AddOrder</Name>
<Description>Adds order successfully</Description>
<ReturnValue>None</ReturnValue>
<Category>OR</Category>
<Param>
<Name>Date (Format: mm/dd/yy)</Name>
<Description>Date of Flight</Description>
<type>String</type>
<defaultValues>today+1</defaultValues>
</Param>
<Param>
<Name>FlyFrom</Name>
<Description>Fly From</Description>
<type>List</type>
<defaultValues>Denver, Frankfurt, London, Los Angeles,
Paris, Portland, San Francisco, Seattle, Sydney, Zurich
</defaultValues>
</Param>
<Param>
<Name>FlyTo</Name>
<Description>Fly To</Description>
<type>List</type>
<defaultValues>Denver, Frankfurt, London, Los Angeles,
Paris, Portland, San Francisco, Seattle, Sydney, Zurich
</defaultValues>
</Param>
<Param>
<Name>Flights</Name>
<Description>Flights</Description>
<type>String</type>
<defaultValues>1</defaultValues>
</Param>
<Param>
<Name>Name</Name>
<Description>Name</Description>
<type>String</type>
<defaultValues>Shawn Barrett</defaultValues>
</Param>
<Param>
<Name>Tickets</Name>
<Description>Tickets</Description>
<type>Integer</type>
<defaultValues>1</defaultValues>
</Param>
<Param>
<Name>Class</Name>
<Description>Class</Description>
<type>List</type>
<defaultValues>First, Business, Economy</defaultValues>
</Param>
</Keyword>
A very basic schema.
- Name: is the VBScript method name.
- Description: This is displayed as a tooltip when the keyword is added to the Grid
- Type: This tells the Grid what kind of control to add to the cell in the DataGrid when added to the Grid.
- DefaultValues: This functionality allows you to specify default values to add to the cell when added to the Grid. These values could be static string values like the Flights parameter above. They could be dynamic values like the Date parameter above; today is a special value that will generate the value of today at runtime. This makes tests less brittle. So you could have values like today+1 or today-5. You may also choose to display a list of values as your default value, as in the FlyTo parameter above. All of these make the creation of tests a lot easier and more intuitive.
Let’s talk about Resources. Default value lists are a great way to help users create tests. But we don’t really want to hard-code these values in keyword files as they may change. Take the FlyTo parameter,
<Param>
<Name>FlyTo</Name>
<Description>Fly To</Description>
<type>List</type>
<defaultValues>Denver, Frankfurt, London, Los Angeles,
Paris, Portland, San Francisco, Seattle, Sydney, Zurich
</defaultValues>
</Param>
It would be better to store the list of destinations in a separate file and reference it in the keyword file instead,
<Param>
<Name>FlyTo</Name>
<Description>Fly To</Description>
<type>List</type>
<defaultValues>Resources/Destinations</defaultValues>
</Param>
Destinations would be Destinations.xml stored in the Resources folder whose path was defined in the Form.Load event,
var resourcesPath = library1.ActualRootPath + @"\Resources\";
These Resources could be cached or generated when required. Logic may be applied to data to filter on options chosen at runtime. Say you had a VBScript keyword called ClickField(screenid,fieldid)
When added to the Grid the screenid parameter cell would be populated with a list of all screens retrieved from Resources/Screens.xml. We couldn’t populate fieldid until we had selected a screen. So the screenid combobox would fire an event when a screen was selected by the user. This would cause the fieldid list to be populated by fields that belonged to the chosen screen. The fieldid parameter may look something like,
<Param>
<Name>Fields</Name>
<Description>Fields for a selected screen</Description>
<type>List</type>
<defaultValues>
Resources/Fields where screenid = [cell-1]
</defaultValues>
</Param>
This says go and get all fields where (screenid = the current cell columnid – 1). It would get the screenid from the cell in the previous column and find a file called [screenid].Fields.xml. For example AddOrder.Fields.xml
Ok, next we’ll continue with some analysis theory and try and understand why we’re using a UI like this instead of traditional spreadsheets.
Create Test Automation Framework – Part1a Create Test Automation Framework – Part 1c