Category Archives: PowerShell script

Daily automation: how to test help files. Part 2. Better navigation


Today’s post is a next version of the recently posted HelpWalker.ps1. This version (HelpWalker2.ps1) brought to us the following improvements:

  • scroll down, in order to make nodes visible. The Invoke-UIAControlClick cmdlet uses Win32 API functions to perform clicks, and these functions are bound to the visible area to be working
  • scroll horizontally, so that the middle of some long tree node names are put geometrically in the tree area. Otherwise, it was seen as if click was send not to a node but to a form splitter or even to a right-side page.

Task: improve the script that all the clicks, especially done in the lower area of the tree, get working.

Requirements: the script should walk through any number of tree nodes, independently of how long their names are.

Solution: below is the script that walks through all nodes with no exception:

####################################################################################################
# Script name: HelpWalker2.ps1
# Description: demonstrates how to work with the Invoke-UIATreeItemScrollItem cmdlet
# Copyright: http://SoftwareTestingUsingPowerShell.com, 2012
####################################################################################################

param(
 [string]$FileName,
 [string]$AppTitle,
 [string]$HelpTitle
 )
Set-StrictMode -Version Latest
cls;

#ipmo $global:uiautomationModule;

if ($FileName.Length -eq 0 -or $AppTitle.Length -eq 0 -or $HelpTitle.Length -eq 0) {
 Write-Host "Please specify parameters as .\HelpWakler2.ps1 app_file_name application_title help_title";
 exit;
}

# set a small delay between nodes
# because the refresh of each page should take time
[UIAutomation.Preferences]::OnSuccessDelay = 100;

# create our enum object
[PSObject]$testNames = New-Object PSObject;
$testNames | `
 Add-Member -MemberType NoteProperty -Name AppTitle -Value $AppTitle -PassThru | `
 Add-Member -MemberType NoteProperty -Name HelpTitle -Value $HelpTitle -PassThru | `
 Add-Member -MemberType NoteProperty -Name AppName -Value $FileName;

# start the AUT, its help file and get the window
Start-Process $testNames.AppName -PassThru | Get-UIAWindow -Seconds 120 | `
 Get-UIAMenuItem -Name Help | Invoke-UIAMenuItemClick | `
 Get-UIAMenuItem -Name 'Help*Topic*' | INvoke-UIAMenuItemClick;
Get-UIAWindow -Name $testNames.HelpTitle -Seconds 120;

function Invoke-TreeNodeExpand
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIAControlClick -DoubleClick -PassThru:$false);
}

function Invoke-TreeNodeCollapse
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIAControlClick -DoubleClick -PassThru:$false);
}
function Invoke-TreeNodeShowRightPane
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIAControlClick -PassThru:$false);
}

function Invoke-TreeNodeScrollTo
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIATreeItemScrollItem);
}

function Invoke-TreeNodeChildrenProcess
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element,
 [string]$NodeHierarchy
 )

 # children of the node or top-level nodes
 $children = $element | Get-UIAControlChildren -ControlType TreeItem;

if ($children -ne $null -and $children -is [Object[]] -and $children.Count -gt 0) {

# we store the previous node in a variable, so that
 # we can return to it and collapse its chilren
 # after we walked through all of them
 [System.Windows.Automation.AutomationElement]$previousChild = $null;

foreach ($childNode in $children) {
 try {
 if ($previousChild -ne $null) {
 # collapse the previous node
 Invoke-TreeNodeShowRightPane $previousChild;
 Invoke-TreeNodeCollapse $previousChild;
 }
 $previousChild = $childNode;

# expand the current node
 Invoke-TreeNodeScrollTo $childNode;
 Invoke-TreeNodeExpand $childNode;
 Invoke-TreeNodeShowRightPane $childNode;

# print out the hierarchy
 [string]$fullHierarchy = "";
 if ($NodeHierarchy.Length -gt 0) {
 $fullHierarchy = $NodeHierarchy + " -> " + $childNode.Current.Name;
 } else {
 $fullHierarchy = $childNode.Current.Name;
 }
 Write-Host $fullHierarchy;

# go down the hierarchy
 Invoke-TreeNodeChildrenProcess $childNode $fullHierarchy;
 }
 catch {
 Write-Host $Error[0];
 break;
 }
 }
 }
}

# first time, the tree is given as the root node
$rootNode = Get-UIATree -Seconds 120;
Invoke-TreeNodeChildrenProcess $rootNode;

The script accepts three parameters, as required, and a typical script run looks like:

.\HelpWalker2.ps1 services.msc Services '*Microsoft*Management*'

You should administrative rights or run PowerShell as administrator, if you are trying this sample. Usually, for regular applications, end user’s rights are enough.

Here are more samples how to run the script:

.\HelpWalker2.ps1 compmgmt.msc 'Computer*Management' '*Disk*Management*'
.\HelpWalker2.ps1 dsa.msc '*Active*Directory*Users*' '*Microsoft*Management*'
.\HelpWalker2.ps1 certmgr.msc *Cert* *Micr*Manag*

Daily automation: how to test help files. Part 1. Walkthrough


Testing of help files is a rather monotony task. What should be tested in help files? Usually, the list is

  • ability to run the help file itself
  • how the help file reacts on pressing F1 everywhere in the application UI
  • help pages hierarchy and navigation
  • help page are working, some txt are represented
  • hyperlinks work, inside the help as well as outside
  • the content of the pages (we can check only help topics and keywords, the rest, i.e. articles’ body, should be read by humans)

Today we’ll learn how to walk all the nodes in the help file.

Task: create a script that is a universal tool for navigating inside help files.

Requirements: the script should accept parameters as follows: file name of the application under test (AUT), the title of the AUT, the title of the help file.

Solution: below is the script that walks through all nodes except the cases the list is tool long to be shown in the tree (the API functions that are used can’t work in the invisible area):

param(
 [string]$FileName,
 [string]$AppTitle,
 [string]$HelpTitle
 )
Set-StrictMode -Version Latest
cls;

ipmo [path]\UIAutomation\UIAutomation.dll;
# set a small delay between nodes
# because the refresh of each page should take time
[UIAutomation.Preferences]::OnSuccessDelay = 100;

# create our enum object
[PSObject]$testNames = New-Object PSObject;
$testNames | `
 Add-Member -MemberType NoteProperty -Name AppTitle -Value $AppTitle -PassThru | `
 Add-Member -MemberType NoteProperty -Name HelpTitle -Value $HelpTitle -PassThru | `
 Add-Member -MemberType NoteProperty -Name AppName -Value $FileName;

# start the AUT, its help file and get the window
Start-Process $testNames.AppName -PassThru | Get-UIAWindow -Seconds 120 | `
 Get-UIAMenuItem -Name Help | Invoke-UIAMenuItemClick | `
 Get-UIAMenuItem -Name 'Help*Topic*' | INvoke-UIAMenuItemClick;
Get-UIAWindow -Name $testNames.HelpTitle -Seconds 120;

function Invoke-TreeNodeExpand
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIAControlClick -DoubleClick -PassThru:$false);
}

function Invoke-TreeNodeCollapse
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIAControlClick -DoubleClick -PassThru:$false);
}
function Invoke-TreeNodeShowRightPane
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element
 )
 [void]($element | Invoke-UIAControlClick -PassThru:$false);
}

function Invoke-TreeNodeChildrenProcess
{
 param(
 [ValidateNotNull()]
 [System.Windows.Automation.AutomationElement]$element,
 [string]$NodeHierarchy
 )

 # children of the node or top-level nodes
 $children = $element | Get-UIAControlChildren -ControlType TreeItem;

if ($children -ne $null -and $children -is [Object[]] -and $children.Count -gt 0) {

# we store the previous node in a variable, so that
 # we can return to it and collapse its chilren
 # after we walked through all of them
 [System.Windows.Automation.AutomationElement]$previousChild = $null;

foreach ($childNode in $children) {
 try {
 if ($previousChild -ne $null) {
 # collapse the previous node
 Invoke-TreeNodeShowRightPane $previousChild;
 Invoke-TreeNodeCollapse $previousChild;
 }
 $previousChild = $childNode;

# expand the current node
 Invoke-TreeNodeExpand $childNode;
 Invoke-TreeNodeShowRightPane $childNode;

# print out the hierarchy
 [string]$fullHierarchy = "";
 if ($NodeHierarchy.Length -gt 0) {
 $fullHierarchy = $NodeHierarchy + " -> " + $childNode.Current.Name;
 } else {
 $fullHierarchy = $childNode.Current.Name;
 }
 Write-Host $fullHierarchy;

# go down the hierarchy
 Invoke-TreeNodeChildrenProcess $childNode $fullHierarchy;
 }
 catch {
 Write-Host $Error[0];
 break;
 }
 }
 }
}

# first time, the tree is given as the root node
$rootNode = Get-UIATree -Seconds 120;
Invoke-TreeNodeChildrenProcess $rootNode;

The script accepts three parameters, as required, and a typical script run looks like:

.\HelpWalker.ps1 services.msc Services '*Microsoft*Management*'

You should administrative rights or run PowerShell as administrator, if you are trying this sample. Usually, for regular applications, end user’s rights are enough.

Here are more samples how to run the script:

.\HelpWalker.ps1 compmgmt.msc 'Computer*Management' '*Disk*Management*'
.\HelpWalker.ps1 dsa.msc '*Active*Directory*Users*' '*Microsoft*Management*'