当应用程序通过UI自动化测试开始,但其时可见应用程序通过用户开始ContentControl中是不可见的 [英] ContentControl is not visible when application starts via UI Automation test, but its visible when application starts by user

查看:170
本文介绍了当应用程序通过UI自动化测试开始,但其时可见应用程序通过用户开始ContentControl中是不可见的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用的棱镜和WPF来构建应用程序。最近,我们开始使用UI自动化(UIA)来测试我们的应用程序。但是,一些奇怪的行为时有发生,我们运行UIA测试。这里的简化壳:

We are using the prism and WPF to build application. Recently we started using UI Automation (UIA) to test our app. But some strange behavior occurred when we run UIA test. Here's simplified shell:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>    
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <TextBlock 
        Grid.Row="0" Grid.Column="0"
        Name="loadingProgressText"
        VerticalAlignment="Center" HorizontalAlignment="Center"
        Text="Loading, please wait..."/>

    <Border
        Grid.Row="0" 
        x:Name="MainViewArea">
        <Grid>
            ...
        </Grid>
    </Border>

    <!-- Popup -->
    <ContentControl 
        x:Name="PopupContentControl"
        Grid.Row="0" 
        prism:RegionManager.RegionName="PopupRegion"
        Focusable="False">
    </ContentControl>

    <!-- ErrorPopup -->
    <ContentControl 
        x:Name="ErrorContentControl"
        Grid.Row="0" 
        prism:RegionManager.RegionName="ErrorRegion"
        Focusable="False">
    </ContentControl>
</Grid>

在我们的应用程序,我们使用层(弹出 ErrorPopup )隐藏的 MainViewArea ,以拒绝访问控制。为了展示弹出,我们用下一个方法:

In our app, we use layers (Popup and ErrorPopup) to hide MainViewArea, to deny access to the controls. To show Popup, we use next method:

    //In constructor of current ViewModel we store _popupRegion instance to the local variable:
    _popupRegion = _regionManager.Regions["PopupRegion"];
    //---

    private readonly Stack<UserControl> _popups = new Stack<UserControl>();
    public void ShowPopup(UserControl popup)
    {
        _popups.Push(popup);

        _popupRegion.Add(PopupView);
        _popupRegion.Activate(PopupView);
    }

    public UserControl PopupView
    {
        get
        {
            if (_popups.Any())
                return _popups.Peek();
            return null;
        }
    }



与此类似,我们显示 ErrorPopup 在我们的应用程序的所有元素:

Similar to this, we show ErrorPopup over all elements of our application:

    // In constructor we store _errorRegion:
    _errorRegion = _regionManager.Regions["ErrorRegion"]
    // --- 

    private UserControl _error_popup;

    public void ShowError(UserControl popup)
    {
        if (_error_popup == null)
        {
            _error_popup = popup;
            _errorRegion.Add(_error_popup);
            _errorRegion.Activate(_error_popup);
        }
    }



Mistics ...

当我们运行它,因为用户这样做(在应用程序图标双击),我们可以看到两个自定义控件(使用 AutomationElement.FindFirst 的方法,或者通过视觉UI自动化验证)。但是,当我们开始使用UI自动化测试 - 从控制树 ErrorPopup 在前看不见。我们试图启动这样的应用程序:

When we run it as users do it (double click on app icon), we can see both custom controls (using AutomationElement.FindFirst method, or through Visual UI Automation Verify). But when we start it using UI Automation test - ErrorPopup disapears from the tree of the controls. We trying to start the application like this:

System.Diagnostics.Process.Start(pathToExeFile);



我认为,我们错过了什么。不过什么?

I think that we missed something. But what?

修改#1

由于@chrismead说,我们试图运行我们的 UseShellExecute 应用标志设置为true,但这并没有帮助。但是,如果我们开始从 CMD 行应用程序,并手动点击按钮,弹出 ErrorPopup 在自动化控制树可见。

As @chrismead said, we tried to run our app with UseShellExecute flag set to true, but this does not help. But if we start app from cmd line, and manually click the button, Popup and ErrorPopup are visible in automation controls tree.

    Thread appThread = new Thread(delegate()
        {
            _userAppProcess = new Process();
            _userAppProcess.StartInfo.FileName = pathToExeFile;
            _userAppProcess.StartInfo.WorkingDirectory = System.IO.Directory.GetCurrentDirectory();
            _userAppProcess.StartInfo.UseShellExecute = true;
            _userAppProcess.Start();

        });
        appThread.SetApartmentState(ApartmentState.STA);
        appThread.Start();



我们的一个建议是,当我们使用方法的FindAll 的FindFirst 搜索按钮,单击,窗口莫名其妙缓存的UI自动化状态,并且不更新它。

One of our suggestion is when we use method FindAll or FindFirst to search the button to click, window somehow cached its UI Automation state, and does not update it.

编辑#2
我们已经发现,棱镜库的扩展方法 IRegionManager.RegisterViewWithRegion(RegionNames.OurRegion的typeof(Views.OurView))有一些奇怪的行为。如果我们停止使用它,这解决我们的问题格外。现在我们能看到ErrorView和 PopupContentControl 任何形式的看法,和应用程序更新UIA元素树结构。但是,这不是一个答案 - 只要停止使用该功能

Edit #2 We have find, that extension method of prism library IRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView)) have some strange behavior. If we stopped use it, this solve our problem particulary. Now we able to see ErrorView and any kind of view in PopupContentControl, and application updates UIA elements tree structure. But this is not an answer - "Just stop use this feature"!

MainViewArea 我们有一个<$! C $ C> ContentControl中,根据用户的操作而更新它的内容,我们可以看到只有第一个加载用户控件 ContentControl.Content 属性。这是这样进行的:

In MainViewArea we have a ContentControl, which updates it content depending on user actions, and we are able to see only the first loaded UserControl to that ContentControl.Content property. This is performed like this:

IRegionManager regionManager = Container.Resolve<IRegionManager>();
regionManager.RequestNavigate(RegionNames.MainContentRegion, this.Uri);



而如果我们改变了看法,没有更新将在UI Automation树进行 - 第一加载视图将在它来代替。但在视觉上我们观察到另一个查看 WPFInspector 说明它正确(它不显示UI自动化树),但Inspect.exe - 不是

And if we change the view, no updates will performed in UI Automation tree - the first loaded view will be in it instead. But visually we observe another View, and WPFInspector shows it properly (its show not a UI Automation tree), but Inspect.exe - not.

另外我们建议该窗口使用某种缓存是错误的 - 在缓存UI自动化客户端,我们必须明确地打开,但我们不这样做。

Also our suggestion that window use some kind of caching is wrong - caching in UI Automation client we have to turn on explicitly, but we don't do it.

推荐答案

我很抱歉,我已经错过了一些细节,这是关键的答案。我认为,这不是重要的事情。不管怎样。

I'm sorry that I've missed some detail, that was the key to the answer. I think that it was not important thing. Anyway.

我们使用的NavBar 的DevExpress 控制对于 WPF <库/ STRONG>。当的NavBar 是存在的,动态创建的视图不在UI Automation树出现什么结果证明,是。当从窗口中删除它,没有看到所有动态加载的观点的能力。什么是的NavBar - 仍然MISTIC我

We used NavBar from DevExpress controls library for WPF. What turns out, is when NavBar is present, dynamically created views are not appears on the UI Automation tree. When remove it from the window, there was an ability to see all dynamically loaded views. What does the NavBar - still mistic for me.

下面鲜艳的例子来看看发生了什么,如果NavBar是存在或缺失窗口(DevExpress的需要)

Here bright example to see what happened, if NavBar is present or absent on the Window (DevExpress is required).

MainWindow.xaml:

MainWindow.xaml:

<Window xmlns:dxn="http://schemas.devexpress.com/winfx/2008/xaml/navbar"
        x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        >
    <Grid Name="ContentGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <!--Comment NavBar to see dynamic control in UI Automation tree-->
        <dxn:NavBarControl Name="asdasd">
            <dxn:NavBarControl.Groups>
                <dxn:NavBarGroup Header="asdasdasdasd" />
            </dxn:NavBarControl.Groups>
        </dxn:NavBarControl>
        <TextBox Grid.Column="1" Name="Statictb" Text="static is visible in ui automation tree" />
        <Button Grid.Row="1" Content="Create controls" Height="25"  Click="Button_Click"/>
    </Grid>
</Window>



MainWindow.xaml.cs

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        TextBox tb = new TextBox();
        Grid.SetRow(tb, 1);
        Grid.SetColumn(tb, 1);
        tb.Text = "dynamic is not visible, if NavBar here...";
        ContentGrid.Children.Add(tb);
    }
}



修改

据对他们的支持的 DevExpress的答案网站:

According to the DevExpress answer on their support site:

之后,自动化的事件监听可能会导致性能问题。我们已决定以清除自动化事件的调用列表来解决它。在您的具体情况,你需要禁用清除。要做到这一点,请设置静态DevExpress.Xpf.Core.ClearAutomationEventsHelper.IsEnabled属性在Window构造假。

After a peer is created, listening of automation events may cause performance issues. We have decided to clear invocation lists of automation events to resolve it. In your specific situation, you need to disabling clearing. To do it, please set the static DevExpress.Xpf.Core.ClearAutomationEventsHelper.IsEnabled property to False in the Window constructor.

这解决问题

这篇关于当应用程序通过UI自动化测试开始,但其时可见应用程序通过用户开始ContentControl中是不可见的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