C# для чайников
.pdf
Далее описана обычная последовательность метода тестирования в NUnit.
1.Выполняются все необходимые настройки теста (если вы еще не сделали этого в методе с атрибутами [Setup ] или [ F i x t u r e S e t U p ] ) .
2.Вызывается тестируемый метод, получаются результаты его вызова.
Если метод ничего не возвращает, вам, вероятно, придется проявить творческий подход. Например, если метод копирует файлы из одного места в другое, вам придется использовать язык С#, чтобы подсчитать количество файлов в источни ке и получателе, или сравнить все имена файлов, например, применяя методы на подобие описанных в главах 19, "Работа с файлами и библиотеками", и 20, "Работа с коллекциями". Вы можете передать часть работы вспомогательным функциям, а платформа .NET Framework предоставляет большое число классов, которые можно использовать для помощи.
Это служит лишним подтверждением тому, что лучше использовать короткие, простые методы — отчасти потому, что их проще проверять. Вы можете "разложить" большой метод на несколько меньших и протестировать их. (Посетите Web-сайт www. ref actoring. com).
3.Выполняется фактический тест: сравнение полученных результатов с ре зультатами, которых вы ожидаете. Если они совпадают, тест пройден. Если нет, то тест завершился неудачно.
Вы должны знать, чего ожидаете от функции, вводя в нее данные. Исполь зуйте контролируемые условия для тестирования и выполняйте тесты с "тестирующими", а не с реальными данными.
Если тест пройден, в окне программы NUnit он будет отмечен зеленой точкой. Если не пройден, он будет отмечен красным, и отобразится информация о том, где произошла ошибка, и что при этом происходило. Используйте эту информа цию для поиска неприятностей в коде своей программы.
4.Выполните все необходимые действия по "уборке за собой".
В частности, не должны сложиться условия, которые могут влиять на последующие тесты. Это можно сделать в методах [TearDown] или [FixtureTearDown] или же в конце самого метода тестирования.
Иногда может потребоваться добавить один или несколько вспомогательных методов или свойств к проверяемому классу, чтобы облегчить тестирование. Я присваиваю таким методам доступ internal (не private и не public) и помечаю их как поддержку тестирования в блоке #region/#endregion. Вы можете также создать в своей про грамме специальный класс TestSupport. Делайте методы и свойства этого класса ста тическими, чтобы их можно было вызывать так, как показано в следующей строке:
TestSupport.StoreSomethingForTestToCheck(something);
Дополнительные преимущества этого вызова состоят в том, что он сохраняет боль шую часть связанного с тестом кода вне программы и помечает элемент поддержки, не внося беспорядка. В своем классе TestSupport вы можете предоставить член для хра нения данных, а также метод или свойство, которое может использоваться в тестах для получения этих сохраненных данных.
554 |
Часть VII. Дополнительные главы |
Использование Assert
Механизмом для проведения фактических испытаний и передачи их результатов в программу NUnit для отображения является класс Assert, который предоставляет NUnit. Класс Assert имеет многочисленные методы для сравнения объектов и выпол нения логических проверок.
Методы класса Assert включают IsTrue (), IsFalse (), IsNull О , IsNotNull (), AreEqual (), AreSame (), Fail () и Ignore ( ) . Для получе ния информации о классе Assert и его методах перейдите в подкаталог \doc в каталоге NUnit и дважды щелкните на файле Assertions.html. (Другие расположенные там файлы содержат полезную информацию об NUnit, доступ ную также на Web-сайте по адресу www. nunit. org.)
В языке С# используется похожая технология Assert, в частности в классе
System.Debug.
Идея заключается в том, чтобы "сделать заявление" (или "утверждать"), что имеет ме сто некоторое логическое условие. Утверждение терпит неудачу, если это условие ложно, или оно успешно, если условие истинно. В случае неудачного исхода в NUnit отображается сообщение, которое передается в качестве последнего параметра методам Assert.
Вы можете проявить творческий подход в тестировании утверждений. Например, ес ли вашим тестирующим вводом является массив данных, который вы передаете тести руемому методу, можно поместить код утверждения внутри цикла так, чтобы утвержде ние выполнялось для каждого элемента массива, как в приведенном ниже фрагменте из еще одного метода тестирования в программе NUnitTestExample.
//Подсчет количества пробелов в строке и проверка
//ожидаемого результата
for(int i = 0; i < stringsOut.Length; i++)
{
// Вспомогательный метод
int nSpaces = CountSpaces(stringsOut[i]);
//Проверка утверждения для каждого элемента массива
//stringsOut
Assert.AreEqual(nSpaces, spacesExpected[i],
"Строка " + i + " содержит неверное " +
"количество пробелов");
}
Это хороший способ — проверять сразу целый диапазон вводов в одном тестирую щем методе.
Запуск набора тестов NUnit
После того как вы написали свою программу и тесты для нее, необходимо запускать тесты следующим образом.
1.Скомпилируйте свою программу.
Компиляция должна пройти без ошибок, прежде чем вы сможете запускать тесты NUnit.
2.Запустите отдельную программу NUnit.
Глава 22. С# по дешевке |
555 |
Она существует в двух вариантах — в форме консольного и графического прило жений. Вы, вероятно, предпочтете графическую версию.
В программе SharpDevelop можно запустить NUnit из меню Tools, и результат будет отображаться прямо в среде SharpDevelop в окне Unit Tests.
Вы также можете загрузить инструмент TestDriven.NET (с Web-сайта www. testdriven. net), который предоставляет похожее отображение результатов тестирования NUnit в среде Visual Studio.
3.В NUnit выберите команду меню File^Open и перейдите к папке \bin\Debug или \bin\Release, где находится программа, только что скомпилированная вами, в виде файла .ЕХЕ или .DLL. В окне открытия файла NUnit дважды щелкните на файле . ЕХЕ или . DLL, который содержит вашу тестируемую программу.
ВNUnit будет отображен иерархический список приспособлений для тестирова ния (классов), а также методов тестирования в окне Test.
4.Щелкните на кнопке Run.
ВNUnit запустятся тесты (в алфавитном порядке!), и серые точки перед названи ем каждого метода тестирования станут зелеными (успешно завершенный тест) или красными (произошла ошибка).
5.Взгляните на вкладку Errors and Failures справа для просмотра информа ции о неудачных тестах.
Щелкните на записи об ошибке, чтобы просмотреть стек вызовов в панели под методом, потерпевшим неудачу: вы увидите последовательность вызовов метода, которая привела к неудаче; для каждого вызова приведены имя файла и номер строки (стек вызовов описан в главе 21, "Использование интерфейса Visual Studio"). (В NUnit отображается и другая полезная информация, такая как обыч ный вывод программы в консоль на вкладке Console.Output и ошибочный вывод программы на вкладке Console.Error.)
Вследующий раз, когда вы захотите выполнить тесты, перекомпилируйте свою про грамму и переключитесь в окно NUnit. Программа автоматически перезагрузит ваш из
мененный код (вы также можете сделать это вручную посредством команды Reload в меню File). Щелкните на кнопке Run.
Вы также можете щелкнуть на одном тесте в программе NUnit для запуска только его.
На рис. 22.7, приведенном выше, показан ряд тестов программы NUnit, которые только что были выполнены. Один из них прошел неудачно (это было сделано преднамеренно). FailingTest отмечен более темной (красной) точкой (и, как результат, MyTestClass и другие элементы иерархии, расположенные над ним). Индикатор выполнения под кнопкой Run также красный. Успешно завершенные тесты отмечены светлыми (зелеными) точками. В программе отображается также стек вызовов для неудачного теста.
556 |
Часть VII. Дополнительные главы |
Исправление ошибок в проверяемой программе
Не исключено, что вы могли совершить ошибки и в самих тестирующих методах, так что любые результаты, полученные в программе NUnit, являются ошибочными незави симо от проверяемого метода или от метода тестирования. Бррр... Кто будет следить за наблюдателями? Когда такое происходит, было бы хорошо иметь возможность пройти методы тестирования в отладчике, чтобы можно было проверить переменные и отсле дить проблему.
Имеется только одна загвоздка: вашу проверяемую программу запускает NUnit, а не Visual Studio или TextPad. И что знает программа NUnit об отладчиках для языка С#?
Однако все же имеется способ отладить тестирующую программу. (В действительно сти их несколько. Вам будет показан один из них.)
Зачем присоединяться к процессу NUnit?
Каждая запущенная программа запускает в Windows процесс, отдельную об ласть памяти, выделенную только для данной программы. Внутри этой облас ти программа сохраняет свои переменные и работает практически так же, как
если бы она имела в своем распоряжении весь компьютер. Когда программы Visual Studio и NUnit выполняются одновременно, каждая из них находится в своем собст венном процессе, и вы должны предоставить программе Visual Studio (или отладчику CLR) доступ к процессу NUnit для отладки.
В следующих разделах описано, как отлаживать тесты NUnit из таких отладчиков:
отладчик Visual Studio (когда вы работаете в Visual Studio);
отладчик CLR (когда вы работаете в SharpDevelop, TextPad или из ко мандной строки).
Запуск тестов NUnit в отладчике Visual Studio
Выполните следующие действия для отладки своей программы тестирования, если вы работаете в Visual Studio (в следующем разделе рассматривается работа в TextPad или SharpDevelop, или из командной строки).
1.Скомпилируйте программу без ошибок времени компиляции.
2.Запустите NUnit и убедитесь, что загружен проект, который вы хотите отладить.
Не забывайте об этом шаге и обязательно проверьте, файл какой именно про граммы вы загрузили в NUnit.
3.В Visual Studio откройте файл, содержащий класс тестирования. Установите точку останова в строке, в которой хотите остановить отладчик.
Эта строка будет в одном из ваших методов тестирования.
4.В Visual Studio выберите команду меню Debugs Attach to Process.
О том, зачем это делать, рассказывается во врезке "Зачем присоединяться к про цессу NUnit?"
5.В диалоговом окне Attach to Process найдите в списке Available Proc esses процесс nun . it - gui . е х е (в левой колонке).
Глава 22. С# по дешевке |
557 |
В поле Title этого "процесса" будет написано что-то вроде N U n i t T e s t E x a m p l e . е х е — NUnit (в зависимости от названия тестируемой программы). На рис. 22.9 по казано, как выглядит диалоговое окно Attach to Process с выбранным процессом NUnit для присоединения.
Рис. 22.9. Присоединитесь к NUnit как ко внешнему процессу для отладки программы тестирования
6.Щелкните на кнопке Attach.
7.Нажмите комбинацию клавиш <Alt+Tab> для переключения в программу NUnit. Щелкните на кнопке Run.
Отладчик остановится на строке с точкой останова и подцветит ее. Вы можете начать пошаговое выполнение программы с этой точки.
Можно установить точки останова как в программе тестирования, так и в тес тируемой программе, но в тесте такая точка должна быть только одна. С нее и начинается отладка.
Запуск тестов NUnit в отладчике CLR
Выполнение тестов NUnit в отладчике CLR очень похоже на их выполнение в отлад чике Visual Studio. Вам необходимо делать это, когда вы работаете с NUnit из программ TextPad или SharpDevelop.
Для запуска программы тестирования в отладчике CLR выполните следующие действия.
1. Запустите отладчик CLR как обычно, из меню Tools в программе TextPad или SharpDevelop, или при необходимости запустите его как самостоятель ное приложение.
558 |
Часть VII. Дополнительные главы |
2.Запустите NUnit (графическую или консольную версию).
3.В отладчике, как обычно, загрузите программу для отладки и соответст вующие ей файлы . CS.
4.Установите в отладчике точку останова в строке исполняемой программы
в одном из ваших методов тестирования.
5.Выберите команду меню Debug^Processes. В диалоговом окне Processes выберите процесс n u n i t - g u i . е х е (или n u n i t - c o n s o l e . ехе ) и щелкните на кнопке Attach. Затем — на кнопке Close.
6.Нажмите клавишу <F10> для выполнения программы с пропуском вызовов функций или <F11> для пошагового выполнения с заходом в функции.
7.Отладчик остановится в установленной вами точке останова.
8.Продолжайте пошаговое выполнение, проверку переменных и т.д.
Этот процесс может перевести вас из испытательного кода в код вашей програм мы по вызову испытательным методом. Ошибка может быть в любой из данных областей.
Прекращение отладки
Для того чтобы прекратить отладку, переключитесь в Visual Studio (или от ладчик CLR) и выберите команду меню Debug<=>Stop Debugging. Это при ведет к отсоединению от процесса NUnit, и вы сможете продолжать про граммирование.
В любой момент, когда вы захотите отладить тесты вашего проекта, повторите пре дыдущие шаги.
Одной из наиболее недостающих возможностей в TextPad является отсутствие визу альных средств для размещения управляющих элементов в ваших формах Windows. Большинство читателей этой книги хотят создавать программы для Windows, и все, что можно здесь сделать — это порекомендовать SharpDevelop. Но можно показать и еще одну альтернативу — написание такого кода вручную.
Это всего лишь код
Не забывайте, что код, генерируемый визуальными средствами для разработки форм — всего лишь код. Он следует определенным соглашениям, к которым вы должны присоединиться при его написании вручную, но это не более чем код на С#. Вы можете написать его самостоятельно следующим образом.
Просто собезьянничав и скопировав код, который был разработан визуальными средствами.
Глава 22. |
С# по дешевке |
559 |
Написав важные части кода самостоятельно и отбросив ненужное, поскольку вы не играете в эти игры.
Далее будут вкратце рассмотрены оба подхода.
Работа в стиле визуального инструмента
Написание такого же кода, как и создаваемый визуальными инструментами, упирает ся в знание формата.
В главе 1, "Создание вашей первой Windows-программы на С#", вы вкратце знакоми лись с программированием Windows Forms и создавали маленькое приложение, которое выводило форму (окно) с двумя текстовыми полями и одной кнопкой. При щелчке на кнопке программа копировала текст из верхнего поля в нижнее.
Если у вас нет Visual Studio, вы не сможете следовать инструкции из гла вы 1, "Создание вашей первой Windows-программы на С#", так что иден тичный код предоставлен в демонстрационной программе ImitatingFormDesigner на прилагаемом компакт-диске. Вы можете увидеть тот же код, что и в главе 1, "Создание вашей первой Windows-программы на С#", но он написан мною самостоятельно, без визуального инструментария.
За красивыми формами, создаваемыми при помощи мыши, Visual Studio скрывает код, который создает все эти управляющие элементы и заставляет их работать.
Visual Studio создает весь код за исключением того, что происходит при взаимодей ствии с пользователем. Например, когда пользователь щелкает на кнопке, выполняются какие-то действия, и написать код для этих действий — это уже ваша забота. В описан ном примере действие представляет собой одну строку на С#, которая копирует текст из textBoxl в textBox2:
textBox2.Text = textBoxl.Text;
Когда вы создаете новое приложение Windows (в отличие от консольных приложе ний, которые использовались во всей этой книге), Visual Studio 2005 генерирует три ис ходных файла. Два из них содержат часть класса Forml, который лежит в основе фор мы, представляющей пользовательский интерфейс вашей программы. В третьем файле находится класс Program, содержащий функцию Main ().
Вот более детальное описание полученных вами файлов.
Forml.cs: этот файл содержит объявление частичного класса (partial class) для класса Forml. (Что такое частичный класс, будет объяснено позже.) Это только по ловина класса Forml (вторая его половина находится в другом файле), но это та по ловина, в которой вы пишете весь код, который должен быть создан вручную.
Forml .Designer, cs: данный файл содержит вторую половину кода частично го класса Forml. Это часть, которую Visual Studio 2005 создает для вас.
Не трогайте этот файл. Добавляйте код только в первую половину класса Forml
вфайле Forml. cs. Когда вы добавляете или модифицируете управляющий элемент
впроектировщике форм, он сам изменит код — вы не должны в это вмешиваться.
Program, cs: этот файл содержит функцию Main ().
560 |
Часть VII. Дополнительные главы |
В демонстрационной программе ImitatingFormDesigner я написал определен ный код в файле Forml. cs для того, чтобы программа выполняла некоторые действия: обработчик щелчка buttonl копирует текст из textBoxl в t e x t B o x 2 , как и в гла ве 1, "Создание вашей первой Windows-программы на С#", в которой на рис. 1.10 пока зано, как это выглядит на экране компьютера.
Взгляните на код второй демонстрационной программы на прилагаемом компактдиске — Forms YourWay. Этот код похож на неприкасаемый код из файла
Forml .Designer, cs демонстрационной программы ImitatingFormDesigner, но в него включены комментарии, поясняющие, что и как работает.
Главное заключается в том, что при возможности использовать проектировщик форм Visual Studio (или его коллегу из SharpDevelop) дизайнер выполняет мас су работы за вас, но все, что он делает — это всего лишь код, который — само собой, с большими затратами труда — вы можете написать и самостоятельно.
Частичные классы
Частичные классы — новая возможность С# 2.0. Идея заключается в разбиении клас са на два или большее количество файлов. Каждый файл содержит частичный класс (partial class), помеченный новым ключевым словом partial:
// Файл 1
public partial class MyClass
{
//Часть класса MyClass, но не весь — остальная его часть
//находится в другом файле
}
// Файл 2
public partial class MyClass // Тот же заголовок
{
//Еще одна часть класса MyClass, но не весь он — словом,
//идея вам понятна?
}
Главное преимущество частичных классов в том, что теперь вы можете сделать сле дующее:
разделить работу над одним классом одновременно между несколькими програм мистами;
отделить часть класса, которую вы создали с помощью некоторого инструмента, генерирующего код, от части(ей), написанной человеком.
Вряд ли вы будете часто использовать эту возможность, но там, где она полезна — она очень и очень нужна.
Главная причина для отделения сгенерированного машиной кода от кода, написанно го человеком, в том, что при каждом запуске генератора для добавления или внесения изменений (например, для добавления новой кнопки) он генерирует код заново. Если в этот код были добавлены ваши изменения, при повторной генерации они пропадут. Но если вы отделите свой код от машинного, то тем самым спасете его от механического вмешательства компьютера.
Глава 22. С# по дешевке |
561 |
Позже вы сможете перенести код из сгенерированной части в написанную вами, но это приведет к тому, что дизайнер не сможет с ним работать. Например, если вы перенесли весь код, касающийся некоторой кнопки, включая ее создание, в вашу половину, то кнопка больше не будет появляться в дизайнере, хотя будет выводиться при работе программы. Именно так вы можете добавлять визуальные элементы в форму или модифицировать ее динамически, во время выполнения программы. Если вы переместите только часть кода, при повторной генерации дизайнер может восстановить ее, что приведет к дублированию и ошибкам ком пиляции. Такое перемещение следует выполнять очень осторожно.
Как уже упоминалось, частичные классы связаны в первую очередь с кодом дизайне ра форм Visual Studio, что наглядно показывает демонстрационная программа Imitat ingFormDesigner.
Самостоятельное написание
Чтобы посмотреть, какой код вы обязаны написать при отсутствии визуаль ного инструментария, взгляните на предельно упрощенную схему демонст рационной программы FormsYourWay на прилагаемом компакт-диске. Комментарии в этом коде указывают, куда следует добавить код управляю щих элементов.
Код демонстрационной программы FormsYourWay состоит в основном из фигурных скобок, комментариев и кода, связанного с управляющими элементами формы.
Одна из интересных особенностей этой программы состоит в том, что в ней нет фай ла Program, cs с функцией Main ( ) . Вместо этого функция Main () сделана методом самого класса Forml. Данная функция может находиться в любом классе. Просто убеди тесь, что в программе имеется ровно одна функция Main ( ) . Кстати, взгляните на эту функцию Main ( ) , чтобы иметь представление, как выглядит типичная функция Main () для графического приложения Windows.
Ознакомьтесь со сводкой элементов кода, необходимых для размещения управляю щих элементов в форме с помощью одного лишь кода, без применения дизайнера.
Объявить управляющие элементы (как члены-данные класса формы). Они должны иметь классы наподобие Button, TextBox или Label из пространства имен
System.Windows.Forms.
System.Windows.Forms.Button buttonl;
При желании можно использовать директиву using для пространства имен Sys tem .Windows.Forms.
Инстанцировать каждый управляющий элемент (в конструкторе формы или мето де, который он вызывает).
buttonl = new System.Windows.Forms.Button()
Установить свойства каждого управляющего элемента (в конструкторе формы или методе, который он вызывает). Вы должны поэкспериментировать, чтобы опреде лить корректные координаты Location и значения Size (обратите внимание, что в примере параметр у у Size не используется, так что указано значение 0).
buttonl.Location = new System.Drawing.Point(40, 80) ; buttonl.Name = "buttonl";
562 |
Часть VII. Дополнительные главы |
buttonl.Tablndex = 1; buttonl.Text = "Copy";
Добавить обработчик для каждого события, которое вы хотите обработать, для каждого из управляющих элементов (в конструкторе). Добавление обработчика для кнопки выглядит примерно так:
buttonl.Click += new Sys
tem. EventHandler (this . buttonl_Click) ;
В представленном примере единственное событие, требующее обработки, — это собы тие Click кнопки. Однако вам могут потребоваться и другие события. Аргумент в скобках именует метод Forml, который отвечает на щелчок кнопки. В данном слу чае он называется buttonl_Click ().
Добавить каждый уггоавляющий элемент в коллекцию Controls (в конструкторе), this.Controls.Add(buttonl);
Написать обработчики для всех событий, связанных с каждым управляющим эле ментом (в качестве методов формы; после конструктора). Метод обработчика кнопки имеет примерно следующий вид:
private void buttonl_Click(object sender,System.EventArgs e)
{
//Некоторые действия в ответ на щелчок на кнопке MessageBox.Show("Hello");
//Или, как в демонстрационной программе FormsYourWay: textBox2.Text = textBoxl.Text;
}
Чрезвычайно простой код демонстрационной программы FormsYourWay использу ет единственное небольшое интерактивное окно, показанное на рис. 1.10. Другими сло вами, результат идентичен полученному в главе 1, "Создание вашей первой Win dows-программы на С#", и ранее в этой главе. Однако сами коды несколько отличаются друг от друга.
Вам потребуется масса справочной информации о свойствах классов управ ляющих элементов, таких как Button, TextBox, ListBox и т.д., а также о классах Form и его базовых классах. Все это можно найти в справочной сис теме .NET SDK.
Представьте, что вы написали программу, выпустили ее окончательную версию и от правили в бурное море людей и событий, где кто-то установит ее на свой компьютер и попытается запустить? Да, эта программа работала (вполне корректно) на вашем ком пьютере, но будет ли она функционировать на чужой машине? Вы должны перед тем как пускать программу по водам, проверить ее по возможности на максимально большем ко личестве компьютеров с разными конфигурациями.
Глава 22. С# по дешевке |
563 |
