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

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


long getNumPassedO const { return nPass: } long getNumFailedO const { return nFail: } const ostream* getStreamO const { return osptr; } void setStreamCostream* osptr) { this->osptr = osptr: } void succeed () { ++nPass: } long reportО const:

virtual void resetO { nPass = nFail = 0: }

} namespace TestSuite #endif TEST H /:-

Класс Test содержит три виртуальные функции:

виртуальный деструктор;

функцию reset();

чисто виртуальную функцию run().

Как объяснялось в первом томе, удаление объекта производного класса через указатель на базовый класс является ошибкой, если у базового класса нет виртуального деструктора. Любой класс, который предполагается использовать в качестве базового (на что, очевидно, указывает присутствие хотя бы одной обычной виртуальной функции), должен иметь виртуальный деструктор. По умолчанию Test::reset() обнуляет счетчики успешных и неудачных проверок. Возможно, вы захотите переопределить эту функцию и организовать сброс данных в производном объекте; только не забудьте явно вызвать функцию Test::reset() из переопределенной версии, чтобы сбросить счетчики. Функция Test::run() является чисто виртуальной, поэтому ее переопределение в производном классе обязательно.

Макросы test () и faiLO могут включать информацию об имени файла и номере строки, полученную от препроцессора. Изначально символы подчеркивания в этих именах отсутствовали, но макрос fa1l() конфликтовал с ios::fa1l() и вызывал ошибки компиляции.

Далее приведена реализация остальных функций Test:

: TestSuite:Test.срр {0} #include Test.h #incl ude <iostream>

#include <typeinfo> Примечание: для Visual С++ необходим ключ /GR using namespace std; using namespace TestSuite:

void Test::do test(bool cond. const std::string& Ibl. const char* fname. long lineno) { if (Icond)

do fail(lbl. fname. lineno); else

succeed ();

void Test::do faiКconst std::strings Ibl. const char* fname. long lineno) { ++nFai1; if (osptr) { *osptr typeid(*this).nameO

failure: ( Ibl ) .



fname

(line lineno ) endl

long Test::reportО const { if (osptr) { *osptr Test \ typeid(*this).name() \ :\n\tPassed: nPass \tFailed: nFail endl:

return nFail: } /:-

Класс Test хранит информацию о количестве успешных и неудачных проверок, атакже выходной поток, в который функция Test::report() должна выводить результаты. Макросы test () и fail () получают текущие имя файла и номер строки от препроцессора; имя файла передается do test(), а номер строки - do fail(). Эти функции занимаются непосредственным выводом сообщений и обновлением счетчиков. Трудно представить, кому и зачем могло бы понадобиться копировать и присваивать объекты Test, поэтому мы запретили эти операции. Для этого их прототипы объявлены закрытыми, а тела функций не определяются.

: TestSuite:Suite.h

#ifndef SUITE H

#define SUITE H

#include <vector>

#include <stdexcept>

#include ../TestSuite/Test.h

using std::vector:

usi ng std::1ogi c error:

namespace TestSuite {

class TestSuiteError : public logic error { public:

TestSuiteError(const strings s = ) : logic error(s) {}

class Suite {

string name:

ostream* osptr:

vector<Test*> tests:

void resetO:

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

Suite(const Suites):

Suites operator=(const SuiteS): public:

Suite(const strings name, ostream* osptr = Scout)

: name(name) { this->osptr = osptr: } string getNameO const { return name: } long getNumPassedO const: long getNumFailedO const:

const ostream* getStreamO const { return osptr: } void setStream(ostream* osptr) { this->osptr = osptr; } void addTest(Test* t) throw (TestSuiteError); void addSuite(const SuiteS);



long Suite::report0 const { if (osptr) { long totFail = 0: *osptr Suite \ name \ \n====== :

void runO: Многократно вызывает Test::run() long reportО const:

void freeO: Уничтожает объекты тестов

} namespace TestSuite #endif SUITE H /:-

Класс Suite хранит указатели на объекты Test в векторе. Обратите внимание на спецификацию исключенир! в объявлении функции addTest(). При включении нового объекта теста в KOHTeiinep функция Suite::addTest() убеждается в том, что переданный указатель отличен от null; в противном случае генерируется исключение TestSuite Error. Поскольку это делает невозможным добавление null-указателя в контейнер, addSuite() проверяет это условие в каждой из своих проверок; то же происходит и в других функциях, перебирающих вектор с объектами тестов (см. реализацию ниже). Как и в классе Test, операции копирования и присваивания в классе Suite запрещены.

: TestSuite:Suite.cpp {0} #include Suite.h #i nclude <iostream> #i nclude <cassert> #i nclude <cstddef> using namespace std: using namespace TestSuite:

void Suite::addTest(Test* t) throw(TestSuiteError) { Проверка действительности теста и наличия выходного потока: if (t == 0)

throw TestSuiteErrorCNull test in Suite::addTest ): else if (osptr && !t->getStream())

t->setStream(osptr): tests.push back(t): t->reset():

void Suite::addSuite(const SuiteS s) { for (size t i = 0: i < s.tests.sizeO: ++i) { assert(tests[i]): addTest(s.tests[i]):

void Suite::free() { for (size t i = 0: i < tests.sizeO: ++i) { delete tests[i]: tests[i] = 0:

void Suite::run() { resetO:

for (size t i = 0: i < tests.size(): ++i) { assert(tests[i]): tests[i]->run():



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

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