WordPress database error: [INSERT, UPDATE command denied to user '51213-2'@'10.10.20.81' for table 'wp_options']
INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('_transient_doing_cron', '1715170502.3084440231323242187500', 'yes') ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)


Warning: Cannot modify header information - headers already sent by (output started at /home/lexiqued/www/WordPress/wp-includes/wp-db.php:1502) in /home/lexiqued/www/WordPress/wp-includes/feed-rss2.php on line 8
Coded UI Tests / Automation – Jonathan ANTOINE's thoughts http://www.jonathanantoine.com Yet another blog about... Mon, 16 Jan 2012 14:44:12 +0000 en-US hourly 1 https://wordpress.org/?v=5.5.3 Coded UI Tests : WPF Utilities http://www.jonathanantoine.com/2012/01/15/coded-ui-tests-wpf-utilities/ http://www.jonathanantoine.com/2012/01/15/coded-ui-tests-wpf-utilities/#comments Sun, 15 Jan 2012 09:40:55 +0000 http://www.jonathanantoine.com/?p=908 I played a lot with Coded UI Tests API on WPF applications these last weeks.

It turned out that this is a really powerful framework available to use but that we need to write a lot of code ourselves even for simple things.

You may already know the coded ui test utilities of Gautam Goenka available on his blog.

On this blog post, I want to introduce a set of complementary helper methods that you can use in your project. The links to the binaries/sources are at the end of the post.

Here is a list of the available features :

  1. List, Tree and Menu emptiness tests as User extension methods.
  2. Helper to get all the AutomationIds of a control collection.
  3. Helper to get all the children control of a specific type.
  4. Easier set text syntax with fallback method: youpi !
  5. Easier set value syntax.
  6. Easier expand and collapse syntax.
  7. Easier selection syntax.
  8. Easier invoke syntax.

Features, code sample and comments

List, Tree and Menu emptiness tests as User extension methods

It’s always useful to know if a listbox is empty or not. Now you can use these simple methods.
[csharp]
// WpfTree treeView = … ;

//Tell me if you are empty my dear
bool isEmpty = treeView.IsEmpty();
Assert.IsTrue(isEmpty);
[/csharp]

Helper to get all the AutomationIds of a control children

Sometimes you store information trough AutomationIds. This method will help you to retrive them in a simple way.
[csharp]
// WpfControl control= … ;

//Rertrieve the ids
List<string> idsOfChildren = control.GetChildrenAutomationIds();
[/csharp]

Helper to get all the children control of a specific type

This is a recursive method which can helps you in several scenarii. Be sure to notice that there is an override which takes a boolean as a parameter. If it sets to false, the method will return ALL the children and not only the direct one.

Also, be sure to understand that you won’t be able to call the Find method on these controls as they do not have defined search properties.

[csharp]
// WpfControl control= … ;

//Get only the direct children
List<WpfEdit> children= control.GetChildren<WpfEdit>();

foreach(WpfEdit edit in children) SomethingCool();

//Get all the children in the tree below the control
List<WpfEdit> children= control.GetChildren<WpfEdit>(onlyDirectChildren: false);

foreach(WpfEdit edit in children) SomethingCoolToo();
[/csharp]

Easier set text syntax with fallback method: youpi !

I found out trying to set the text of a TextBox that you can end up waiting eternity for the text being really set.

I do so tried to create an helper method which can be faster using the automation pattern. I then try to use the value pattern but oddly, it wasn’t available on the TextBox automation peer.

I finally find on a MSDN code sample comments that “Elements that support TextPattern do not support ValuePattern and TextPattern does not support setting the text of multi-line edit or document controls”. So if the control implements the TextPattern, you have to use a fallback method which is in fact simulate keyboard inputs.

The helper method just do that :

[csharp]
//WpfControl control = …;

//Set the text
bool isTextSet= control.TrySetText("I love Coded UI tests");
Assert.IsTrue(isTextSet);
[/csharp]

Easier set value syntax

Testing if a control implements a pattern and then trying to call it represents a lot of code line.
With this helper you just have one single line method call.
[csharp]
//WpfControl control = …;

//Set the value
bool isValueSet= control.TrySetValue("I want to set this value.");
Assert.IsTrue(isValueSet);
[/csharp]

Easier expand and collapse syntax

Same as the previous, one single line to collapse/expand a control. If the control does not implements the pattern, the method will just returns false.
[csharp]
//WpfControl control = …;

//Expanding
bool isExanpded = control.TryExpand();
Assert.IsTrue(isExanpded);

//Collapsing
bool isCollapsed = control.TryCollapse();
Assert.IsTrue(isCollapsed);
[/csharp]

