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-13 04:36 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Ха, много не надо. Для каждого кейса стрим с одним кейсом, и выход соответственно. А иначе корутины присобачивать... в джаве это можно, но нудно.

Date: 2020-08-13 07:28 (UTC)
ircicq: (Default)
From: [personal profile] ircicq
Если средствами C++, то надо написать свою реализацию std::streambuf
и инициализировать ей std::istream, std::ostream с которыми вызовете application()

P.S. sorry, увеидел что уже ниже написали
Edited Date: 2020-08-13 07:29 (UTC)