2017-02-21 1 views
0

J'utilise le framework TestStack White pour automatiser le test d'une application WPF Il doit ouvrir la fenêtre modale et y accéder TextBox. Tout fonctionne bien, mais blanc ne peut pas trouver Textbox, bien qu'il trouve d'autres éléments de la fenêtreTestStack White ne trouve pas TextBox dans WPF Application

J'ai essayé les lignes de code suivantes:

TestStack.White.UIItems.TextBox TextBox = CreateBranch.Get<TestStack.White.UIItems.TextBox>(SearchCriteria.byAutomationId("Title")); 

où CreateBranch est fenêtre modale

J'ai aussi essayé (SearchCriteria.All), (SearchCriteria.ByControlType) et rien ne fonctionne

outil UI Coded trouve cet élément bien par AutomationID, mais je dois le faire en blanc

UISpy et d'autres outils similaires reconnaissent ce contrôle et voir son AutomationID

Cette zone de texte est un contrôle personnalisé, voici ce code pour elle, je l'ai changé le nom d'espace de noms pour la vie privée:

using System; 
using System.ComponentModel; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Input; 
using System.Windows.Interactivity; 
using System.Windows.Media; 

namespace Test.Wpf.Controls.XTextBox 
{ 
    [TemplatePart(Name = "PART_Watermark", Type = typeof(TextBlock))] 
    [TemplatePart(Name = "PART_Pasword", Type = typeof(TextBlock))] 
    public class XTextBox : TextBox 
    { 
     #region Static 
     static XTextBox() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(XTextBox), new FrameworkPropertyMetadata(typeof(XTextBox))); 
     } 
     #endregion //Static 

     #region Fields 

     private TextBlock PART_Watermark; 
     private TextBlock PART_Pasword; 

     #endregion //Fields 

     #region DependencyProperties 

     public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
      "Watermark", 
      typeof(String), 
      typeof(XTextBox), 
      new PropertyMetadata(String.Empty)); 

     public static readonly DependencyProperty WatermarkVerticalAlignmentProperty = DependencyProperty.Register(
      "WatermarkVerticalAlignment", 
      typeof(VerticalAlignment), 
      typeof(XTextBox), 
      new PropertyMetadata(VerticalAlignment.Stretch)); 

     public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register(
      "WatermarkForeground", 
      typeof(Brush), 
      typeof(XTextBox), 
      new PropertyMetadata(new SolidColorBrush(Colors.Black))); 

     public static readonly DependencyProperty WatermarkFontSizeProperty = DependencyProperty.Register(
      "WatermarkFontSize", 
      typeof(Double), 
      typeof(XTextBox), 
      new PropertyMetadata(12.0)); 

     public static readonly DependencyProperty IsFloatingProperty = DependencyProperty.Register(
      "IsFloating", 
      typeof(Boolean), 
      typeof(XTextBox), 
      new PropertyMetadata(false)); 

     public static readonly DependencyProperty IsAccessNegativeProperty = DependencyProperty.Register(
      "IsAccessNegative", 
      typeof(Boolean), 
      typeof(XTextBox), 
      new PropertyMetadata(true)); 

     public static readonly DependencyProperty IsDigitOnlyProperty = DependencyProperty.Register(
      "IsDigitOnly", 
      typeof(Boolean), 
      typeof(XTextBox), 
      new PropertyMetadata(false)); 

     public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register(
      "MaxValue", 
      typeof(Single), 
      typeof(XTextBox), 
      new PropertyMetadata(Single.NaN)); 

     public static readonly DependencyProperty IsPasswordProperty = DependencyProperty.Register(
      "IsPassword", 
      typeof(Boolean), 
      typeof(XTextBox), 
      new PropertyMetadata(false)); 

     public static readonly DependencyProperty VisibilityMainTextProperty = DependencyProperty.Register(
      "VisibilityMainText", 
      typeof(Visibility), 
      typeof(XTextBox), 
      new PropertyMetadata(Visibility.Visible)); 

     #endregion //DependencyProperties 

     #region Properties 
     [Description("Gets or sets the watermark title")] 
     public String Watermark 
     { 
      get { return (String)GetValue(WatermarkProperty); } 
      set { SetValue(WatermarkProperty, value); } 
     } 

     [Description("Gets or sets the watermark vertical alignment")] 
     public VerticalAlignment WatermarkVerticalAlignment 
     { 
      get { return (VerticalAlignment)GetValue(WatermarkVerticalAlignmentProperty); } 
      set { SetValue(WatermarkVerticalAlignmentProperty, value); } 
     } 


     [Description("Gets or sets the watermark title color")] 
     public Brush WatermarkForeground 
     { 
      get { return (Brush)GetValue(WatermarkVerticalAlignmentProperty); } 
      set { SetValue(WatermarkVerticalAlignmentProperty, value); } 
     } 

     [Description("Gets or sets the watermark title font size")] 
     public Double WatermarkFontSize 
     { 
      get { return (Double)GetValue(WatermarkVerticalAlignmentProperty); } 
      set { SetValue(WatermarkVerticalAlignmentProperty, value); } 
     } 

     [Description("Gets or sets the textbox floating mode")] 
     public Boolean IsFloating 
     { 
      get { return (Boolean)GetValue(IsFloatingProperty); } 
      set { SetValue(IsFloatingProperty, value); } 
     } 

     [Description("Gets or sets the textbox access of negative values")] 
     public Boolean IsAccessNegative 
     { 
      get { return (Boolean)GetValue(IsAccessNegativeProperty); } 
      set { SetValue(IsAccessNegativeProperty, value); } 
     } 

     [Description("Gets or sets the textbox chars type")] 
     public Boolean IsDigitOnly 
     { 
      get { return (Boolean)GetValue(IsDigitOnlyProperty); } 
      set { SetValue(IsDigitOnlyProperty, value); } 
     } 

     [Description("Gets or sets the max input value (enable in digit mode only)")] 
     public Single MaxValue 
     { 
      get { return (Single)GetValue(MaxValueProperty); } 
      set { SetValue(MaxValueProperty, value); } 
     } 

     [Description("Gets or sets the textbox is passwordbox")] 
     public Boolean IsPassword 
     { 
      get { return (Boolean)GetValue(IsPasswordProperty); } 
      set { SetValue(IsPasswordProperty, value); } 
     } 

     public Visibility VisibilityMainText 
     { 
      get { return (Visibility)GetValue(VisibilityMainTextProperty); } 
      set { SetValue(VisibilityMainTextProperty, value); } 
     } 

     #endregion //Properties 

     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 
      PART_Watermark = GetTemplateChild("PART_Watermark") as TextBlock; 
      PART_Pasword = GetTemplateChild("PART_Pasword") as TextBlock; 
      SetWatermarkVisibility(); 
      if (IsPassword) 
      { 
       VisibilityMainText = Visibility.Collapsed; 
       if (PART_Pasword != null) 
       { 
        PART_Pasword.Visibility = Visibility.Visible; 
        PART_Pasword.FontSize = 20; 
       } 
      } 
      else 
      { 
       VisibilityMainText = Visibility.Visible; 
      } 

      DataObject.AddPastingHandler(this, OnPaste); 
     } 

     protected void OnPaste(Object sender, DataObjectPastingEventArgs e) 
     { 
      try 
      { 
       var isText = e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true); 
       if (!isText) return; 
       var text = e.SourceDataObject.GetData(DataFormats.UnicodeText) as String; 
       if (!String.IsNullOrEmpty(text)) 
       { 
        if (IsDigitOnly) 
        { 
         if (!IsAccessNegative) 
         { 
          var ch = text[0]; 
          if (ch == 45) 
          { 
           e.CancelCommand(); 
          } 
         } 
         for (int i = 0; i < text.Length; i++) 
         { 
          if (i == 0) 
          { 
           if (IsAccessNegative && text[i] == 45) 
           { 
            continue; 
           } 
          } 
          if (!Char.IsDigit(text[0])) 
           e.CancelCommand(); 
         } 
        } 
       } 
      } 
      catch (Exception) 
      { 
       // ignored 
       e.Handled = true; 
      } 
     } 

     protected override void OnTextChanged(TextChangedEventArgs e) 
     { 
      base.OnTextChanged(e); 
      SetWatermarkVisibility(); 
      if (IsPassword) 
      { 
       PART_Pasword.Text = new String('•', Text.Length); 
      } 
     } 

     protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) 
     { 
      base.OnLostKeyboardFocus(e); 
      SetWatermarkVisibility(); 
     } 

     protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) 
     { 
      base.OnGotKeyboardFocus(e); 
      if (PART_Watermark != null) 
      { 
       PART_Watermark.Visibility = Visibility.Hidden; 
      } 
     } 

     protected override void OnPreviewTextInput(TextCompositionEventArgs e) 
     { 
      base.OnPreviewTextInput(e); 
      if (e.Text.Length == 0) 
      { 
       e.Handled = true; 
       return; 
      } 
      if (IsDigitOnly) 
      { 
       var ch = e.Text[0]; 
       if (!Char.IsDigit(ch) && ch != 8 && ch != 46) 
       { 
        if (!(IsAccessNegative && ch == 45)) 
         e.Handled = true; 
       } 
       if (IsFloating) 
       { 
        if (ch == 46 && Text.IndexOf('.') != -1) 
        { 
         e.Handled = true; 
         return; 
        } 
       } 

       if (!IsAccessNegative) 
       { 
        if (ch == 45) 
        { 
         e.Handled = true; 
        } 
       } 
      } 
     } 

     #region Private 

     private void SetWatermarkVisibility() 
     { 
      if (PART_Watermark != null) 
      { 
       PART_Watermark.Visibility = (Text != String.Empty || IsKeyboardFocused)? Visibility.Hidden : Visibility.Visible; 
      } 
     } 
     #endregion 
    } 
} 