Easier selection syntax

Select a control in one line of code !
[csharp]
//WpfControl control = …;

//Select the control
bool isSelected = control.TrySelect();
Assert.IsTrue(isSelected);
[/csharp]

Easier Invoke syntax

Instead of simulate a mouse click, you can now use this method which will use the invoke pattern even if the control is hided.
[csharp]
//WpfControl control = …;

//Invoke
bool isInvoked = control.TryInvoke();
Assert.IsTrue(isInvoked);
[/csharp]

Were are the binaries ?

The binaries and the, well commented, soure code can be found at this adress : https://www.dropbox.com/s/gmpybsviirm3bqd#view:list

Don’t forget to support me by registering to Dropbox using this link.

]]>
http://www.jonathanantoine.com/2012/01/15/coded-ui-tests-wpf-utilities/feed/ 4
Coded UI Tests : Property “ReadOnly” cannot be retrieved due to the current state of Edit http://www.jonathanantoine.com/2012/01/10/coded-ui-tests-property-readonly-cannot-be-retrieved-due-to-the-current-state-of-edit/ http://www.jonathanantoine.com/2012/01/10/coded-ui-tests-property-readonly-cannot-be-retrieved-due-to-the-current-state-of-edit/#comments Tue, 10 Jan 2012 19:03:04 +0000 http://www.jonathanantoine.com/?p=936

Did you ever encounter this error while trying to retrieve a property value from an AutomationElement ? I did !

Don’t worry, there is always a work-around, and I’ve found one.

In this post, we’ll dig a little more into this issue and give a little example of the “Coded UI Tests” fun 🙂

The issue

Let’s create a little demo application wich contains only one control : a RichTextBox set as readonly.
[xml] <RichTextBox IsReadOnly="True" Margin="3" />[/xml]

It may be interesting in a coded ui test to verify that the RichTextBox is really read only. Doing so seems pretty easy with Visual Studio :

  1. Target the element using the coded ui test recorder;
  2. In the code, get ReadOnly property value from the WpfEdit element;
  3. In the code, Assert that the value is equal to ‘True’.

[csharp][TestMethod]
public void CodedUITestMethod1()
{
//The target richTextBlock is of WpfEdit type
WpfEdit uIItemEdit = UIMap.UIPropertyXXXcannotberWindow.UIItemEdit;

//Assert it is really readonly
Assert.IsTrue(uIItemEdit.ReadOnly);
}[/csharp]

By running this code, you will be disappointed to get this exception : “Property “ReadOnly” cannot be retrieved due to the current state of Edit” ! I try to google this error but nothing is what I found 🙁 !

How I solved it !

I struggled a lot with the API and I found out that the read only property is also available via an another way.

First of all, you have to add the UIAutomationClient.dll assembly as a reference.

The solution is to get the native element linked to the WpfEdit which is of AutomationElement type. With it I can retrieve the the TextPattern which is supported by the RichTextBox automation peer.

This pattern can be use to select the whole text in the RichTextbox. Then you can retrieve the selection with the same pattern and ask for the IsReadOnly attribute value.

Pretty easy to find no ? (I am just kidding here :-s) !

The resulting, commented, code is here :
[csharp]
public static bool IsReadOnly(this WpfEdit richText)
{
if (richText == null) throw new ArgumentNullException("richText");

//We are in WPF so NativeElement is of AutomationElement type.
var element = richText.NativeElement as AutomationElement;

//Retrieve the TextPattern,
var pattern = element.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
if (pattern == null)
throw
new InvalidOperationException("Cannot retrieve the info from the control");

//use the pattern to select the whole RichTextBox
pattern.DocumentRange.Select();

// use the pattern to get the selection
var selection = pattern.GetSelection();

if (selection.Any())
{
//Retrieve the value of the IsReadOnly attribute
var attValue = selection[0]
.GetAttributeValue(TextPattern.IsReadOnlyAttribute);
if (attValue == null)
throw
new InvalidOperationException("Cannot retrieve the info from the control");

//This is a boolean my dear
return bool.Parse(attValue.ToString());
}

throw
new InvalidOperationException("Cannot retrieve the info from the control");
}
[/csharp]

If you are struggling with the same kind of issue, please share it with us in the comment. You may also find intersting the list of available attributes for the TextPattern : http://msdn.microsoft.com/en-us/library/ms608656.aspx

