GoogleTest 测试夹具说明
GoogleTest Test Fixture Clarification
当我编写测试夹具来测试一些 C 代码时,我使用相同的设置:
https://github.com/google/googletest/blob/master/googletest/docs/primer.md#test-fixtures-using-the-same-data-configuration-for-multiple-tests。待测c代码如下:
static struct {
uint32_t success;
uint32_t errors;
}stats;
uint32_t get_errors(void)
{
return stats.errors;
}
uint32_t get_success(void)
{
return stats.success;
}
void increment_errors(void)
{
stats.errors++;
}
void increment_success(void)
{
stats.success++;
}
void main_function(int arg)
{
if (arg >=0)
increment_success();
else
increment_errors();
}
现在,当我为此编写单元测试时:
class MyTest : public ::testing::Test
{
protected:
void SetUp(void)
{
}
void TearDown(void)
{
}
};
TEST_F(MyTest, Test1)
{
main_function(1);
EXPECT_EQ(1, decoder_get_success());
EXPECT_EQ(0, decoder_get_errors());
}
TEST_F(MyTest, Test2)
{
main_function(40);
EXPECT_EQ(1, decoder_get_success()); //This is a fail as number ends up being 2 not 1 which includes prev. test results
EXPECT_EQ(0, decoder_get_errors());
}
现在我注意到,当我为此代码编写不同的测试装置时,stats 结构变量的值不会重置,即如果第一个测试应该增加成功数,那么当我们开始第二个测试时,成功数= 1 不是 0 等等。我发现这种行为很奇怪,因为我认为它应该在每次测试时重置所有内容。
为了解决这个问题,我最终在 C 代码中添加了以下函数:
void stats_init(void)
{
decoder_stats.errors = 0;
decoder_stats.success = 0;
}
并将其添加到 TearDown():
void TearDown(void)
{
stats_init();
}
这可以确保所有内容都被重置。这里的问题是在使用测试夹具时这是 gtests 的正确行为吗?我认为不应该要求 m 定义 init() 函数并将其添加到 TearDown() 是错误的吗?
gtest 的正确行为是为您定义的每个 TEST_F 创建一个新的 MyTest 实例。
因此,通过在测试夹具中定义成员属性,您可以确保在每个 TEST_F
中将拥有不同的成员属性实例
不幸的是,您正在测试一个实例化一次的静态变量。 gtest 并没有神奇地知道它。所以,是的,您必须在每个 TEST_F.
之间重置静态结构的值
就我个人而言,我将使用 SetUp() 而不是 TearDown 来调用 stats_init。
当我编写测试夹具来测试一些 C 代码时,我使用相同的设置: https://github.com/google/googletest/blob/master/googletest/docs/primer.md#test-fixtures-using-the-same-data-configuration-for-multiple-tests。待测c代码如下:
static struct {
uint32_t success;
uint32_t errors;
}stats;
uint32_t get_errors(void)
{
return stats.errors;
}
uint32_t get_success(void)
{
return stats.success;
}
void increment_errors(void)
{
stats.errors++;
}
void increment_success(void)
{
stats.success++;
}
void main_function(int arg)
{
if (arg >=0)
increment_success();
else
increment_errors();
}
现在,当我为此编写单元测试时:
class MyTest : public ::testing::Test
{
protected:
void SetUp(void)
{
}
void TearDown(void)
{
}
};
TEST_F(MyTest, Test1)
{
main_function(1);
EXPECT_EQ(1, decoder_get_success());
EXPECT_EQ(0, decoder_get_errors());
}
TEST_F(MyTest, Test2)
{
main_function(40);
EXPECT_EQ(1, decoder_get_success()); //This is a fail as number ends up being 2 not 1 which includes prev. test results
EXPECT_EQ(0, decoder_get_errors());
}
现在我注意到,当我为此代码编写不同的测试装置时,stats 结构变量的值不会重置,即如果第一个测试应该增加成功数,那么当我们开始第二个测试时,成功数= 1 不是 0 等等。我发现这种行为很奇怪,因为我认为它应该在每次测试时重置所有内容。
为了解决这个问题,我最终在 C 代码中添加了以下函数:
void stats_init(void)
{
decoder_stats.errors = 0;
decoder_stats.success = 0;
}
并将其添加到 TearDown():
void TearDown(void)
{
stats_init();
}
这可以确保所有内容都被重置。这里的问题是在使用测试夹具时这是 gtests 的正确行为吗?我认为不应该要求 m 定义 init() 函数并将其添加到 TearDown() 是错误的吗?
gtest 的正确行为是为您定义的每个 TEST_F 创建一个新的 MyTest 实例。
因此,通过在测试夹具中定义成员属性,您可以确保在每个 TEST_F
中将拥有不同的成员属性实例不幸的是,您正在测试一个实例化一次的静态变量。 gtest 并没有神奇地知道它。所以,是的,您必须在每个 TEST_F.
之间重置静态结构的值就我个人而言,我将使用 SetUp() 而不是 TearDown 来调用 stats_init。