2016-10-06 6 views
6

NUnit에서 시스템 테스트를 작성하려고하며 ms의 UI Automation을 사용하여 UI를 호출하려고합니다.NUnit 테스트에서 WPF 텍스트 상자에 대한 setter 호출 방법

내 호출이 실패합니다. 온라인에서 컴파일 테스트를 작성할 수 있지만 내 주장이 실패하는 상태에 이르는 힌트가 온라인에서 발견되었습니다.

다음은 컴파일 가능한 최소 예입니다. 내 문제는 예제에서 실패한 테스트입니다.

출원 XAML

<Application x:Class="InvokeTest.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:InvokeTest" 
      Startup="Application_Startup"/> 

출원 CS

using System.Windows; 

namespace InvokeTest 
{ 
    public partial class App : Application 
    { 
     private void Application_Startup(object sender, StartupEventArgs e) 
     { 
      var view = new MainWindow(); 
      var viewmodel = new MainWindowViewModel(); 
      view.DataContext = viewmodel; 
      view.Show(); 
     } 
    } 
} 

윈도우 XAML

<Window x:Class="InvokeTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:InvokeTest" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
<TextBox x:Name="MyTextBox" x:FieldModifier="public" Text="{Binding TextProperty, UpdateSourceTrigger=PropertyChanged}" /> 
</Window> 

창 CS

using NUnit.Framework; 
using System.Diagnostics; 
using System.Threading; 
using System.Windows; 
using System.Windows.Automation.Peers; 
using System.Windows.Automation.Provider; 
using System.Windows.Controls; 

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

    public class MainWindowViewModel 
    { 
     string textfield; 
     public string TextProperty 
     { 
      get { DebugLog("getter"); return textfield; } 
      set { textfield = value; DebugLog("setter"); } 
     } 

     private void DebugLog(string function) 
     { 
      Debug.WriteLine(ToString() + " " + nameof(TextProperty) + " " + function + " was called. value: '" + textfield ?? "<null>" + "'"); 
     } 

     [TestFixture, Apartment(ApartmentState.STA)] 
     public class WPFTest 
     { 
      MainWindow view; 
      MainWindowViewModel viewmodel; 

      [SetUp] 
      public void SetUp() 
      { 
       view = new MainWindow(); 
       viewmodel = new MainWindowViewModel(); 
       view.DataContext = viewmodel; 
      } 

      [Test] 
      public void SetTextBox_NoAutomation() 
      { 
       string expected = "I want to set this"; 
       view.MyTextBox.Text = expected; 
       Assert.AreEqual(expected, viewmodel.TextProperty); 
       /* 
       Test Name: SetTextBox_NoAutomation 
       Test Outcome: Failed 
       Result Message: 
       Expected: "I want to set this" 
       But was: null 
       */ 
      } 

      [Test] 
      public void SetTextBox_UIAutomation() 
      { 
       string expected = "I want to set this"; 
       SetValue(view.MyTextBox, expected); 
       Assert.AreEqual(expected, viewmodel.TextProperty); 
       /* 
       Test Name: SetTextBox_UIAutomation 
       Test Outcome: Failed 
       Result Message: 
       Expected: "I want to set this" 
       But was: null 
       */ 
      } 
      private static void SetValue(TextBox textbox, string value) 
      { 
       TextBoxAutomationPeer peer = new TextBoxAutomationPeer(textbox); 
       IValueProvider provider = peer.GetPattern(PatternInterface.Value) as IValueProvider; 
       provider.SetValue(value); 
      } 
     } 
    } 
} 

EDIT # 1 : @Nkosi가 내 xaml에 바인딩 오류가 있다고 지적했습니다.
EDIT # 2 : 수동 테스트가 가능한 보일러가 추가되었으며 자동 실행 기능이없는 동작을 보여주는 유스 케이스가 추가되었습니다. 그것은 단지 부업이며, 자문은이 질문의 핵심입니다.

+2

이미 알고 계실지 모르지만 단위 테스트는 실제로 UI를 테스트하도록 설계되지 않았습니다. 그것은 아마도 작업에 "해킹"될 수 있지만, 당신이가는 동안 당신은 시스템을 싸우게 될 것입니다. UI 테스트는 일반적으로 코드화 된 UI 테스트 및 스크립팅 된 통합 테스트의 일부로 수행됩니다. –