A demo solution is available on my DropBox folder as usual.

]]>
http://www.jonathanantoine.com/2012/01/10/coded-ui-tests-property-readonly-cannot-be-retrieved-due-to-the-current-state-of-edit/feed/ 4
Coded UI Tests : the recorder encountered a wrong control while recording the last action. http://www.jonathanantoine.com/2011/11/15/coded-ui-tests-the-recorder-encountered-a-wrong-control-while-recording-the-last-action/ http://www.jonathanantoine.com/2011/11/15/coded-ui-tests-the-recorder-encountered-a-wrong-control-while-recording-the-last-action/#comments Tue, 15 Nov 2011 16:55:56 +0000 http://www.jonathanantoine.com/?p=825 One more quick post on Coded UI tests recording issue. Today, the coded UI test builder tool said to me “The recorder encountered a wrong control while recording the last action.” !

After some search in my app, I found out that it’is related to a ScrollViewer in a TabControl.

In this post we’ll see how I solved it…

The issue

The problem is easy to reproduce: inside a tabcontrol, add a TabItem and set its ContentTemplate with a DataTemplate containing a ScrollViewer. Then try to record any action inside the TabItem using the Coded UI Test Builder. You won’t be able to do it.

You can even set the ContentTemplate of the TabControl as pointed out on the Connect web site.

Here is an example of the XAML which does not work:
[xml]<TabControl Margin="0" x:Name="MainTabControl">
<TabItem Header="Tab">
<TabItem.ContentTemplate>
<DataTemplate>
<ScrollViewer>
<DockPanel>
<Button DockPanel.Dock="Bottom" Content="Youpi !"
Click="onButtonClick" />
<TextBox Text="a value " />
</DockPanel>
</ScrollViewer>
</DataTemplate>
</TabItem.ContentTemplate>
</TabItem>
</TabControl>[/xml]

The solution

The solution is the same than for the TextBox issue : you have to create a fixed version of the ScrollViewer and use it instead of the standard one.

The fixed version simply provide an automation peer which returns true when the UI test framework ask him if it’s a ControlElement. Here is the regarding code :
[csharp]public class FixedScrollViewer : ScrollViewer
{
protected override AutomationPeer OnCreateAutomationPeer()
{
var peer = new FixedScrollViewerAutomationPeer(this);
return peer;
}
}

public class FixedScrollViewerAutomationPeer : ScrollViewerAutomationPeer
{
public FixedScrollViewerAutomationPeer(ScrollViewer target)
: base(target)
{

}
protected override bool IsContentElementCore()
{
var isContentElementCore = base.IsContentElementCore();
return isContentElementCore;
}

protected override bool IsControlElementCore()
{
//If in a template it returns false and it breaks the CUITB :'(
return true;
}
}[/csharp]

MS fix : Visual Studio 2011

This bug is on connect and Mathew Aniyan, the Visual Studio ALM program manager, noticed us that it will be fixed in the next version (VS2011 and Framework 4.5).

Regards,

]]>
http://www.jonathanantoine.com/2011/11/15/coded-ui-tests-the-recorder-encountered-a-wrong-control-while-recording-the-last-action/feed/ 1
Coded UI tests : my TextBlock is not found, how to find it ? http://www.jonathanantoine.com/2011/11/09/coded-ui-tests-my-textblock-is-not-found-how-to-find-it/ http://www.jonathanantoine.com/2011/11/09/coded-ui-tests-my-textblock-is-not-found-how-to-find-it/#comments Wed, 09 Nov 2011 16:16:59 +0000 http://www.jonathanantoine.com/?p=806 In the previous post, we have seen that setting the AutomationId can greatly help us when we want to perform some UI Tests.

Todyay, I struggled with a problem which seems common after some digging on the net : the TextBlock control is not found and no assertion can be set on it.
But it does not always occur and it is then difficult to debug this strange behavior.

In this post we’ll see why this happen and how to solve this issue.

Why and When ?

The problem comes from the TextBlockAutomationPeer. If you digg into its code you can find this :
[csharp]override protected bool IsControlElementCore()
{
return ((TextBlock)Owner).TemplatedParent == null;
} [/csharp]

This basically means that if the TextBlock is inside a template, any kind of template, it is not exposed.
For example, if in an ItemsControl, a Listbox or another control, you use a DataTemplate containing a TextBlock, this one won’t be find by the automation client. Here is a code example :
[xml]<Grid>
<Grid.Resources>
<DataTemplate x:Key="ItemTemplate">
<TextBlock Text="{Binding }" />
</DataTemplate>
</Grid.Resources>
<ListBox ItemsSource="{Binding }"
ItemTemplate="{StaticResource ItemTemplate}" />
</Grid>[/xml]

A solution

