将GoogleTest与通过STD :: CIN从用户输入的函数一起使用

Use googletest with a function that gets input from user via std::cin?

本文关键字:输入 函数 一起 用户 CIN GoogleTest STD      更新时间:2023-10-16

我如何使用googletest测试通过std :: cin?

依赖用户输入的函数

在下面的示例中,我正在寻找任何代码允许我在std :: cin流中添加" 2 n"用户的任何输入。

#include <iostream>
#include "gtest/gtest.h"
int readUserInput()
{
    int value;
    std::cout << "Enter a number: ";
    std::cin >> value;
    return value;
}
TEST(cin_test, Basic)
{
    // need code here to define "2n"
    // as the next input for std::cin
    ASSERT_EQ(readUserInput(), 2);
}
int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

向您的函数添加一个参数:

int readUserInput(std::istream& input)
{
    int value;
    std::cout << "Enter a number: ";
    input >> value;
    return value;
}
TEST(Some, Test) {
    std::ifstream ifs;
    ifs.open("someFile", std::ifstream::in);
    // in production code pass std::cin
    std::cout << "readUserInput from std::cin: " << readUserInput(std::cin) << std::endl;
    // in testing pass some mock data from the file (or whatever)
    std::cout << "readUserInput from ifs: " << readUserInput(ifs) << std::endl;
    ifs.close();
}

tl:dr

假设您将通过Jetbrains单元测试教程:https://www.jetbrains.com/help/clion/unit-testing-tutorial.html#adding-framework

MyLib/TaskTwo.cpp

//Write a program reading integers until zero is entered and printing the length of the longest sequence of consecutive numbers of the same value (and this value).

#include "TaskTwoResult.h"
#include <iostream>
using namespace std;
class TaskTwo { ;
public:
    TaskTwo() {
    }
    TaskTwoResult getLongestSequence(istream &std_input,
                                     ostream &std_output,
                                     ostream &result_output) {
        int largestToken = 0;
        int largestTokenOccurences = 0;
        int currentToken = 0;
        int currentOccurences = 0;
        std_output << "Please enter an integer value or enter 0 to stop" << endl;
        while (true) {
            int token = 0;
            std_output << "Enter value:";
            std_input >> token;
            if (token == 0) {
                result_output << "Longest sequence: " << largestTokenOccurences << " times " << largestToken;
                return {
                    largestToken,
                    largestTokenOccurences
                };
            }
            const bool isNewToken = token != currentToken;
            if (isNewToken) {
                currentToken = token;
                currentOccurences = 1;
            } else {
                currentOccurences++;
            }
            if (currentOccurences > largestTokenOccurences) {
                largestTokenOccurences = currentOccurences;
                largestToken = currentToken;
            }
        };
    }
};

Google_Test/MyTests.cpp

#include <gtest/gtest.h>
#include "TaskTwo.cpp"
using namespace std;

//This is just a group -> test name so it will later be reflected in your IDE unit testing window as a tree:
// getLongestSequence
//   | - Test1
//   | - Test2
//   | - Test3
TEST(getLongestSequence, Test1){
    //for input: 22 22 22 22 3 3 3 2 -6 -6 -6 0
    string test_input = "22n22n22n22n3n3n3n2n-6n-6n-6n0";
    string expected = "Longest sequence: 4 times 22";
    stringstream fake_input(test_input);
    ostringstream fake_output;
    ostringstream fake_result_output;
    TaskTwoResult result = TaskTwo().getLongestSequence(fake_input, fake_output, fake_result_output);
    string actual = fake_result_output.str();
    EXPECT_EQ(expected, actual);
}

另请参见:

  • 源代码:https://github.com/konradbartecki/cpp-stdin out-tests
  • https://www.jetbrains.com/help/clion/unit-testing-tutorial.html#adding-framework
  • 这篇文章也可以在我的博客上提供:https://bartecki.me/blog/cpp-testing-std-input-unput

如果您使用的是Linux,则可以创建管道,然后将stdin FD与" read"交换。管道的末端。这使您可以写入管道,然后std::cin将从管道中读取而不是实际的stdin

#include <gtest/gtest.h>
#include <iostream>
int readUserInput()
{
    int value;
    std::cout << "Enter a number: ";
    std::cin >> value;
    return value;
}
TEST(cin_test, Basic)
{
    // Create pipe to mock stdin
    int fildes[2];
    int status = pipe(fildes);
    ASSERT_NE(status, -1);
    // Swap `stdin` fd with the "read" end of the pipe
    status = dup2(fildes[0], STDIN_FILENO);
    ASSERT_NE(status, -1);
    // Create payload
    const char buf[] = "2n";
    const int bsize  = strlen(buf);
    // Send payload through pipe
    ssize_t nbytes = write(fildes[1], buf, bsize);
    close(fildes[1]);
    ASSERT_EQ(nbytes, bsize);
    ASSERT_EQ(readUserInput(), 2);
    close(fildes[0]);
}
int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}