我需要为不是由我编写的小型学习计划编写测试(使用谷歌测试框架)。 (这只是一个小型控制台游戏,它可以从命令行获取模式或只是在运行时获取它) 有一个问题:我无法改变源代码,但几乎所有方法都使用了cout和cin。我的问题是“如何在测试时回答programm的请求(cin)(比如从字符串获取cin的数据)?”。
答案 0 :(得分:5)
假设您可以控制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
以从字符串流中读取。它也可以是任何其他流缓冲区。
答案 1 :(得分:1)
我的理解是您需要执行以下操作:
标准C ++语言没有与其他程序通信的标准工具。您将需要操作系统的帮助(您未指定)。
使用仅限C ++ 或没有特定于操作系统的调用,我建议:
否则,搜索您的OS API以了解如何写入I / O重定向驱动程序。
答案 2 :(得分:1)
我知道你说你不能修改代码,但我会像你一样回答这个问题。现实世界通常允许(小)修改以适应测试。
一种方法是将需要外部输入(数据库,用户输入,套接字等)的调用包装在虚拟函数调用中,这样就可以将它们模拟出来。 (以下示例)。但首先,有关测试的书籍推荐。 Working Effectively with Legacy Code是一本很好的书,用于测试不仅限于遗留代码的技术。
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());
}
答案 3 :(得分:1)
您可以直接使用cin
和cout
来提高课程的可测试性。而是使用istream&
和ostream&
将输入源和输出接收器作为参数传递。这是依赖注入的情况。如果您这样做,则可以传入std::stringstream
而不是cin
,以便您可以提供指定的输入并获取测试框架的输出。
也就是说,你可以通过将cin和cout变成stringstream
s(至少是暂时的)来达到类似的效果。为此,请设置std :: stringbuf(或从std::stringstream
“借用”)并使用cin.rdbuf(my_stringbuf_ptr)
更改streambuf
使用的cin
。您可能希望在测试拆卸中恢复此更改。为此,您可以使用以下代码:
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();