2015-07-09 1 views
0

В настоящее время я пытаюсь выяснить, как автоматизировать тестирование пользовательского интерфейса для моего приложения WPF, и у меня возникли проблемы с его работой.UI автоматизации тестирования элементов управления WPF, кажется, игнорирует привязки

Часть XAML из MyControl (который простирается 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 Automation, кажется, именно то, что я ищу, так что я написал следующий 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 игнорируется или что обновление не запускается. Есть ли у кого-нибудь предложение, как исправить мой тест? Возможно ли это?

ответ

0

Мне потребовалось некоторое время, чтобы понять это, но, в конце концов, это очевидно и описано во многих местах по всему Интернету. Я думаю, все легко, как только вы знаете, что искать ...

Проблема кодированных тестов пользовательского интерфейса заключается в том, что привязки не разрешаются автоматически. Решение должно быть инициировано по телефону Window.ShowWindow.

Я продлил мое испытание и добавил следующий фрагмент:

Window window = new Window 
{ 
    Content = sut // the control to test 
}; 
window.Show(); 

Добавление этот вызов мгновенно исправили странное поведение тест, который я описал в моем посте.

Прямая проблема с последующим наблюдением заключается в том, что для этого вызова требуется активный поток пользовательского интерфейса. Из-за этого было бы сложно получить тест для запуска на сервере сборки в непрерывной среде интеграции. Однако это зависит от среды (особенно сервер сборки) и представляет собой другой вопрос.

0

Издание берет свое начало здесь

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

После того, как вы сослались

pattern.Toggle(); 

неявно вызвать сеттер IsFoo который поднимает PropertyChanged событие и в свою очередь силы, чтобы обновить элементы пользовательского интерфейса, которые связывания, связанные с IsFoo - вырезать длинную историю, вызывается геттер и вместо _isFoo он возвращает _IsFoo. Вы ошибаетесь.
Старайтесь не вызывать метод OnPropertyChanged с явным именем свойства. Вместо этого используется Атрибут CallerMemberName, который извлекает имя свойства.

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

     public event PropertyChangedEventHandler PropertyChanged; 

Тогда вам нужно только под вызовом.

OnPropertyChanged(); 
+0

Я не понимаю часть «вместо _isFoo, она возвращает _IsFoo» ... Я предполагаю, что это опечатка, но даже если это должно быть «IsFoo», я не понимаю ... значение ' _isFoo' устанавливается перед вызовом OnPropertyChange. Почему это должно быть проблемой? Как я уже сказал, элемент управления работает в пользовательском интерфейсе, он просто не работает в тесте. (И побочная заметка, которая не связана с вопросом: использование [CallerMemberName] - хорошая идея, но я должен оставаться совместимым с .net 4.0, поэтому я не могу использовать его ...) – Seb

+0

Только что понятная опечатка уже существует в вопрос ... извините, я отредактировал это сейчас. – Seb

+0

Он вызывается OnPropertyChanged, затем в свою очередь был вызван getter, который возвращает unset IsFoo = false, а false отправлен в CheckBox, и поскольку он был проверен, но получил false, свойство было изменено и еще один вызов времени был вызван. Он все еще не работает? – Maximus

0

У меня была аналогичная проблема. Я заселение текстового поля с помощью следующего кода:

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

И в зависимости от значения в текстовом поле, другое состояние кнопки должен было изменить с Невозможе Включено.

Я заметил, что после выполнения вышеописанного кода автоматизации щелкнув по окну вручную, связанное с привязкой для оценки.

Так что я просто добавил

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

после SetValue и он начал работать нормально.

+0

Извините, но это звучит скорее как взломать, чем решение. :) Тем временем я уверен, что основной причиной является отсутствие вызова «Window.ShowWindow». Возможно, ваше решение работает так же, потому что ваш имитируемый нажатие клавиши транзитивно вызывает один и тот же вызов метода, но я предпочитаю наиболее очевидное решение. – Seb