Программирование >>  Разработка устойчивых систем 

1 ... 15 16 17 [ 18 ] 19 20 21 ... 196


Для решения этой задачи также хорошо подходят пакетные файлы и сценарии командного интерпретатора. Класс Suite предназначен для группировки взаимосвязанных тестов средствами C-t-+.

при невыполнении условий, включите в программу намеренную ошибку, например, измените условие в первом вызове test () в DateTest::testOps() на противоположное. Выходные данные точно сообщают, какое условие не прошло проверку, и где случилась ошибка:

DateTest failure: (mybday > today) , DateTest.h (line 31) Test DateTest *:

Passed: 20 Failed: 1

Помимо функции test () в систему тестирования включены функции succeed () и faiLO для тех случаев, когда логическое условие не подходит. Эти функции применяются, когда тестируемый класс может генерировать исключения. Для тестирования создается набор входных данных, благодаря которым должно произойти исключение. Если исключение не запускается, значит, в программе произошла ошибка; тогда вызывается функция faiLO для вывода сообщения и обновления счетчика сбоев. Если, как и предполагалось, запускается исключение, вызывается функция succeedO для обновления счетчика удачных проверок.

Рассмотрим конкретный пример. Допустим, спецификация двух конструкторов Date была изменена так, чтобы конструкторы запускали исключение Date Error (тип, вложенный по отношению к Date и производный от std::logic error), если их входные параметры не представляют допустимую дату:

Date(const strings s) throw(DateError);

Datednt year, int month, int day) throw(DateError):

Теперь функция DateTest: :run() может вызвать следующую функцию для тестирования обработки исключений:

void testExceptionsO { try {

Date d(O.O.O): Недопустимая дата fail ( Invalid date undetected in Date int ctor ): } catch (Date::DateError&) { succeed ():

try {

Date d( ): Недопустимая дата fail ( Invalid date undetected in Date string ctor ): } catch (Date::DateError&) { succeed ():

В обоих случаях отсутствие исключения является ошибкой. Обратите внимание: логическое условие в программе не проверялось, поэтому при вызове faiL() сообщение приходится передавать вручную.

Комплексы тестов

Реальные проекты обычно состоят из множества классов. Нам понадобится способ группировки тестов, который бы позволял протестировать весь проект нажатием одной кнопки Класс Suite объединяет тесты в функциональные группы.



Test StringStorageTest :

Passed: 2 Failed: 0 Test SieveTest :

Passed: 50 Failed: 0 Test FindTest :

Passed: 9 Failed: 0 Test RparseTest :

Passed: 8 Failed: 0 Test TrimTest :

Passed: 11 Failed: 0 Test CompStrTest :

Passed: 8 Failed: 0 */ III:-

Пять из этих тестов полностью находятся в заголовочных файлах. Тест TrimTest отличается от них: он содержит статические данные, которые должны определяться в файле реализации. Первые две строки вывода содержат трассировочные данные из теста StringStorage. Комплексу тестов должно быть присвоено имя, которое передается в аргументе конструктора. Функция Suite::run() вызывает функцию Test:: run О для каждого теста, входящего в комплекс. Практически то же самое происходит в функции Suite::report(), если не считать того, что отчеты отдельных тес-

Отдельные объекты Test включаются в контейнер Suite функцией addTest(); также предусмотрена функция addSuite() для включения содержимого целого контейнера. В следующем примере программы из главы 3, использующие класс Test, объединяются в одну группу. Учтите, что этот файл находится в подкаталоге главы 3:

: C03:Str1ngSuite.cpp

{L} ../TestSuite/Test ../TestSuite/Suite

{LJ TrimTest

Группировка тестов на примере кода из главы 3

#1ncl ude <1ostream>

#include ../TestSuite/Suite.h

#1 ncl ude StringStorage.h

#1nclude Sieve.h

#1 nclude Find.h

#include Rparse.h

#include TrimTest.h

#include CompStr.h

using namespace std:

using namespace TestSuite:

int mainO {

Suite suite( String Tests ): suite.addTest(new StringStorageTest): suite.addTest(new SieveTest): suite.addTest(new FindTest): suite.addTest(new RparseTest): suite.addTest(new TrimTest): suite.addTest(new CompStrTest): suite.runO:

long nFail = suite.reportC): suite.free(): return nFail:

/* Вывод: si = 62345 s2 = 12345

Suite String Tests



тов могут направляться в другие выходные потоки. Если тесту, переданному при вызове addSuite(), уже назначен указатель на выходной поток, он сохраняется за этим тестом. В противном случае поток назначается объектом Suite (как и в классе Test, у конструктора Suite имеется необязательный второй аргумент, по умолчанию равный std::cout). Деструктор Suite не выполняет автоматического освобождения указателей на хранящиеся в нем объекты Test, поскольку они не обязаны храниться в куче; эта задача решается функцией Suite::free().

Код TestSuite

Код системы автоматизированного тестирования находится в подкаталоге TestSuite архива примеров. Чтобы использовать его в своих программах, включить путь к каталогу TestSuite в заголовочный файл, скомпонуйте объектные файлы и включите подкаталог TestSuite в перечень путей к библиотекам. Заголовочный файл Test.h выглядит так:

: TestSuite:Test.h #ifndef TEST H #define TEST H #include <string> #include <iostream> #include <cassert> using std::string: using std::ostream: using std::cout:

Символ подчеркивания в имени fail () предотвращает конфликты с ios::fail(). Ради единства стиля в имена test () и succeed () также были включены символы подчеркивания.

#define test (cond) \

do test(cond. #cond. FILE . LINE ) #define failjstr) \

do fail(str. FILE . LINE )

namespace TestSuite {

class Test { ostream* osptr: long nPass: long nFail:

Запрещенные операции:

Test(const Tests):

Tests operator=(const TestS):

protected:

void do test(bool cond. const strings Ibl.

const char* fname. long lineno): void do fail(const strings Ibl.

const char* fname. long lineno): public:

Test(ostream* osptr = Scout) { this->osptr = osptr: nPass = nFail = 0:

virtual -TestО {} virtual void runO = 0:



1 ... 15 16 17 [ 18 ] 19 20 21 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика