WPF控件的UI自动化测试似乎忽略了绑定

本文关键字:绑定 控件 UI 自动化测试 WPF | 更新日期: 2023-09-27 18:02:00

我目前正在尝试找出如何为我的WPF应用程序自动化UI测试,我有麻烦让它工作

MyControl的XAML(扩展了UserControl)包含以下CheckBox:

<CheckBox Name="IsFooCheckBox"
    IsChecked="{Binding Path=IsFoo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

绑定指向实现INotifyPropertyChanged的自定义数据上下文,并包含以下属性:

private bool _isFoo;
public bool IsFoo
{
   get { return _isFoo; }
   set
   {
      _isFoo = value;
      OnPropertyChanged("IsFoo");
   }
}

绑定在生产中工作(在调试器中可以看到_isFoo在我切换复选框时被更新)。

我想现在有一个测试,切换复选框并检查数据上下文是否更新(或检查在代码隐藏中实现的逻辑)。WPF UI自动化框架似乎正是我所寻找的,所以我写了下面的NUnit测试:

var myContext = ...
var sut = new MyControl
{
   DataContext = myContext
};
var peer = new CheckBoxAutomationPeer(sut.IsFooCheckBox);
var pattern = peer.GetPattern(PatternInterface.Toggle) as IToggleProvider;
pattern.Toggle();
Assert.That(sut.IsProvidingProfileCheckBox.IsChecked.Value); // works
Assert.That(myContext.IsFoo); // fails

当第一个Assert通过时,第二个失败了。我不明白为什么会这样……似乎忽略了XAML文件中的绑定,或者没有触发更新。有没有人有什么建议来修改我的测试?这可能吗?

WPF控件的UI自动化测试似乎忽略了绑定

问题从这里开始

public bool IsFoo
{
   get { return _IsFoo; }
   set
   {
      _isFoo = value;
      OnPropertyChanged("IsFoo");
   }
}

一旦调用了

pattern.Toggle();

你隐式调用IsFoo的setter,它引发PropertyChanged事件,并反过来强制刷新与IsFoo绑定相关的UI元素-长话短说,调用getter,而不是_isFoo它返回_isFoo。你搞错了变量。
尽量避免调用带有显式属性名的OnPropertyChanged方法。而不是使用CallerMemberName属性来检索属性名。

     public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;

那么你只需要下面的调用。

OnPropertyChanged();

我也遇到过类似的问题。我正在用以下代码填充文本框:

        ValuePattern valuePattern = promptBox.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
        valuePattern.SetValue(value);

根据文本框中的值,另一个按钮状态应该从Disabled变为Enabled。

我注意到在上面的自动化代码执行后,手动点击窗口会触发绑定来求值。

所以我添加了

    System.Windows.Forms.SendKeys.SendWait("{TAB}");

SetValue之后,它开始正常工作

我花了一些时间才弄明白这一点,但最终,它是很明显的,在互联网上的许多地方都有描述。我想只要你知道要找什么,一切都很容易了。

编码UI测试的问题是绑定不能自动解决。解析必须通过调用Window.ShowWindow来启动。

我扩展了测试并添加了以下代码片段:
Window window = new Window
{
    Content = sut // the control to test
};
window.Show();

添加这个调用立即修复了我在我的帖子中描述的奇怪的测试行为。

直接的后续问题是这个调用需要一个活动的UI线程。因此,让测试在持续集成环境中的构建服务器上运行可能比较棘手。但是,这取决于环境(特别是构建服务器),这是另一个问题。