如何将字符串中的数据放入 cin 中
How to put data in cin from string
我需要为不是我编写的小型学习程序编写测试(使用谷歌测试框架)。(这只是小型控制台游戏,可以从命令行获取模式或只是在运行时获取)有一个问题:我无法更改 souce 代码,但几乎所有方法都使用了 cout 和 cin。我的问题是"如何在测试时回答程序的请求 (CIN)(例如从字符串中获取 CIN 的数据)?
假设您可以控制main()
(或在要测试的函数之前调用的其他函数),您可以更改std::cin
读取的位置以及std::cout
写入的位置:
int main(int ac, char* av[]) {
std::streambuf* orig = std::cin.rdbuf();
std::istringstream input("whatever");
std::cin.rdbuf(input.rdbuf());
// tests go here
std::cin.rdbuf(orig);
}
(同样适用于std::cout
)
此示例保存 std::cin
的原始流缓冲区,以便在离开 main()
之前可以替换它。然后,它将std::cin
设置为从字符串流中读取。它也可以是任何其他流缓冲区。
我的理解是您需要执行以下操作:
- 启动
- /启动目标可执行文件(游戏)。
- 将测试数据发送到目标可执行文件。
- 从目标可执行文件获取输出。
- 将输出与预期结果进行比较。
标准C++语言没有与其他程序通信的标准工具。 您将需要操作系统(您未指定)的帮助。
仅使用C++或不使用特定于操作系统的调用,我建议:
- 将测试输入写入文件。
- 运行可执行文件,将测试输入文件管道化为输入和管道结果文件的输出。
- 读取并分析结果文件。
否则,请搜索操作系统 API 以了解如何写入 I/O 重定向驱动程序。
我知道你说你不能修改代码,但我会像你可以一样回答这个问题。 现实世界通常允许(小的)修改以适应测试。
一种方法是将需要外部输入(DB、用户输入、套接字等)的调用包装在虚拟的函数调用中,以便您可以模拟它们。(下面的示例)。 但首先,关于测试的书籍推荐。 《有效使用遗留代码》是一本测试技术(不仅限于遗留代码)的好书。
class Foo {
public:
bool DoesSomething()
{
string usersInput;
cin >> usersInput;
if (usersInput == "foo") { return true; }
else { return false; }
}
};
会变成:
class Foo
{
public:
bool DoesSomething() {
string usersInput = getUserInput();
if (usersInput == "foo") { return true; }
else { return false; }
}
protected:
virtual std::string getUserInput() {
string usersInput;
cin >> usersInput;
return usersInput;
}
};
class MockFoo : public Foo {
public:
void setUserInput(std::string input) { m_input = input }
std::string getUserInput() {
return m_input;
}
};
TEST(TestUsersInput)
{
MockFoo foo;
foo.setUserInput("SomeInput");
CHECK_EQUAL(false, foo.DoesSomething());
foo.setUserInput("foo");
CHECK_EQUAL(true, foo.DoesSomething());
}
您可以通过不使用直接使用 cin
和 cout
来提高类的可测试性。请改用 istream&
和 ostream&
将输入源和输出接收器作为参数传入。这是依赖注入的情况。如果这样做,则可以传入std::stringstream
而不是cin
,以便可以提供指定的输入并从测试框架获取输出。
也就是说,您可以通过将cin和cout变成stringstream
s(至少暂时)来达到类似的效果。为此,请设置一个 std::stringbuf(或从std::stringstream
中"借用"一个)并使用cin.rdbuf(my_stringbuf_ptr)
更改cin
使用的streambuf
。您可能希望在测试拆解中还原此更改。为此,您可以使用如下代码:
stringbuf test_input("One line of input with no newline", ios_base::in);
stringbuf test_output(ios_base::out);
streambuf * const cin_buf = cin.rdbuf(&test_input);
streambuf * const cout_buf = cout.rdbuf(&test_output);
test_func(); // uses cin and cout
cout.rdbuf(cout_buf);
cin.rdbuf(cin_buf);
string test_output_text = test_output.str();
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 如果用户不小心给出了不正确的数据类型,cin 如何工作?
- 使用 CIN 和 COUT 在 C++ 中声明基本数据类型
- C++ 检查 cin 的输入是否正确数据
- C++:获取用户通过cin输入的数据类型
- 什么是cin的数据类型
- cin和cout如何支持不同的数据类型
- 将'std::cin'与数据结构成员结合使用
- 读取所有数据后进行无限cin循环
- Cin 执行不起作用 (程序.exe <文件与数据.txt)
- 如何使用cin读取字符数据以存储在数组中并显示
- cin 直接到向量<int>,当没有更多数据时断开循环
- 从std::cin中读取二进制数据
- 如何使用CIN在一行中捕获两种不同的数据类型
- 如何将字符串中的数据放入 cin 中
- 为什么 getline 在交换机中不起作用,并且 cin 没有正确获取数据
- c++检查cin是否有效数据不工作