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文件中的绑定,或者没有触发更新。有没有人有什么建议来修改我的测试?这可能吗?
问题从这里开始
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线程。因此,让测试在持续集成环境中的构建服务器上运行可能比较棘手。但是,这取决于环境(特别是构建服务器),这是另一个问题。