Метод модульного тестирования, использующий элементы управления пользовательского интерфейса.

В настоящее время я пишу некоторые методы, которые выполняют некоторые основные операции с элементами управления формы, например Textbox, Groupbox, эти операции являются общими и могут использоваться в любом приложении.

Я начал писать несколько модульных тестов и просто задавался вопросом, следует ли мне использовать настоящие элементы управления формой, найденные в System.Windows.Forms, или я должен просто смоделировать разделы, которые я пытаюсь протестировать. Так, например:

Скажем, у меня есть этот метод, который принимает элемент управления, и если это текстовое поле, он очистит свойство текста следующим образом:

        public static void clearall(this Control control)
        {
            if (control.GetType() == typeof(TextBox))
            {
                ((TextBox)control).Clear();
            }
        }

Затем я хочу проверить этот метод, поэтому я делаю что-то вроде этого:

        [TestMethod]
        public void TestClear() 
        {
            List<Control> listofcontrols = new List<Control>();
            TextBox textbox1 = new TextBox() {Text = "Hello World" };
            TextBox textbox2 = new TextBox() { Text = "Hello World" };
            TextBox textbox3 = new TextBox() { Text = "Hello World" };
            TextBox textbox4 = new TextBox() { Text = "Hello World" };

            listofcontrols.Add(textbox1);
            listofcontrols.Add(textbox2);
            listofcontrols.Add(textbox3);
            listofcontrols.Add(textbox4);

            foreach (Control control in listofcontrols)
            {
                control.clearall();
                Assert.AreEqual("", control.Text);
            }
        }

Должен ли я добавлять ссылку на System.Window.Forms в мой модульный тест и использовать реальный объект Textbox? или я делаю это неправильно?

ПРИМЕЧАНИЕ. Приведенный выше код является лишь примером, я его не компилировал и не запускал.


person Nathan W    schedule 19.11.2008    source источник


Ответы (3)


Если вы пытаетесь выполнить модульное тестирование логики приложения, имитируя взаимодействие с элементами управления пользовательского интерфейса, вам следует сделать некоторую абстракцию, используя ссылку Шаблон MVC. Затем вы можете просто иметь представление-заглушку и вызывать методы контроллера из своих модульных тестов.

Если вы пытаетесь протестировать фактические элементы управления, вы меня поймали.

person Cristian Diaconescu    schedule 19.11.2008
comment
Согласен, тестировать .NET Framework бесполезно. Microsoft делает это уже в значительной степени :). - person Tigraine; 20.11.2008

Существует несколько шаблонов, полезных для отделения представления пользовательского интерфейса от логики пользовательского интерфейса, включая модель-представление-контроллер и различные воплощения модели-представления-презентатора (он же Humble Dialog). Humble Dialog был придуман специально для облегчения модульного тестирования. Вы обязательно должны иметь один из этих шаблонов пользовательского интерфейса в своем дизайнерском арсенале.

Но я обнаружил, что для простых форм, когда фреймворк поддерживает это, довольно просто протестировать непосредственно на реальных элементах управления пользовательского интерфейса. Я создал довольно надежные пользовательские интерфейсы, полностью протестированные в Java Swing и Windows.Forms. Я не мог управлять этим в SWT или ASP.NET и вернулся к MVP.

Для тестирования таких вещей...

[Test] public void ShouldCopyFromAvailableToSelectedWhenAddButtonIsCLicked(){
  myForm.AvailableList.Items.Add("red");
  myForm.AvailableList.Items.Add("yellow");
  myForm.AvailableList.Items.Add("blue");

  myForm.AvailableList.SelectedIndex = 1;
  myForm.AddButton.Click();

  Assert.That(myForm.AvaiableList.Items.Count, Is.EqualTo(2));
  Assert.That(myForm.SelectedList.Items[0], Is.EqualTo("yellow"));
}

...работа непосредственно с элементами управления пользовательского интерфейса работает нормально. Но если вы хотите начать тестировать движения мыши, нажатия клавиш или перетаскивание, вам лучше выбрать более надежный шаблон пользовательского интерфейса, такой как тот, который предложил Брайан.

person Community    schedule 19.11.2008

То, что вы предлагаете, даже не скомпилируется, если ваш код полагается на System.Windows.Forms.Control. Ваша версия Control и Textbox просто неправильного типа.

Если бы вместо этого вы разделили свой пользовательский интерфейс и логику с помощью интерфейсов, вы могли бы сделать это... Что-то вроде этого:

public interface ITextBox
{
    public string Text {get; set;}
}

public class TextBoxAdapter : ITextBox
{
    private readonly System.Windows.Forms.TextBox _textBox;
    public TextBoxAdapter(System.Windows.Forms.TextBox textBox)
    {
        _textBox = textBox;
    }

    public string Text
    {
        get { return _textBox.Text; }
        set { _textBox.Text = value; }
    }
}

public class YourClass
{
    private ITextBox _textBox;
    public YourClass(ITextBox textBox)
    {
        _textBox = textBox;
    }

    public void DoSomething()
    {
        _textBox.Text = "twiddleMe";
    }
}

Затем в вашем тесте все, что вам нужно сделать, это создать макет, подделку или заглушку ITextBox и передать его.

Когда я делаю что-то подобное, я создаю интерфейс немного более высокого уровня... Я создаю интерфейс, который очень похож на весь пользовательский интерфейс, и пользовательский интерфейс реализует этот интерфейс. Затем я могу крутить пользовательский интерфейс столько, сколько мне нужно, даже не зная, что это элемент управления Forms.

Кстати, если вы хотите пойти по пути создания фактических элементов управления, рассмотрите этот пост в блоге об этом: http://www.houseofbilz.com/archive/2008/10/12/winforms-automation-extensions.aspx

person Brian Genisio    schedule 19.11.2008