Screenshot from UISpy

+0

Pouvez-vous poster le code pour trouver la fenêtre ainsi qu'une capture d'écran de sortie UISpys pour la zone de texte en question? Je trouve généralement que lorsque je ne peux pas trouver un contrôle sur une fenêtre, j'ai accidentellement trouvé une autre fenêtre. Généralement les fenêtres finissent par être des pointes d'outils ou quelque chose de similaire. –

+0

application = TestStack.White.Application.Launch (Chemin d'application); TestStack.White.UIItems.WindowItems.Window mainWindow = application.GetWindow (SearchCriteria.ByText ("title"), TestStack.White.Factory.InitializeOption.NoCache); // puis faites des actions pour ouvrir la fenêtre modale et quand elle est ouverte TestStack.White.UIItems.WindowItems.Window CreateBranch = mainWindow.ModalWindow (SearchCriteria.All); Ajouté une capture d'écran. Edit a deux barres de défilement mais elles ne sont pas utilisées. Lorsque j'ai essayé d'utiliser le conseil de DLDR avec l'ajout de AutomationPeer, le contrôle reconnu comme personnalisé, pas Modifier –

Répondre

0

Permettez-moi savoir si cela fonctionne

TextBox = (TextBox)CreateBranch 
     .Get(SearchCriteria.ByAutomationId("Title").AndOfFramework(WindowsFramework.Wpf)); 

Ed ité après nouvelle source ajouté

Vous devez créer un AutomationPeer spécifique pour votre contrôle personnalisé et le retourner par la substitution de la méthode OnCreateAutomationPeer().

Votre contrôle est une sous-classe du contrôle TextBox. Vous pouvez donc renvoyer une nouvelle instance TextBoxAutomationPeer ou créer votre AutomationPeer personnalisé.

public class XTextBox : TextBox 
{ 
... 
    protected override AutomationPeer OnCreateAutomationPeer() 
    { 
     return new XTextBoxAutomationPeer(this); 
     // or just use the TextBoxAutomationPeer 
     // return new TextBoxAutomationPeer(this); 
    } 
... 
} 

L'automatisation personnalisé par les pairs

public class XTextBoxAutomationPeer : TextBoxAutomationPeer 
{ 
    public XTextBoxAutomationPeer(XTextBox owner) 
     : base(owner) 
    { 
    } 

    protected override string GetClassNameCore() 
    { 
     return "XTextBox"; 
    } 
} 
+0

Non, cela ne fonctionne pas –

+0

Votre zone de texte est-elle un contrôle personnalisé? Pourriez-vous fournir le code XAML? – DLDR

+0

Voici le code XAML: Et il y a XTextBox. cs, donc c'est un contrôle personnalisé. Comment puis-je travailler avec le contrôle standrard ou que puis-je faire d'autre? –

0
[SetUpFixture] 
    public class SETUP_THAT_WILL_GET_CALL_LATER 
    { 
     [OneTimeSetUp] 
     public void OneTimeSetUp() 
     { 
      var applicationDirectory = TestContext.CurrentContext.TestDirectory; 
      var applicationPath = Path.Combine(applicationDirectory, @"..\..\..\, "your debug folder path here", "your application.exe here"); 
      Application = Application.Launch(applicationPath); 

      Thread.Sleep(2000); 

      Window = Application.GetWindow("Title of your application", InitializeOption.WithCache); 
     } 

     [OneTimeTearDown()] 
     public void OneTimeTearDown() 
     { 
      Window.Dispose(); 
      Application.Dispose(); 
     } 

     public static Application Application; 
     public static Window Window; 
    } 

Ensuite, dans votre test

[Test] 
public void yourtest() 
{ 
    var textBox = SETUP_THAT_WILL_GET_CALL_LATER.**Window.Get<TextBox>("Your textbox name here");** 

} 
+0

Il semble que mon code, pour le lancement de l'application et que les fenêtres, mais le sommeil n'aide pas –

+0

hmmm essayer de faire threadsleep (5000) ... si ça ne fonctionne toujours pas, je vais essayer de trouver d'autres solutions pour votre problème – user7583356

+0

Ajout de sommeil plus long après chaque étape, n'aide pas –