Category Archives: Windows Server 2012

Metro automation: navigating to a certain page


A typical Metro UI application is a set of pages. One is main, and there are several pages where we can go from the main page.

A Metro UI app is unlikely to a traditional app, which often starts from some starting point. A Metro UI app starts for the first time with its main page, but further is may start from wherever page the user left the app.

In our sample, we’ll be using the *Wizard* cmdlets. What are they?

1. the New-UIAWizard cmdlet creates a wizard object, provides it with name and contains a code to start the AUT (application under test), for example. Some initial code.

2. the Add-UIAWizardStep cmdlet creates a step, provides the step with a name, takes a wizard object as an input.

First action we should do on a step is to examine the step. The -SearchCriteria parameter does exactly this task.

After that, we run code for this step. There are two actions we can use, for forward movement and for backward. In out Metro UI app we will be using only forward steps for simplicity sake.

3. the Invoke-UIAWizard cmdlets runs the wizard (in fact, the code we added to the New-UIAWizard cmdlet). It’s usually used for starting the AUT. For purposes of Metro UI testing, we will use this action to show the Start screen and to open the app window.

4. the Step-UIAWizard cmdlet checks the -SearchCriteria (i.e., checks that controls are here and we are on the right page) and runs the step code.


Set-StrictMode -Version Latest

[UIAutomation.Preferences]::Timeout = 10000;
[UIAutomation.Preferences]::EveryCmdletAsTestResult = $true;
[UIAutomation.Preferences]::OnSuccessDelay = 300;

# names of the pages and buttons in the app menu
[string]$constPageMain = 'Home';
[string]$constPageFeaturedDestinations = 'Featured Destinations';
[string]$constPageDestinations = 'Destinations';
[string]$constPageFlights = 'Flights';
[string]$constPageHotels = 'Hotels';
[string]$constPageBestOfWeb = 'Best Of Web';

# names of wizard steps
[string]$constWizardName = 'TravelWizard';
[string]$constWizardStepHome = 'Home';
[string]$constWizardStepDestinations = 'Destinations';
[string]$constWizardStepFlights = 'Flights';
[string]$constWizardStepHotels = 'Hotels';
[string]$constWizardStepBestOfWeb = 'BestOfWeb';

# we need to clear the collection of wizards or delete
# the wizard we are playing with.
# Otherwise, the next run will throw an exception
# 'Wizard already exists'
[UIAutomation.WizardCollection]::Wizards.Clear();

# Creating a new wizard
New-UIAWizard -Name $constWizardName `
 -StartAction {
 # setting the Metro Start screen
 Get-UIADesktop;
 Show-UIAMetroStartScreen;

# clicking on the tile of the AUT
 Get-UIAListItem -Name 'Travel' | `
 Invoke-UIAListItemClick;

