TestStack White在WPF应用程序

时间:2017-02-21 13:03:48

标签: c# wpf automated-tests white

我使用TestStack White框架自动测试WPF应用程序 它需要打开模态窗口并访问其中的TextBox。一切都很好,但是White找不到Textbox,虽然它找到了窗口的其他元素

我尝试了以下几行代码:

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

其中CreateBranch是模态窗口

我也尝试过(SearchCriteria.All),(SearchCriteria.ByControlType)并且没有任何作用

编码的UI工具很好地通过AutomationID找到了这个元素,但我需要在White

中完成

UISpy和其他类似工具识别此控件并查看其AutomationID

这个文本框是自定义控件,这里是代码,我为隐私更改了命名空间名称:

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

2 个答案:

答案 0 :(得分:1)

如果有效,请告诉我

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

在新来源添加后编辑

您必须为自定义控件创建特定的AutomationPeer,并通过覆盖方法OnCreateAutomationPeer()将其返回。

您的控件是TextBox控件的子类,因此您只需返回一个新的TextBoxAutomationPeer实例或从中创建自定义AutomationPeer。

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

自定义自动化同行

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

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

答案 1 :(得分: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;
    }

然后在你的测试中

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

}