2008-12-01 2 views
10

Я пытаюсь выполнить тестирование тестовых данных WPF с помощью тестового макета, предоставленного системой Team Team. Я хотел бы иметь возможность проверить привязки, не показывая окно, потому что большинство моих тестов будут для пользовательских элементов управления, а не на самом деле в окне. Возможно ли это или есть лучший способ сделать это? Код ниже работает, если я покажу это окно, но если этого не произойдет, привязки не будут обновляться.Узел тестирования WPF Bindings

  Window1_Accessor target = new Window1_Accessor(); 
      UnitTestingWPF.Window1_Accessor.Person p = new UnitTestingWPF.Window1_Accessor.Person() { FirstName = "Shane" }; 
      Window1 window = (target.Target as Window1); 
      window.DataContext = p;   
      //window.Show(); //Only Works when I actually show the window 
      //Is it possible to manually update the binding here, maybe? Is there a better way? 
      Assert.AreEqual("Shane", target.textBoxFirstName.Text); //Fails if I don't Show() the window because the bindings aren't updated 

ответ

2

Шейн, если вы действительно беспокоитесь о том, что привязка ломается тихо, вам следует взглянуть на перенаправление следов привязки туда, где вы можете исследовать. Я хотел бы начать здесь:

http://blogs.msdn.com/mikehillberg/archive/2006/09/14/WpfTraceSources.aspx

Кроме того, я согласен с Gishu что привязок не являются хорошими кандидатами для модульного тестирования, в основном за счет Automagic происходит на этом Gishu упоминается в «Эпилог». Вместо этого сосредоточьтесь на том, чтобы убедиться, что базовый класс ведет себя правильно.

Заметим также, что вы можете получить еще более надежные следы, используя класс PresentationTraceSources:

http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.aspx

Надежда, что помогает!

1

Eyeball it.
Этот вид декларативной разметки редко ломается. Если кто-то не входит в руководство и не закручивает его. Даже тогда вы можете исправить это в течение нескольких минут. ИМХО стоимость написания таких тестов намного превышает преимущества.

Обновление [Dec3,08]: Тогда же.
Тест просто проверяет, что текстовое поле имеет значение «FirstName» как свойство Path привязки. Если я изменяю/рефакторизую FirstName на JustName в фактическом объекте источника данных, тест все равно пройдет, поскольку он тестирует анонимный тип. (Зеленый тест, когда код сломана - TDD антипаттерн: Лжец) Если ваша цель состоит в том, чтобы убедиться, что FirstName было указано в XAML,

Assert.AreEqual("FirstName", txtBoxToProbe.GetBindingExpression(TextBox.TextProperty).ParentBinding.Path.Path); 

Если вы действительно должны поймать сломанные привязок через блок тестов (и не хотите показать пользовательский интерфейс), используйте реальный источник данных ... борется какое-то время и придумал это.

[Test] 
public void TestTextBoxBinding() 
{ 
    MyWindow w = new MyWindow(); 
    TextBox txtBoxToProbe = w.TextBox1; 
    Object obDataSource = w;    // use 'real' data source 

    BindingExpression bindingExpr = BindingOperations.GetBindingExpression(txtBoxToProbe, TextBox.TextProperty); 
    Binding newBind = new Binding(bindingExpr.ParentBinding.Path.Path); 
    newBind.Source = obDataSource; 
    txtBoxToProbe.SetBinding(TextBox.TextProperty, newBind); 

    Assert.AreEqual("Go ahead. Change my value.", txtBoxToProbe.Text); 
} 

Эпилог: Там какая-то real covert stuff происходит в вызове Window.Show(). Это как-то волшебным образом устанавливает свойство DataItem, после которого начинает работать привязка данных.

// before show 
bindingExpr.DataItem => null 
bindingExpr.Status => BindingStatus.Unattached 

// after show 
bindingExpr.DataItem => {Actual Data Source} 
bindingExpr.Status => BindingStatus.Active 