# the loading screen (if happened)
 try {
 Get-UIAWindow -Name 'Travel' | `
 Get-UIAProgressBar;
 #sleep -Seconds 5; # the app is loading
 }
 catch {}

 # start our tests from the Main page
 Show-UIAMetroMenu;
 Get-UIAWindow -Name 'Travel' | `
 Get-UIAMenuBar -Name 'App Bar' | `
 Get-UIAHyperlink -Name $constPageMain | `
 Invoke-UIAControlClick;
 } | `
 Add-UIAWizardStep -Name $constWizardStepHome `
 -SearchCriteria @{ControlType="Text";Name='Bing Travel'} `
 -StepForwardAction {
 #[System.Windows.Forms.MessageBox]::Show("StepHome");
 "<<<<<<<<<< On the Home page >>>>>>>>>>";
 try {
 Get-UIAText -Name 'Bing Travel';
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Home page >>>>>>>>>>" -TestPassed;
 }
 catch {
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Home page >>>>>>>>>>";
 }
 } -PassThru | `
 Add-UIAWizardStep -Name $constWizardStepDestinations `
 -SearchCriteria @{ControlType="Text";Name='Destinations'},@{ControlType="Text";Name='Region'} `
 -StepForwardAction {
 #[System.Windows.Forms.MessageBox]::Show("StepDestinations");
 "<<<<<<<<<< On the Destinations page >>>>>>>>>>";
 try {
 Get-UIAText -Name 'Destinations';
 Get-UIAText -Name 'Region';
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Destinations page >>>>>>>>>>" -TestPassed;
 }
 catch {
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Destinations page >>>>>>>>>>";
 }
 } -PassThru | `
 Add-UIAWizardStep -Name $constWizardStepFlights `
 -SearchCriteria @{ControlType="Text";Name='Flights'},@{ControlType="Text";Name='Schedule'} `
 -StepForwardAction {
 #[System.Windows.Forms.MessageBox]::Show("StepFlights");
 "<<<<<<<<<< On the Flights page >>>>>>>>>>";
 try {
 Get-UIAText -Name 'Flights';
 Get-UIAText -Name 'Schedule';
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Flights page >>>>>>>>>>" -TestPassed;
 }
 catch {
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Flights page >>>>>>>>>>";
 }
 } -PassThru | `
 Add-UIAWizardStep -Name $constWizardStepHotels `
 -SearchCriteria @{ControlType="Text";Name='Hotels'},@{ControlType="Text";Name='Check-in'} `
 -StepForwardAction {
 #[System.Windows.Forms.MessageBox]::Show("StepHotels");
 "<<<<<<<<<< On the Hotels page >>>>>>>>>>";
 try {
 Get-UIAText -Name 'Hotels';
 Get-UIAText -Name 'Check-in';
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Hotels page >>>>>>>>>>" -TestPassed;
 }
 catch {
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the Hotels page >>>>>>>>>>";
 }
 } -PassThru | `
 Add-UIAWizardStep -Name $constWizardStepBestOfWeb `
 -SearchCriteria @{ControlType="Text";Name='Travel'},@{ControlType="Text";Name='Explore'},@{ControlType="Text";Name='Plan a Trip'} `
 -StepForwardAction {
 #[System.Windows.Forms.MessageBox]::Show("Best Of Web");
 "<<<<<<<<<< On the 'Best Of Web' page >>>>>>>>>>";
 try {
 Get-UIAText -Name 'Travel';
 Get-UIAText -Name 'Explore';
 Get-UIAText -Name 'Plan a Trip';
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the 'Best Of Web' page >>>>>>>>>>" -TestPassed;
 }
 catch {
 Close-TMXTestResult -Name "<<<<<<<<<< Navigating to the 'Best Of Web' page >>>>>>>>>>";
 }
 };

# Start the wizard
[UIAutomation.Wizard]$wizard = Invoke-UIAWizard -Name $constWizardName;

# Click on the Destinations button in the app menu
Show-UIAMetroMenu;
Get-UIAWindow -Name 'Travel' | `
 Get-UIAMenuBar -Name 'App Bar' | `
 Get-UIAHyperlink -Name $constPageDestinations | `
 Invoke-UIAControlClick;

# Check that this is the Destinations page and run code (in the future sample)
$wizard | Step-UIAWizard -Name $constWizardStepDestinations

# Click on the Flights button in the app menu
Show-UIAMetroMenu;
Get-UIAWindow -Name 'Travel' | `
 Get-UIAMenuBar -Name 'App Bar' | `
 Get-UIAHyperlink -Name $constPageFlights | `
 Invoke-UIAControlClick;

# Check that this is the Flights page and run code (in the future sample)
$wizard | Step-UIAWizard -Name $constWizardStepFlights;

# Click on the Hotels button in the app menu
Show-UIAMetroMenu;
Get-UIAWindow -Name 'Travel' | `
 Get-UIAMenuBar -Name 'App Bar' | `
 Get-UIAHyperlink -Name $constPageHotels | `
 Invoke-UIAControlClick;

# Check that this is the Hotels page and run code (in the future sample)
$wizard | Step-UIAWizard -Name $constWizardStepHotels;

