Рекомендации по модульному тестированию приложения Windows Forms - PullRequest
21 голосов
/ 01 февраля 2012

Я написал приложение для Windows Forms, и теперь я хочу написать для него несколько модульных тестов (не совсем на основе тестовой разработки, поскольку я пишу тесты после того, как разработал, но лучше поздно, чем никогда!) Мой вопрос заключается в том, что с такое приложение, как вы пишете модульные тесты, учитывая, что почти все методы и события являются частными? Я слышал о NUnit Forms, но слышал о хороших и плохих вещах, а также некоторое время не было реального развития этого проекта, поэтому он выглядит заброшенным. Также общепринятым является то, что в проекте имеется адекватное модульное тестирование, если я написал тестовые примеры для всех событий, которые пользователь будет вызывать нажатием / нажатием кнопок, или мне нужно было бы написать и написать модульные тесты для всех методы и найти способ проверить мои личные методы?

РЕДАКТИРОВАТЬ: Моя бизнес-логика отделена от моей логики представления, есть 1 или 2 открытых метода, которые моя бизнес-логика предоставляет, чтобы форма могла получить к ним доступ, но как насчет всех частных методов, которые находятся в бизнес логика?

Ответы [ 6 ]

27 голосов
/ 01 февраля 2012

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

Шаблоны проектирования, такие как Model View Presenter и Model View Controller может помочь при проектировании такой системы.

Для примера:

public partial class Form1 : Form, IMyView
{
    MyPresenter Presenter;
    public Form1()
    {
        InitializeComponent();
        Presenter = new MyPresenter(this);
    }

    public string SomeData
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            MyTextBox.Text = value;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Presenter.ChangeData();
    }
}

public interface IMyView
{
    string SomeData { get; set; }
}

public class MyPresenter
{
    private IMyView View { get; set; }
    public MyPresenter(IMyView view)
    {
        View = view;
        View.SomeData = "test string";
    }

    public void ChangeData()
    {
        View.SomeData = "Some changed data";
    }
}

Как видите, форма имеет только некоторыекод инфраструктуры к твоему все вместе.Вся ваша логика находится внутри вашего класса Presenter, который знает только об интерфейсе View.

Если вы хотите выполнить модульное тестирование, вы можете использовать инструмент Mocking, такой как Rhino Mocks , чтобы смоделировать интерфейс View ипередать это своему докладчику.

[TestMethod]
public void TestChangeData()
{
    IMyView view = MockRepository.DynamickMock<IMyView>();
    view.Stub(v => v.SomeData).PropertyBehavior();

    MyPresenter presenter = new MyPresenter(view);

    presenter.ChangeData();

    Assert.AreEqual("Some changed data", view.SomeData);
}
17 голосов
/ 01 февраля 2012

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

Теперь это может оставить некоторые непроверенные функции, специфичные для формы. Т.е. правильно ли подключена форма к сервису? Для этого вы можете рассмотреть что-то вроде NUnit Forms или другой альтернативы.

5 голосов
/ 01 февраля 2012

У вас есть несколько вариантов.

  1. Используйте инструмент, подобный Coded UI, для тестирования через пользовательский интерфейс.Это не лучший вариант, потому что он медленнее, чем модульное тестирование, и тесты, как правило, более хрупкие.

  2. Отделите свою бизнес-логику от логики представления.Если у вас есть много частных методов, выполняющих бизнес-логику в вашем пользовательском интерфейсе, вы тесно связали свою бизнес-логику с вашей презентацией.Начните определять их и перемещать в отдельные классы с открытыми интерфейсами, которые вы можете протестировать.Читайте о SOLID принципах, которые могут помочь вам сохранить ваш код свободно связанным и тестируемым.

5 голосов
/ 01 февраля 2012

Разбейте всю бизнес-логику на отдельный проект и протестируйте его. Или, по крайней мере, переместить всю логику из форм в отдельные классы.

0 голосов
/ 02 ноября 2017

Можно использовать шаблон MVVM (Model – View – ViewModel) с Reactive.UI, чтобы создать тестируемый код WinForms. Чтобы получить разделение интересов действительно нужно. См .: Reactive.UI https://reactiveui.net/ Основным недостатком использования Winforms / MVVM / Reactive.UI является то, что существует не так много примеров его использования (для WinForms). Плюс в том, что он применим практически ко всем рабочим средам и языкам. Вы изучаете это для одного, но принципы применяются для всех. Когда у вас много частных методов, это нормально. ИМХО: попробуйте использовать публичные методы, чтобы начать бизнес-процесс, который вы хотите протестировать. Вы можете использовать Tell-Don't-Ask: https://martinfowler.com/bliki/TellDontAsk.html и по-прежнему сохранять все эти методы закрытыми.

Можно также протестировать код, управляя пользовательским интерфейсом, но это не очень рекомендуется, потому что результирующие тесты (1) очень хрупкие, (2) труднее получить работу, и ИМХО, (3) не может быть написанный на том же уровне тонкой гранулярности, что и тесты чистого кода (4) Наконец: если вы используете базу данных, вам нужно будет рассмотреть вопрос о ее заполнении тестовыми данными, и, поскольку ваша база данных должна находиться в чистом, четко определенном состоянии перед каждым тестом, (5) ваши тесты могут выполняться еще медленнее чем вы думаете, как вы повторяете данные для каждого теста.

Резюме: создайте свой код с хорошим SoC (например, применив MVVM), и тогда ваш код будет иметь гораздо лучшую тестируемость.

0 голосов
/ 24 апреля 2012

Модульное тестирование View достаточно просто с использованием утверждений тестирования (www.approvaltests.com или nuget). здесь есть видео: http://www.youtube.com/watch?v=hKeKBjoSfJ8

Однако вам также кажется, что вы беспокоитесь о том, чтобы сделать функцию по умолчанию или общедоступной, чтобы иметь возможность проверить функциональность.

Обычно их называют швами; способы попасть в ваш код для тестирования. и они хороши Иногда люди путают частную / публичную с безопасностью и боятся сделать приватную функцию общедоступной, но при этом будет вызвано и рефлексия, так что это не совсем безопасно. В других случаях люди беспокоятся об интерфейсе API для класса. Но это имеет значение, только если у вас есть общедоступный API, и если у вас есть приложение winform, оно, вероятно, предназначено для верхнего уровня (другие потребители его не называют).

Вы - программист, и поэтому можете разрабатывать свой код так, чтобы его было легко тестировать. Обычно это означает немного больше, чем изменение нескольких открытых методов и создание нескольких методов connivence, которые позволяют передавать зависимости.

Например:

buttonclick += (o,e)=> {/*somecode*/};

очень сложно проверить.

private void button1_Click(object sender, EventArgs e) {/*somecode*/}

все еще трудно проверить

public void button1_Click(object sender, EventArgs e) {/*somecode*/}

легче проверить

private void button1_Click(object sender, EventArgs e) { DoSave();}
public void DoSave(){/*somecode*/}

Действительно легко проверить!

Это удваивается, если вам нужна информация с мероприятия. то есть.

public void ZoomInto(int x, int y)

Гораздо проще проверить, что соответствующее событие щелчка мыши, и вызов passthrough все еще может быть одной игнорируемой строкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...