vak: (Default)
[personal profile] vak
Навеяло недавним достижением [personal profile] spamsink: восстановлением исходников игры "Посадка на Луну" с БЭСМ-6.

https://github.com/besm6/bega-re/blob/master/landing.pas

Пусть у нас есть диалоговое приложение на Си++ с текстовым интерфейсом. Приложение запрашивает построчный ввод из std::cin и выдаёт результаты на std::cout. Условно говоря, вызов выглядит следующим образом:
application(std::cin, std::cout);
Схематично, работает оно так:
void application(std::istream &input, std::ostream &output)
{
output << "something\n";

while (!input.eof()) {
std::string line;
getline(input, line);

std::string result = something(line);
output << result;
}
}
Теперь стоит задача покрыть имеющуюся реализацию тестами. Я ж теперь адепт TDD. Хочется иметь возможность делать тесты (с применением Catch) вида:
send("foo\n");
std::string reply = receive();
REQUIRE(reply == "bar\n");
Как бы вы стали решать эту задачу? Я имею в виду, как средствами Си++ привинтить одно к другому? Чтобы, не модифицируя исходники application(), вызывать и тестировать её из Catch?

Нет, это не задача для собеседования. Тут и опытный человек голову сломает.

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

Date: 2020-08-14 09:40 (UTC)
norian: (Default)
From: [personal profile] norian
йа бы использовал адаптер - функция получает потоки как аргументы, а более верхний уровень либо назначает стандартные, либо подставляет кастомные для тестирования

а, ну собсно оно так уже написано (на третий день коты посмотрели на топик, ага), просто дёргать снаружи со своими стримами и сравнивать результаты с ожидаемыми
Edited Date: 2020-08-14 09:46 (UTC)

Date: 2020-08-14 13:33 (UTC)
norian: (Default)
From: [personal profile] norian
как-нть так

#include iostream
#include sstream

using namespace std;

void application( istream& input,  ostream &output)
{
    output << "Start" << endl;

    ostringstream local_str;
    local_str << input.rdbuf();

    output << local_str.str() + "_test";
}

int main() {

    stringstream in_str;
    stringstream out_str;

    in_str << "Hello";

    application( in_str, out_str );

    if (out_str.str() == "Start\nHello_test")
        cout << "PASS" << endl;
    else
        cout << "FAIL " << endl;

    return 0;
}



с функцией из топика тоже будет работать, только шаблон результата поменять на фактический
и третья строка не нужна, лишний копипаст был
Edited Date: 2020-08-14 14:15 (UTC)