# Click on the 'Best Of Web' button in the app menu
Show-UIAMetroMenu;
Get-UIAWindow -Name 'Travel' | `
 Get-UIAMenuBar -Name 'App Bar' | `
 Get-UIAHyperlink -Name $constPageBestOfWeb | `
 Invoke-UIAControlClick;

# Check that this is the 'Best Of Web' page and run code (in the future sample)
$wizard | Step-UIAWizard -Name $constWizardStepBestOfWeb;

The dubious piece of code is getting a progress bar on loading the application. Sometimes, it is shown. Sometimes, there is no progress bar.

Advertisements

0.8.0 Preview 3: bug fix and improvements to UIARunner


UIARunner from 0.8.0 Preview 2 has a bug that is easy to work around, but It is difficult to find out this workaround.

The bug in fact is a combination of two bugs:

  • UIARunner failed to load its autoexec file called UIARunner.ps1 if the application is in a folder with spaces in the path, i.e., Program Files. There weren’t added quotes.
  • error reporting in the grid couldn’t display the right error

Even though it’s avoidable, it’s better to publish 0.8.0 Preview 3. Now, it works as

  • The UIARunner.ps1 autoexec file can be loaded from any folder
  • Binaries (UIAutomation.dll and TMX.dll) are loaded before the autoexec script
  • Grid and the report file provide an error’s description, for example, execution policy is set to Restricted.

0.8.0 Preview 2: wanted richer output?


Again and again, it’s not going to end. People ask me ‘why Metro UI testing doesn’t work from PowerShell ISE?’

PowerShell ISE and powershell.exe are Microsoft’s tools, they have no relation to Metro UI testing. Technically, Microsoft guys can build ISE and powershell.exe to make them uiAccess’ible. However, don’t wait this: why should they build a host for my cmdlets? To help compete with their Coded UI? I sooner believe that they will write their own UI cmdlets in v3 or v4 (as they usually answer to PowerGUI features, for example), than they do something specific for 3rd party cmdlets.

The other side of coin is that I’m not going to write one more code editor with debugging capabilities. I’d like to, but this is a time-consuming task. Not to say that an editor of appropriate quality is not so easy to write up.

That’s a dilemma: we can run PowerShell over Metro UI, but we can’t work deeply with variables and output.

0.8.0 Preview 2 solves this partly. Now, output is partially supported. The list of what is supported:

  • string output (code: “string”)
  • string output for objects (code: (Get-UIAWindow 0n calc*).Current | Out-String)

Write- cmdlets are not supported in this version. Possibly, they will be supported later.

Here is a sample:

[UIAutomation.Preferences]::EveryCmdletAsTestResult=$true
[UIAutomation.Preferences]::OnSuccessDelay = 0;

Start-Process calc
Get-UIAWindow -n calc* | Get-UIAButton -n 1 | Invoke-UIAButtonClick;
(Get-UIAButton -n add | Invoke-UIAButtonClick).Current.AutomationId;
(Get-UIAButton -n 1 | Invoke-UIAButtonClick).Current | Out-String;
Get-UIAWindow -n calc* | Get-UIAButton | Set-UIAFocus | Set-UIAControlKeys -Text "1{+}1{=}"
'Get-UIAWindow -n calc* | Out-String; ->'
Get-UIAWindow -n calc* | Out-String;
'(Get-UIAWindow -n calc*).Current | Out-String;'
(Get-UIAWindow -n calc*).Current | Out-String;

"now test should fail"
Get-UIAWindow -n "non-existing window" -Seconds 2
Get-UIAWindow -n calc* | Get-UIAButton -n 10 | Invoke-UIAButtonClick;

Output is shown as light-blue lines. It returns:

  • the button 1 (Invoke-UIAButtonClick returns)
  • the automation id of the button Add (again, the same cmdlet returns)
  • AutomationElementInfo (i.e., .Current). This is the button 1 again.
  • further, after an empty string, there are string lines to help you compare what means to put an AutomationElement and an AutomationElementInfo to the Out-String cmdlet.

It’s not proper way to debug your scripts, though it’s the only way for now.

0.8.0 Preview 2: double squares help to visualize controls better


Controls belong to a big hierarchy. What may be the reason to highlight only two levels of controls if, in practice, there might be ten or twenty levels in the hierarchy?

The pictures show what the double-highlighting is. The inner square is over the control of interest, whereas the circumscribing one is over its parent.

However, things suddenly change when you put the cursor over WPF applications, its (WPF’s) derivatives and HTML:

This is a rather typical case: we are seeing a button or a link and, at the same time, the topmost control is a text.

The same story in Metro UI applications:

Here it is seen even better:

and here too:

The name of the button is not ‘Permissions’ as we could think, the name is ‘Back’.

At the end, there is a brilliant example:

There are TWO things on top of the button! This is the out-of-the-box Mail application.

0.8.0 Preview 1: UIARunner, UIAutomationSpy, and modules are published


Even though with some bugs and ugly-looking (it never was our intent to write GUI tools besides modules:)), UIARunner is published. As far as I know, this is the first GUI wrapper for PowerShell that looks like a software testing tool. ūüôā

This preliminary version supports:

  • running one script at a time
  • using the UIARunner.ps1 file (in the application’s folder) as a configuration file
  • generating test report on the fly (in the GUI)
  • generating¬†test report on the fly as a CSV file (both GUI and command-line versions produce such output)
  • unattended runs
  • the GUI version also shows how many test results are passed, failed and the velocity in newly introduced measures called ‘test results per second’ (trps)
  • of course, it supports basic sorting in the grid.

Known issues are numerous (again, this project lacks of professional GUI programmers :)):

  • bad multithreading
  • poor informing about what happened at the PowerShell level
  • and many, many lesser bugs.

Anyway, this version is worth experimenting with. Each package includes several simple scripts to try the runner. Scripts work similarly to other PowerShell hosts, note, however, that you need to use try/catch blocks to avoid terminating errors.

0.8.0 Preview 1: UIARunner for unattended tests


Today’s Preview 1 brings to us not only a new graphical test runner, it includes also command-line test runner: UIARunner for unattended runs.

Although this is a very preliminary version, it can be used to start clicking on your test app. How is this intended to work?

You simply run UIARunner.exe with one parameter, the path to a script with test code. Before¬†a blind run, you can run it in the graphical version of UIARunner: UIARunner.exe. Don’t be afraid of incompatibility! Both utilities are proven on it. They are compatible to the greatest extent, they even is one utility as well.

Being run without the parameter, it displays the form:

 

The form provides us with date/time, status, name and/or source code of test results, and paths to screenshots if there were generated ones.

The command-line version creates a csv file in the folder of the program.

As examples for GUI-based and unattended runs, you may use scripts from folder TMX¬†and UIARunner in the ‘samples’ package.

 

0.8.0 Preview 1: UIARunner as a graphical test tool


Today’s Preview 1 brings to us a new test runner: UIARunner for testing Metro UI and Windows UI.

This version, even though not a release, already can run a script and display test results. The current version supports only test results, i.e., events generated by the Close-TMXTestResult cmdlet or closed automatically through the parameter [UIAutomation.Preferences]::EveryCmdletAsTestResult set to $true.

The figure below shows how it works:

 

The picture was taken¬†when UIARunner¬†was working on a performance test: it should calculate the results of expressions 1 + 1 and 2 + 2 a thousand times, and thousand times try to find the 10 button (it’s a flaw that Microsoft didn’t manage to find more space to put this useful button on the form).

To obtain such a visual report, you need no more than start the application with default settings, open a script through the File -> Open menu item (or by pressing Ctrl+O) and run the script by clicking on the menu item Script -> Run or by pressing F5.

The application is not smooth and cool for its first version. Nonetheless, it already can be used for gathering script results.

Speaking about future improvements, the features that are planned to implement are:

  • ¬†supporting hierarchical reports based on test suites, test scenarios and test results and shown in a grouped list view
  • probably, pausing the script
  • maybe, some events or alerts on conditions like ‘too many failures’ or ‘global timeout interrupted the script’.

 

Metro automation: the first step


Visit our Metro UI automation page.

Yesterday, a customer was disappointed with the difficulty of installing the module. Although the UIAutomation module wasn’t guilty, it would be better to figure out how to install the module on your Windows 8 or Windows Server 2012 host.

First of all, download the right package. Go to the project page and click the Downloads tab:

There, you need to download the package that is called as ‘UIAutomation X.Y.Z for Metro testing’:

Download the package with name like ‘UIAutomation.X.Y.Z.for.Metro.testing.zip’ and open it. Don’t put the content directly to the %ProgramFiles% folder! It won’t work. Security has been tightened even more (and it’s a good news for us), so that we need to do some preparations. Open the package where it was saved (supposedly, in your Downloads folder):

unpack the zip into your user’s folder, for example, Documents. I created the folder ‘Metro’ and paste the files to there. Open properties of dlls:

Now, you need to unblock the binaries one by one::

Eventually, you can copy all the files to a folder within the ‘Program Files’ hierarchy. If you had not unblocked the binaries, or tried to unblock in the ‘Program Files’ folder, your output in PowerShell console would look like that:

If you did all I wrote above, you output will be much cleaner:

The next step is to install the certificate as described here.

Release: version 0.7.12 that does work with Metro UI from UIAutomationSpy a bit more comfortable is out


Visit our Metro UI automation page.

Today, three hosts (Windows 8 RP x64, Windows 8 RP x86, Windows Server 2012 RC) agreed on that the version 0.7.12 is the version we can start with.
What we now can do for testing Metro UI applications?

  • we can start UIAutomationSpy manually and type or paste script code into it, or type a path to the script file. Automated run with preloaded code or script file is not done yet
  • we can show the Start screen (the Show-UIAMetroStartScreen cmdlet) from UIAutomationSpy
  • we can call charm (the Show-UIAMetroCharm cmdlet)
  • we also can call the app/ the Start screen menu (the Show-UIAMetroMenu cmdlet)
  • we can select an app at the Start screen (the Get-UIAListItem cmdlet issuing somewhat after the Get-UIADesktop cmdlet, as the Get-UIA[ControlType] cmdlets require input object)
  • we can start an app by sending an InvokePattern-click to it (the Invoke-UIAListItemClick cmdlet)

All that is mentioned above can be done with the version 0.7.12 and using existing blog posts.

Note: the UIASendKeys utility is deprecated. the Invoke-UIAHotkey is not recommended for use and will be rewritten soon.

Download 0.7.12 from here, the samples.

Metro automation: a nightmare of code generation


Visit our Metro UI automation page.

 

I’ve been struggling with code generation in UIAutomationSpy for a couple of hours. What’s the problem?

Code that UIAutomationSpy generates for Windows applications is what you can run immediately after recording (okay, some polishing or additions may be needed). At least, from today, when I removed the first line of code (i.e., RootElement) and UIAutomaitonSpy is now so close to the Start-UIARecorder-generated code as it might be.

For example, this is code for Notepad (an emtpy document, I click File, the dialog opens and I close it):

Get-UIAWindow -Class 'Notepad' -Name 'Untitled - Notepad' | `