После Binding активен, я думаю, вы можете заставить обновления TextBox с помощью кода, как это ..

txtBoxToProbe.GetBindingExpression(TextBox.TextProperty).UpdateTarget(); 

Еще раз выразить свое нежелание против такого подхода. Получение NUnit для запуска в STA было больно.

+2

Если мы являемся обязательными для свойств в классе, и реорганизовать класс, то XAML будет компилироваться, но исключение не будет выброшено и наше приложение не будет больше работать неправильно, как привязки будут некорректными. Это уже проблема для нас, поэтому мы ищем решение. – NotDan 2008-12-02 15:48:23

0

вы можете попробовать Guia. С его помощью вы можете провести тестирование вашего UserControl и проверить правильность привязки данных. Однако вы должны показать окно.

Вот пример.Он запускает новый экземпляр вашего UserControl и устанавливает его DataContext, а затем проверяет, установлено ли в текстовом поле правильное значение.

[TestMethod] 
    public void SimpleTest() 
    { 
     var viewModel = new SimpleControlViewModel() {TextBoxText = "Some Text"}; 

     customControl = CustomControl.Start<SimpleUserControl>((control) => control.DataContext = viewModel); 

     Assert.AreEqual("Some Text", customControl.Get<TextBox>("textbox1").Value); 

     customControl.Stop(); 
    } 
1

Сочетание рекомендаций Я столкнулся с несколькими сообщениями SO, которые я написал следующий класс, который очень хорошо работает, чтобы проверить привязки WPF.

public static class WpfBindingTester 
{ 
    /// <summary>load a view in a hidden window and monitor it for binding errors</summary> 
    /// <param name="view">a data-bound view to load and monitor for binding errors</param> 
    public static void AssertBindings(object view) 
    { 
     using (InternalTraceListener listener = new InternalTraceListener()) 
     { 
      ManualResetEventSlim mre = new ManualResetEventSlim(false); 

      Window window = new Window 
      { 
       Width = 0, 
       Height = 0, 
       WindowStyle = WindowStyle.None, 
       ShowInTaskbar = false, 
       ShowActivated = false, 
       Content = view 
      }; 

      window.Loaded += (_, __) => mre.Set(); 
      window.Show(); 

      mre.Wait(); 

      window.Close(); 

      Assert.That(listener.ErrorMessages, Is.Empty, listener.ErrorMessages); 
     } 
    } 

    /// <summary>Is the test running in an interactive session. Use with Assume.That(WpfBindingTester.IsAvailable) to make sure tests only run where they're able to</summary> 
    public static bool IsAvailable { get { return Environment.UserInteractive && Process.GetCurrentProcess().SessionId != 0; } } 


    private class InternalTraceListener : TraceListener 
    { 
     private readonly StringBuilder _errors = new StringBuilder(); 
     private readonly SourceLevels _originalLevel; 
     public string ErrorMessages { get { return _errors.ToString(); } } 

     static InternalTraceListener() { PresentationTraceSources.Refresh(); } 

     public InternalTraceListener() 
     { 
      _originalLevel = PresentationTraceSources.DataBindingSource.Switch.Level; 
      PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error; 
      PresentationTraceSources.DataBindingSource.Listeners.Add(this); 
     } 

     public override void Write(string message) {} 

     public override void WriteLine(string message) { _errors.AppendLine(message); } 

     protected override void Dispose(bool disposing) 
     { 
      PresentationTraceSources.DataBindingSource.Listeners.Remove(this); 
      PresentationTraceSources.DataBindingSource.Switch.Level = _originalLevel; 
      base.Dispose(disposing); 
     } 
    } 
} 
4

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

Техника очень проста:

  1. Наследуйте TraceListener, генерирующий вместо лесозаготовок
  2. Добавим, что слушатель PresentationTraceSources.DataBindingSource

Пожалуйста, смотрите complete solution on GitHub, она включает в себя блок тестовый проект.

Failed test in Visual Studio

 Смежные вопросы

  • Нет связанных вопросов^_^