2016-10-06 13 views
6

Tôi cố gắng viết hệ thống kiểm tra trong NUnit và tôi muốn gọi giao diện người dùng bằng cách sử dụng tự động hóa giao diện người dùng từ ms.Làm thế nào để gọi một setter cho một hộp văn bản WPF trong một thử nghiệm NUnit

Vì lý do nào đó mà lời gọi của tôi không thành công - tôi đã tìm thấy một số gợi ý trực tuyến đã đưa tôi đến trạng thái mà tôi có thể viết bài kiểm tra biên dịch nhưng xác nhận của tôi không thành công.

Dưới đây là ví dụ tối thiểu có thể biên dịch được. Vấn đề của tôi là thử nghiệm thất bại trong ví dụ.

Ứng dụng 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"/> 

Application 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(); 
     } 
    } 
} 

Window 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> 

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 đã chỉ ra rằng có một lỗi liên kết trong xaml
EDIT # 2 của tôi: Thêm một chút nồi hơi để cho phép kiểm tra thủ công và cũng thêm một usecase cho thấy hành vi mà không uiautomation. Đó chỉ là một phần phụ, uiautomation là cốt lõi của câu hỏi này.

+2

Hy vọng bạn đã biết điều này, nhưng kiểm tra đơn vị không thực sự được thiết kế để kiểm tra giao diện người dùng. Nó có thể có thể bị "hack" để làm việc, nhưng bạn sẽ kết thúc chiến đấu với hệ thống khi bạn đi. Kiểm tra giao diện người dùng thường được thực hiện như một phần của Kiểm tra giao diện người dùng được mã hóa và thử nghiệm tích hợp theo kịch bản. –

+0

@BradleyUffner yeah tôi biết :) Nó thực sự là phổ biến đến mức bạn không thể tự động google ui autoamtion mà không cần nhấn vào các thử nghiệm UI được mã hóa. Tôi nghĩ rằng thử nghiệm giao diện người dùng mã hóa là cấp trên nhưng tôi muốn đi sâu vào uiautomation một chút. – Johannes

Trả lời

0

Tôi cần hiển thị cửa sổ. Tôi cho rằng đó là để máy bơm thông báo hoạt động.

Nếu ai đó có thể cung cấp Chi tiết về điều này, tôi sẽ đặt câu trả lời đó làm câu trả lời được chấp nhận.

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

Tôi nghĩ rằng phiên bản gốc mà ràng buộc không phải là AttachToContext. [Việc ràng buộc nhiều khả năng sẽ được giải quyết lần đầu tiên khi phương thức UpdateLayout được gọi lần đầu tiên, nếu DataContext đã được thiết lập.] (Http: // stackoverflow.com/questions/13875537/khi-are-data-bindings-apply) Phiên bản thứ hai của view.Show sẽ kích hoạt sự kiện UpdateLayout. – zzczzc004

2

Thực ra bạn có thể gọi số TextBox.Text Property.

view.MyTextBox.Text = expected; 

Theo quan điểm của bạn, bạn cũng có hiệu lực đối Text tài sản trên mô hình quan điểm của bạn trong khi mô hình điểm trong bài kiểm tra của bạn có một tài sản MyTextBox. Một hoặc khác cần phải được cập nhật để phù hợp.

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

Tôi đã gửi lỗi liên kết (tôi nghĩ :)). Đề xuất của bạn không hoạt động trên máy của tôi - bạn có thể chạy nó không? – Johannes

+0

Bạn có gặp bất kỳ lỗi nào không? Nếu vậy, chúng là gì? – Nkosi

+0

ngoài xác nhận? Không. – Johannes

Các vấn đề liên quan