Get-UIAMenuBar -AutomationId 'MenuBar' -Name 'Application' | `

Get-UIAMenuItem -AutomationId 'Item 1' -Name 'File'
Get-UIAWindow -Class 'Notepad' -Name 'Untitled - Notepad' | `

Get-UIAMenuBar -AutomationId 'MenuBar' -Name 'Application' | `

Get-UIAMenuItem -AutomationId 'Item 1' -Name 'File' | `

Get-UIAMenu -Class '#32768' -Name 'File' | `

Get-UIAMenuItem -AutomationId 'Item 1' -Name 'New'
Get-UIAWindow -Class 'Notepad' -Name 'Untitled - Notepad' | `

Get-UIADocument -AutomationId '15' -Class 'Edit'
Get-UIAWindow -Class 'Notepad' -Name 'Untitled - Notepad' | `

Get-UIAWindow -Class '#32770' -Name 'Open' | `

Get-UIATitleBar -AutomationId 'TitleBar' -Name 'Open'

The code is readable (to some extent), though even such code should be prepared to run well.

In fact, the code is raw and the Start-UIARecorder cmdlet still works better:

Get-UIAWindow -n *notepad* | Get-UIAMenuItem -Name File | Invoke-UIAMenuItemExpand | Get-UIAMenuItem -Name Open* | Invoke-UIAMenuItemClick

Anyway, a Windows app is not a mythical beast. Metro UI is more complicated; below is a typical piece of generated code:

Get-UIAList -AutomationId 'GridRoot' -Class 'GridRoot' -Name 'Start Apps' | `
Get-UIAPane -AutomationId 'ScrollViewer' -Class 'TouchScrollViewer' | `
Get-UIAPane -AutomationId 'content' -Class 'GridContent' | `
Get-UIAGroup -AutomationId 'Group 2305843009213693952' -Class 'GridGroup' -Name 'Mail' | `
Get-UIAListItem -AutomationId 'microsoft.windowscommunicationsapps_8wekyb3d8bbwe!Microsoft.WindowsLive.Chat' -Class 'GridTileElement' -Name 'Messaging'

This code simpy finds the Messaging app. This is a dead code. To make the code alive, we need:

  1. add Get-UIADesktop before the first instruction
  2. add Show-UIAMetroStartScreen before the first instruction
  3. remove the line 2:¬†Get-UIAPane -AutomationId ‘ScrollViewer’ -Class ‘TouchScrollViewer’ | `
  4. remove the line 3:¬†Get-UIAPane -AutomationId ‘content’ -Class ‘GridContent’ | `
  5. remove the part of line 5:¬†-AutomationId ‘microsoft.windowscommunicationsapps_8wekyb3d8bbwe!Microsoft.WindowsLive.Chat’ -Class ‘GridTileElement’