The only dirty solution I find is to create your own TextBlock control with its own corrected AutomationPeer.
It will be based on the original TextBlockAutomationPeer but the IsControlElementCore method will always return true.
As a bonus, I let commented a snippet which will expose the TextBlock only if an AutomationId is set on it.

The code to write is really light. The real issue is that you have to update every TextBlock usage in the XAML of your application.
[csharp]
public class AutomatisableTextBlock : TextBlock
{
protected override AutomationPeer OnCreateAutomationPeer()
{
return new AlwaysVisibleTextBlockAutomationPeer(this);
}
}

//The corrected AutomationPeer is based on the TextBlockAutomationPeer
public class AlwaysVisibleTextBlockAutomationPeer : TextBlockAutomationPeer
{
public AlwaysVisibleTextBlockAutomationPeer(TextBlock t)
: base(t) { }

protected override bool IsControlElementCore()
{
//if (String.IsNullOrEmpty(GetAutomationId()))
// return false;
return true;
}
}
[/csharp]

Finally, the demo app XAML needs to be updated:
[xml]
<Grid>
<Grid.Resources>
<DataTemplate x:Key="ItemTemplate">
<local:AutomatisableTextBlock Text="{Binding }" />
</DataTemplate>
</Grid.Resources>
<ListBox ItemsSource="{Binding }"
ItemTemplate="{StaticResource ItemTemplate}" />
</Grid>[/xml]

After the update, the TextBlock is correctly found by any automation client:

]]>
http://www.jonathanantoine.com/2011/11/09/coded-ui-tests-my-textblock-is-not-found-how-to-find-it/feed/ 4
Coded UI tests : AutomationId or how to find the chose one (control) ! http://www.jonathanantoine.com/2011/11/03/coded-ui-tests-automationid-or-how-to-find-the-chose-one-control/ http://www.jonathanantoine.com/2011/11/03/coded-ui-tests-automationid-or-how-to-find-the-chose-one-control/#comments Thu, 03 Nov 2011 16:07:10 +0000 http://www.jonathanantoine.com/?p=737 In my previous post on Coded UI tests, we have seen how to make a control discoverable by a Microsoft UI Automation client including the Coded UI tests builder.

This is a first step and the controls now need to be uniquely identified. This is done via the AutomationId property. In this post we’ll digg a little more in coded UI tests and discover the AutomationId property.
[table-of-content]

AutomationId : what is it ?

As stated in the previous post, an application exposes AutomationPeer. They are then found by UI Automation Client as AutomationElement objects. These items are identified uniquely by the AutomationId property.

This identifier is not mandatory but it’s a best practice to set it when you plan to perform UI tests.

To retrieve a control, the automation peer tree is used : first the top element is found, then the automation client iterate on its children, then the children of the children until it finds the aimed element. Each of the children and the final target is find using conditions and usually, one is set on the automation id.

The automation id is a property which helps you to find a specific UI element among others. This is, for example, very useful when you want to find a specific item in a collection (listbox, menus, etc.). Another benefit is that, as the control is uniquely identified, you can move it elsewhere or change its name and it will still be found by a previous code needing it.

To leverage the power of it, there is a rule to respect: it’s expected to be the same in any instance of the same application and ‘unique by instance in its scope‘.

  1. If you exit the application and launch it again, the value will not change.
  2. If you change the culture of the PC/Application, it will not change.
  3. If you launch several instance of the application, it remains the same on each of them.
  4. If there is several usage of the control in the application, each of them has a different automation id on each scope. A scope is defined by the path in the tree to go to the element. For example each menu item of a menu can be named in a generic way : menuItem1, menuItem2, etc.

This is a rule and you are not forced by the runtime or anything to follow it. As a proof, AutomationPeer returns a default value of string.empty which is really not unique!

By the way, if you want to set a name to a control(for example to improve accesibility) uses the Name property instead of the AutomationId one.

How to set it ?

The AutomationPeer exposes a method GetAutomationId of type string. When you create a custom AutomationPeer, you can override the GetAutomationIdCore abstract method to return a custom value. The default value is string.empty.

You can also set the returned value via XAML using the AutomationProperties’s AutomationId attached property.
[xml]<MyControl AutomationProperties.AutomationId="AnUniqueValue"/>[/xml]

The default implementation (which you can override) of the the AutomationPeer’s GetAutomationIdCore method read the value from the attached property too:
[csharp]
//In the AutomationPeer class.
protected override string GetAutomationIdCore()
{
return (AutomationProperties.GetAutomationId(_owner));
}[/csharp]

How to use it in automation clients ?

This is pretty straightforward, you just have to define a condition on it, providing the searched value:
[csharp]string seekedAutomationId = "AnUniqueValue";

//Create the condition
var condition = new PropertyCondition(
AutomationElement.AutomationIdProperty, seekedAutomationId);

//Retrieve the element via FindFirst(best practice)
var elt = AutomationElement.RootElement.FindFirst(TreeScope.Descendants, condition);
[/csharp]

Also, you can retrieve the AutomationId value of an element using this code:
[csharp]AutomationElement autoElement = //Retrieves the auto element here.
string autoId =
autoElement.GetCurrentPropertyValue(AutomationElement.AutomationIdProperty)
as string;[/csharp]

How is it used by the Coded UI tests builder ?

This tool is the one shipped with Visual Studio with which you can record coded UI tests.

If no AutomationId is set, the tools generates code which search the button based on its properties’ values. As you can see, if you move the button elsewhere, the test won’t be able to find it again.
[csharp]var mUIYoupiButton1 = new WpfButton(this);
#region Search Criteria
mUIYoupiButton1.SearchProperties[WpfButton.PropertyNames.Name] = "Youpi !";
mUIYoupiButton1.SearchProperties[WpfButton.PropertyNames.Instance] = "2";
mUIYoupiButton1.WindowTitles.Add("MainWindow");
#endregion

return mUIYoupiButton1;
[/csharp]

When you set the automation id, the generated code is smart enough to use it to identify the button:
[csharp]var mUIYoupiButton = new WpfButton(this);
#region Search Criteria
mUIYoupiButton
.SearchProperties[WpfButton.PropertyNames.AutomationId] = "AnUniqueValue";
mUIYoupiButton.WindowTitles.Add("MainWindow");
#endregion

return mUIYoupiButton;[/csharp]

How to find it on existing application ?

Snoop for a WPF application, UI Spy for a Silverlight one !

As this is a standard property you can read it as any other with these tools! In using it, don’t forget that it’s not an inherited property and that you have to select precisely the control (It can be difficult using the Ctrl+Shift shortcut).
AutomationId retrieval with snoop

When to set the AutomationId ?

As you’ve read, this is not mandatory to set it but it is a best practice.

My opinion is to do it right when you code in any application which may be tested trough coded UI tests.

To set it on all control is useless because not all control will be tested. Instead, I recommend to identify the key controls of the application. Usually, it’s button, menu items, any controls which can receive input from the users (keyboard and/or mouse).
Also, don’t forget the controls which evolve on user interaction and display results / information.

It can be a good thing, before to start to write any code, to set up a meeting with the quality team, deciding what are those controls. The member of the quality team usually know what they test 🙂

AutomationId and ItemsControl or dynamically generated controls.

In any user interface, there is dynamic parts. One of the most common are ItemsControls. A recurrent question is “how can I define an AutomationId on something which is dynamic ?“.

My answer is : “as you would do for any other problem – via a binding“. The AutomationId is an attached dependency property and you can set a binding on it which will solve your problem.

Let’s say, that I want to display a list of person, then in the DataTemplate representing a person, I can use the Id property of the person as an Automation id. Here is an example:
[xml]<DataTemplate x:Key="PersonDataTemplate" DataType="model:Person">
<TextBlock Text="{Binding Name}">
<AutomationProperties.AutomationId>
<MultiBinding StringFormat="AID_{0}-{1}">
<Binding Path="Name" />
<Binding Path="Id" />
</MultiBinding >
</AutomationProperties.AutomationId>
</TextBlock>
</DataTemplate>

<ItemsControl x:Name="_myItemsControl"
ItemTemplate="{StaticResource PersonDataTemplate}" />

[/xml]

The real issue is to respect the previously mentioned rule: “how to keep the id unique and the same in all the instance of the application”. The solution will depends of the application and the goal of the control.

If the aimed control is targeted because of the value it represents (a specific person) then you can generate the id using the model property (the id of the person).

If the aimed control is targeted because of its position in the interface (the 5th item in the list) then you can bind to UI-related properties like the alternation count for example. You can also find a technique which uses the index of the item in the list as an AutomationId.

I am sad to tell it but there is no solution which will work in all case 🙁

More to read on the subject

If you want to discover more on this subject, here is some interesting links:

  1. Visual Studio Team Test blog posts on the subject : part 1 and part 2.
  2. UI Automation Properties Overview on MSDN.
  3. Use the AutomationID Property on MSDN.
  4. WPF Application Quality Guidelines on UI testing.
  5. My previous post on the subject explaining Automation peers.

[/table-of-content]

]]>
http://www.jonathanantoine.com/2011/11/03/coded-ui-tests-automationid-or-how-to-find-the-chose-one-control/feed/ 13