WordPress database error: [INSERT, UPDATE command denied to user '51213-2'@'10.10.20.125' for table 'wp_options']
INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('_transient_doing_cron', '1714922300.4656629562377929687500', '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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372

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/rest-api/class-wp-rest-server.php on line 1372
{"id":737,"date":"2011-11-03T17:07:10","date_gmt":"2011-11-03T16:07:10","guid":{"rendered":"http:\/\/www.jonathanantoine.com\/?p=737"},"modified":"2011-11-09T17:19:33","modified_gmt":"2011-11-09T16:19:33","slug":"coded-ui-tests-automationid-or-how-to-find-the-chose-one-control","status":"publish","type":"post","link":"http:\/\/www.jonathanantoine.com\/2011\/11\/03\/coded-ui-tests-automationid-or-how-to-find-the-chose-one-control\/","title":{"rendered":"Coded UI tests : AutomationId or how to find the chose one (control) !"},"content":{"rendered":"

\"\"<\/a>In my previous post on Coded UI tests<\/a>, we have seen how to make a control discoverable by a Microsoft UI Automation client including the Coded UI tests builder.<\/p>\n

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.<\/strong>
\n[table-of-content]<\/p>\n

<\/p>\n

AutomationId : what is it ?<\/h3>\n

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.<\/p>\n

This identifier is not mandatory<\/strong> but it’s a best practice<\/strong> to set it when you plan to perform UI tests.<\/p>\n

To retrieve a control, the automation peer tree is used<\/a> : 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.<\/p>\n

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

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<\/em>‘. <\/p>\n

    \n
  1. If you exit the application and launch it again, the value will not change.<\/li>\n
  2. If you change the culture of the PC\/Application, it will not change.<\/li>\n
  3. If you launch several instance of the application, it remains the same on each of them.<\/li>\n
  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.<\/li>\n<\/ol>\n

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

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

    How to set it ?<\/h3>\n

    The AutomationPeer exposes a method GetAutomationId<\/em> 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.<\/p>\n

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

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

    How to use it in automation clients ?<\/h3>\n

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

    \/\/Create the condition
    \nvar condition = new PropertyCondition(
    \n AutomationElement.AutomationIdProperty, seekedAutomationId);<\/p>\n

    \/\/Retrieve the element via FindFirst(best practice)
    \nvar elt = AutomationElement.RootElement.FindFirst(TreeScope.Descendants, condition);
    \n[\/csharp]<\/p>\n

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

    How is it used by the Coded UI tests builder ?<\/h3>\n

    This tool is the one shipped with Visual Studio with which you can record coded UI tests.
    \n<\/strong>
    \nIf 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.
    \n[csharp]var mUIYoupiButton1 = new WpfButton(this);
    \n#region Search Criteria
    \nmUIYoupiButton1.SearchProperties[WpfButton.PropertyNames.Name] = "Youpi !";
    \nmUIYoupiButton1.SearchProperties[WpfButton.PropertyNames.Instance] = "2";
    \nmUIYoupiButton1.WindowTitles.Add("MainWindow");
    \n#endregion<\/p>\n

    return mUIYoupiButton1;
    \n[\/csharp]<\/p>\n

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

    return mUIYoupiButton;[\/csharp]<\/p>\n

    How to find it on existing application ?<\/h3>\n

    Snoop for a WPF application, UI Spy for a Silverlight one !<\/p>\n

    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).
    \n
    \"AutomationId<\/a><\/p>\n

    When to set the AutomationId ?<\/h3>\n

    As you’ve read, this is not mandatory to set it but it is a best practice.<\/p>\n

    My opinion is to do it right when you code in any application which may be tested trough coded UI tests.<\/p>\n

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

    It can be a good thing, before to start to write any code, to set up a meeting with the quality team,<\/strong> deciding what are those controls. The member of the quality team usually know what they test \ud83d\ude42<\/p>\n

    AutomationId and ItemsControl or dynamically generated controls.<\/h3>\n

    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 ?<\/strong>“. <\/p>\n

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

    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:
    \n[xml]<DataTemplate x:Key="PersonDataTemplate" DataType="model:Person">
    \n <TextBlock Text="{Binding Name}">
    \n <AutomationProperties.AutomationId>
    \n <MultiBinding StringFormat="AID_{0}-{1}">
    \n <Binding Path="Name" \/>
    \n <Binding Path="Id" \/>
    \n <\/MultiBinding >
    \n <\/AutomationProperties.AutomationId>
    \n <\/TextBlock>
    \n<\/DataTemplate><\/p>\n

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

    [\/xml]<\/p>\n

    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”.<\/strong> The solution will depends of the application and the goal of the control. <\/p>\n

    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). <\/p>\n

    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 <\/a>which uses the index of the item in the list as an AutomationId.<\/p>\n

    I am sad to tell it but there is no solution which will work in all case \ud83d\ude41 <\/strong><\/p>\n

    More to read on the subject<\/h3>\n

    If you want to discover more on this subject, here is some interesting links:<\/p>\n

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

      [\/table-of-content]<\/p>\n","protected":false},"excerpt":{"rendered":"

      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…<\/p>\n","protected":false},"author":3,"featured_media":781,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[27,6,4,5],"tags":[],"_links":{"self":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts\/737"}],"collection":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/comments?post=737"}],"version-history":[{"count":47,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts\/737\/revisions"}],"predecessor-version":[{"id":822,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/posts\/737\/revisions\/822"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/media\/781"}],"wp:attachment":[{"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/media?parent=737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/categories?post=737"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.jonathanantoine.com\/wp-json\/wp\/v2\/tags?post=737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}