After editing, code looks like:

Get-UIADesktop | Get-UIAList -AutomationId 'GridRoot' -Class 'GridRoot' -Name 'Start Apps' | `
Get-UIAGroup -AutomationId 'Group 2305843009213693952' -Class 'GridGroup' -Name 'Mail' | `
Get-UIAListItem -Name 'Messaging'

Finally, the right code would be (for Windows 8 RP):

Get-UIADesktop;
Show-UIAMetroStartScreen;
Get-UIAListItem -Name *Internet*Explorer* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *people* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *messag* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *phot* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *calen* | Invoke-UIAListItemClick;

and for Windows Server 2012:

Get-UIADesktop;
Show-UIAMetroStartScreen;
Get-UIAListItem -Name *Internet*Explorer* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *control* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *computer* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *task*man* | Invoke-UIAListItemClick;

Show-UIAMetroStartScreen;
Get-UIAListItem -Name *admi*tool* | Invoke-UIAListItemClick;

As can be seen, the problem is that code UIAutomationSpy generates is far away of what is working…

The worst of all, the code for Windows applications can be useful from the top control to the current, whereas the code for Metro UI apps should be filtered, edited and some commands should be added to it.
This requires two branches of code generation, doesn’t it?

There is a video based on code samples (HD mode is recommended if you want to read the code).

function Start-MetroApp
{
param( [string]$appName )

Show-UIAMetroStartScreen;
Get-UIAListItem -Name $appName | Invoke-UIAListItemClick;
}
Get-UIADesktop;

Start-MetroApp Music;

Start-MetroApp Finan*;

Start-MetroApp '*internet*explorer*';

Start-MetroApp people;
%d bloggers like this: