单元测试其目的是副作用的函数

时间:2010-05-06 16:23:59

标签: c++ unit-testing

你如何进行单元测试do_int_to_string_conversion?

#include <string>
#include <iostream>

void do_int_to_string_conversion(int i, std::string& s) {
    switch(i) {
    case 1:
        s="1";
        break;
    case 2:
        s="2";
        break;
    default:
        s ="Nix";
    }
}

int main(int argc, char** argv){
    std::string little_s;

    do_int_to_string_conversion(1, little_s);
    do_int_to_string_conversion(2, little_s);
    do_int_to_string_conversion(3, little_s);

}

5 个答案:

答案 0 :(得分:11)

我没有担心如何测试它的功能,而是重新设计了更合理的功能,并测试了重新设计的版本。

现在,该函数似乎有三个独立的(并且只是略微相关)职责:执行转换,修改外部提供的字符串,并将一些数据写入流。它写入的流(std::cout)也是硬编码的 - 等待发生的问题(例如,转换到GUI环境可能非常重要)。

我首先将1)拆分为逻辑函数,然后2)将流作为参数提供。

std::string convert_int(int val) {
    switch (val) { 
       case 1: return "1";
       case 2: return "2";
       default: return "Nix";
   }
}

std::ostream &write_string(std::ostream &os, std::string const &s) { 
    return os << s;
}

我没有包含任何内容(特别是)修改外部提供的字符串 - 显然你可以根据需要分配来自convert_int的返回值,以及传入的字符串的值isn'无论如何都要使用。

说实话,write_string是完全被淘汰的好人选,但由于你拥有那种基本的能力,我们暂时保留它。测试这些相对简单 - 对于convert_int,我们查看它返回的字符串,并与我们的预期进行比较。对于write_string,我们可以传递stringstream而不是普通ostream - 然后我们可以使用.str()将结果作为字符串传递,并且(再次)与我们的期望。

答案 1 :(得分:9)

我认为这只是一个例子。为什么不能在每次调用后断言little_s的值?

do_int_to_string_conversion(1, little_s);
assert_are_equal("1", little_s);

答案 2 :(得分:3)

如果确实需要确保输出已写入,则需要打破对std::cout的依赖,并在测试期间使用其他std::ostream

这可能像全局变量一样简单:

#if PRODUCTION
std::ostream my_output = std::cout;
#else
std::ostream my_output = std::ostringstream;
#endif

void setup()
{
    my_output = std::ostringstream;
}

void print_hello()
{
    my_output << "hello";
}

void test_hello_was_printed()
{
    print_hello();
    ASSERT("hello" == my_output.str());
}

或类似的效果。

答案 3 :(得分:3)

我要更改do_int_to_string_conversion以便它只做一件事(将in转换为字符串)。

void do_int_to_string_conversion(int i, std::string& s) {
    switch(i) { ... }
}

这没有任何副作用,因此您可以编写一个简单的单元测试来验证输出。

如果我需要一个打印转换结果的函数,我会把它放在一个单独的函数中,并且我会对输出流进行参数化。

void output_int(int i, ostream &stream) {
    std::string s;
    do_int_to_string_conversion(i, s);
    stream << s;
}

要进行单元测试,我会传入一个std :: stringstream对象并检查结果。

答案 4 :(得分:-1)

您可以使用Expect之类的内容向其传递一些输入并验证其输出是否应该是它。