Чистый способ рефакторинга тестового кода - PullRequest
0 голосов
/ 14 февраля 2010

Фон
В настоящее время я пишу тестовые случаи для клиентской части сетевого протокола. В рамках тестов мне нужно смоделировать несколько разных ожидаемых и неожиданных ответов от сервера (неправильный заголовок, потеря соединения, неожиданные сообщения, тайм-ауты).
К каждому из этих тестовых примеров можно получить доступ по уникальному адресу.
Моя проблема :
Текущая реализация разбита на несколько частей:

  • Перечисление, содержащее все адреса тестовых случаев
  • Класс A Тесты, содержащие все тесты в качестве статических функций
  • Число определяет, какое отображение имени функции на соответствующий enum + _FUNC
  • Класс-обертка, который принимает в качестве аргумента адрес функции и имя
  • Метод, который возвращает список объектов класса-оболочки, по одному объекту для каждого теста

Для каждого полученного сообщения сервер проверяет список тестовых случаев и либо выполняет тестовый случай, соответствующий адресу, либо возвращается к ответу по умолчанию.
Вопрос :
Эта реализация требует, чтобы я обновлял как минимум пять разных мест для каждого нового тестового случая, и класс Test растет довольно быстро. Есть ли хороший способ его рефакторинга?
Пример кода :( этот код недействителен c ++)

enum TestAddress
{
   TEST_CONNECTION_BREAKDOWN = 0x100,
   TEST_ALL_IS_GOOD = 0x101,
}


class Wrapper : AbstrTestCase  //AbstrTestCase requires applies and test implementations
{ 
typedef testFun;
Wrapper(TestAddress addr,testFun func,string name)
boolean applies(int ad,...){return addr == ad;}
int test(...){return func(...);}
}
class Test
{
static int testConnectionBreakDownFunc (...)
static int testAllIsGoodFunc(...)
}
#define TEST_CONNECTION_BREAKDOWN_FUNC Test::testConnectionBreakDownFunc
#define TEST_ALL_IS_GOOD_FUNC Test::testAllIsGoodFunc

list<AbstrTestCase*> GetTests()
{
   list<AbstrTestCase*> tlist;
   tlist.push_back(new Wrapper(TEST_ALL_IS_GOOD,TEST_ALL_IS_GOOD_FUNC,"TEST_ALL_IS_GOOD"));
   ...
   tlist.push_back(new Wrapper(TEST_CONNECTION_BREAKDOWN,TEST_CONNECTION_BREAKDOWN_FUNC,"TEST_CONNECTION_BREAKDOWN_FUNC"));
   return tlist;
}

Related: Моя последняя попытка хотя бы очистить код в GetTests () была дополнительным определением аргументов оболочки

#define WRAP_ARGS(N) N,N##_FUNC,#N
tlist.push_back(new Wrapper(WRAP_ARGS(TEST_CONNECTION_BREAKDOWN));
#undef WRAP_ARGS(N)

, хотя в результате получается более чистый код, проблема только скрывается

1 Ответ

0 голосов
/ 15 февраля 2010

У меня были такие же проблемы, как и у вас. Подход, который я обычно использую, состоит в том, чтобы управлять этим через скрипт, чтобы автоматизировать добавление кода в разные места. Комментарий отмечает точку для сценария для обработки файла, поэтому вам не нужно писать сложный парсер. Что-то вроде:

/* automatic code insertion point. Don't remove this comment */

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

...