+0

@BradleyUffner 예. 알고 있습니다. 실제로 코드화 된 UI 테스트를 사용하지 않고도 자동으로 Google auto를 사용할 수 없습니다. 코드화 된 UI 테스트가 우수하다고 생각하지만 실제로는 좀 더 자세히 설명하고 싶습니다. – Johannes

답변

0

이 창을 표시해야합니다. 메시지 펌프를 실행하는 것으로 가정합니다.

누군가가 이에 대한 세부 정보를 제공 할 수 있다면 그 대답을 허용 된 대답으로 설정합니다.

using NUnit.Framework; 
using System.Diagnostics; 
using System.Threading; 
using System.Windows; 
using System.Windows.Automation.Peers; 
using System.Windows.Automation.Provider; 
using System.Windows.Controls; 

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

    public class MainWindowViewModel 
    { 
     string textfield; 
     public string TextProperty 
     { 
      get { DebugLog("getter"); return textfield; } 
      set { textfield = value; DebugLog("setter"); } 
     } 

     private void DebugLog(string function) 
     { 
      Debug.WriteLine(ToString() + " " + nameof(TextProperty) + " " + function + " was called. value: '" + textfield ?? "<null>" + "'"); 
     } 

     [TestFixture, Apartment(ApartmentState.STA)] 
     public class WPFTest 
     { 
      MainWindow view; 
      MainWindowViewModel viewmodel; 

      [SetUp] 
      public void SetUp() 
      { 
       view = new MainWindow(); 
       viewmodel = new MainWindowViewModel(); 
       view.DataContext = viewmodel; 
       view.Show(); 
      } 

      [TearDown] 
      public void TearDown() 
      { 
       view.Close(); 
       view.DataContext = null; 
       view = null; 
       viewmodel = null; 
      } 

      [Test] 
      public void SetTextBox_NoAutomation() 
      { 
       string expected = "I want to set this"; 
       view.MyTextBox.Text = expected; 
       Assert.AreEqual(expected, viewmodel.TextProperty); 
      } 

      [Test] 
      public void SetTextBox_UIAutomation() 
      { 
       string expected = "I want to set this"; 
       SetValue(view.MyTextBox, expected); 
       Assert.AreEqual(expected, viewmodel.TextProperty); 
      } 

      private void SetValue(TextBox textbox, string value) 
      { 
       TextBoxAutomationPeer peer = new TextBoxAutomationPeer(textbox); 
       IValueProvider provider = peer.GetPattern(PatternInterface.Value) as IValueProvider; 
       provider.SetValue(value); 
      } 
     } 
    } 
} 
+1

원래 버전의 바인딩은 AttachToContext가 아니라고 생각합니다. [바인딩은 DataContext가 이미 설정된 경우 UpdateLayout 메서드가 처음 호출 될 때 처음으로 해결됩니다.] (http : // stackoverflow.com/questions/13875537/when-are-data-bindings-applied) 두 번째 버전 인 view.Show는 UpdateLayout 이벤트를 트리거합니다. – zzczzc004

2

실제로 TextBox.Text Property으로 전화 할 수 있습니다. 테스트에서 뷰 모델은 MyTextBox 속성을 가지고있는 동안보기에

view.MyTextBox.Text = expected; 

당신은 또한 당신의보기 모델에 Text 속성에 바인딩된다. 하나 또는 다른 하나는 일치하도록 업데이트해야합니다.

public class MainWindowViewModel 
{ 
    public string Text { get; set; } 
} 

[TestFixture, Apartment(ApartmentState.STA)] 
public class WPFTest 
{ 
    [Test] 
    public void SetTextBox() 
    { 
     //Arrange 
     var expected = "I want to set this"; 

     var view = new MainWindow(); 
     var viewmodel = new MainWindowViewModel(); 
     view.DataContext = viewmodel; 

     //Act 
     view.MyTextBox.Text = expected; 

     //Assert 
     Assert.AreEqual(expected, viewmodel.Text); 
    } 
} 
+0

나는 바인딩 실패를 제기했다 (나는 생각한다 :)). 내 컴퓨터에서 내 제안이 작동하지 않습니다 - 실행할 수 있습니까? – Johannes

+0

오류가 있습니까? 그렇다면 그들은 무엇입니까? – Nkosi

+0

어설 션 이외의? 아니. – Johannes