Как один модуль тестирует разделы кода, которые являются процедурными или основанными на событиях - PullRequest
8 голосов
/ 16 сентября 2008

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

Часто примеры, которые я вижу для тестирования, - это тестирование классов - они создают объект, передают ему фиктивные данные, а затем проверяют свойства объекта. Это имеет смысл для меня, но как насчет не объектно-ориентированных частей?

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

Итак, вопрос - как один модуль тестирует процедурный или основанный на событиях код? Предоставьте ссылку на хорошую документацию или объясните это самостоятельно.

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

Ответы [ 7 ]

5 голосов
/ 16 сентября 2008

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

Если вы планируете модульное тестирование системы, основанной на событиях, вы значительно упростите себе жизнь, если будете использовать шаблон внедрения зависимостей и в идеале прошли бы весь путь и использовали инверсию управления (см. http://martinfowler.com/articles/injection.html и http://msdn.microsoft.com/en-us/library/aa973811.aspx для деталей этих образцов)

(спасибо pc1oad1etter за указание, что я испортил ссылки)

2 голосов
/ 20 сентября 2008

Отвечая на мой собственный вопрос здесь, но я наткнулся на статью, в которой объясняется проблема и дается простой пример - Agile User Interface Development . Код и изображения великолепны, и вот фрагмент, который показывает идею:

Проворные гуру, такие как Кент Бек и Дэвид Астелс предлагает построить графический интерфейс сохраняя объекты очень тонкими, и тестирование слоев "под поверхность. "Этот" смарт-объект / тонкий Представление "Модель аналогично знакомый просмотр документа и парадигмы клиент-сервер, но применяются на разработку индивидуального GUI элементы. Разделение контента и презентация улучшает дизайн кода, делая его более модульным и тестируемый. Каждый компонент Пользовательский интерфейс реализован в виде смарт-объект, содержащий поведение приложения, которое должно быть протестировано, но нет кода представления графического интерфейса. Каждый смарт-объект имеет соответствующий тонкий класс просмотра, содержащий только общее поведение GUI. С этим дизайном модель, здание GUI становится доступным в TDD.

2 голосов
/ 16 сентября 2008

Сначала я бы протестировал такие события:

private bool fired;

private void HandlesEvent(object sender, EventArgs e)
{
    fired = true;
 } 

public void Test()
{
   class.FireEvent += HandlesEvent;
   class.PErformEventFiringAction(null, null);

   Assert.IsTrue(fired);
}

А потом я обнаружил RhinoMocks . RhinoMocks - это фреймворк, который создает фиктивные объекты, а также обрабатывает события. Это может пригодиться и для процедурного тестирования.

1 голос
/ 22 декабря 2008

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

// Arrange
var car = new Car();
string changedPropertyName = "";
car.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
                        {
                           if (sender == car) 
                                  changedPropertyName = e.PropertyName;
                        };

// Act
car.Model = "Volvo";

// Assert 
Assert.AreEqual("Model", changedPropertyName, 
    "The notification of a property change was not fired correctly.");

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

1 голос
/ 16 сентября 2008

Проблема в том, что «программирование на основе событий» связывает слишком много логики с событиями. Такая система должна быть спроектирована так, чтобы существовала подсистема, которая генерирует события (и вы можете написать тесты, чтобы убедиться, что эти события вызываются в правильном порядке). И должна быть другая подсистема, которая занимается только управлением, скажем, состоянием формы. И вы можете написать модульный тест, который проверит, что при правильных входных данных (т. Е. Вызываемых событиях) будет установлено правильное значение состояния формы.

Кроме того, фактический обработчик событий, который вызывается из компонента 1 и вызывает поведение компонента 2, - это просто интеграционное тестирование, которое может быть выполнено вручную сотрудником QA.

0 голосов
/ 17 сентября 2008

См. Часто связанные Эффективная работа с устаревшим кодом . См. Разделы «Мое приложение - это все вызовы API» и «Мой проект не является объектно-ориентированным. Как сделать безопасные изменения?».

В мире C / C ++ (по моему опыту) лучшим решением на практике является использование компоновщика "seam" и ссылка на двойники теста для всех функций, вызываемых тестируемой функцией. Таким образом, вы не изменяете ни один из устаревших кодов, но все равно можете тестировать его изолированно.

0 голосов
/ 16 сентября 2008

Подход, который я нашел полезным для процедурного кода, заключается в использовании TextTest. Дело не столько в модульном тестировании, но в том, чтобы помочь вам провести автоматическое регрессионное тестирование. Идея состоит в том, что ваше приложение пишет журнал, а затем использует texttest для сравнения журнала до и после ваших изменений.

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