C++和Google测试

4
我正在研究Google Test参数化测试。它们看起来非常好,但是,除非我漏掉了什么诀窍,否则我看不到如何为每个测试使用不同的测试数据。我使用了在在线上找到的一个示例,它很好用,但是如果我想为每个TEST_P提供不同的参数,似乎我需要创建一个新的类,即FooTest1、2、3、4等,以便为每个类提供INSTANTIATE_TEST_CASE_P。我认为我一定漏掉了什么。
class FooTest: public ::testing::TestWithParam < int >{....};

TEST_P(FooTest, DoesBar)
{
    ASSERT_TRUE(foo.DoesBar(GetParam());
}

INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); 

有没有人可以确认这是否可以通过其他方式实现?

谢谢。


1
请查看 testing::Values 部分 https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#how-to-write-value-parameterized-tests - stark
1
谢谢你的回复,Stark。不过我已经阅读过这个内容了。 你是在指这段话吗:“请注意,INSTANTIATE_TEST_CASE_P将实例化给定测试用例中的所有测试,无论其定义是在INSTANTIATE_TEST_CASE_P语句之前还是之后。”如果是这种情况,你是在暗示我不能实现我想要的吗? - Yos
1
给定夹具上的所有测试都与每组参数一起实例化。因此,将应具有不同参数的测试放在不同的夹具上。 - Useless
谢谢你们两位,看起来他们提到了这种方法,如果一个测试夹具类被普通测试和死亡测试共享,您可以使用typedef引入别名来避免重复代码:您会推荐这样做吗,而不是:class FooTest1: public ::testing::TestWithParam < int >{....}; class FooTest2: public ::testing::TestWithParam < int >{....}; - Yos
1个回答

4

很遗憾,这方面没有简单的解决方法。

每个INSTANTIATE_TEST_CASE_P实例化一个(参数化)测试夹具(class FooTest: public ::testing::TestWithParam < int >{....}),并使用提供的测试值范围进行实例化(在INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10))的情况下,使用从1到9的值 - 请记住,不包括结束值

每个定义为使用该夹具的TEST_P(例如TEST_P(FooTest, DoesBar))将针对值范围中的每个值执行一次(即GetParam()将在所有执行中返回1到9,其中"OneToTenRange"作为测试前缀)。

您可以为同一测试夹具添加第二个INSTANTIATE_TEST_CASE_P(例如:INSTANTIATE_TEST_CASE_P(TenToTwentyRange, FooTest, ::testing::Range(10, 20))),这将导致使用FooTest夹具的所有测试执行该范围(在此情况下为10到19,带有前缀"TenToTwentyRange")。

如果您不想让TEST_P执行特定范围(或使用不同参数),则需要创建一个单独的测试夹具,并根据您的需求进行实例化。从另一个角度来看,测试夹具定义了您运行的测试的参数(即GetParam()返回什么),并确保与其关联的每个TEST_P都针对/使用每个参数执行一次。

幸运的是,您可以使用以下技巧使事情变得更加容易:

创建一个包含所有设置/拆卸的普通(非参数化)测试夹具。然后从中派生出一个简单的参数化测试夹具,并通过INSTANTIATE_TEST_CASE_P进行实例化。

#include "gtest/gtest.h"

class BaseTest : public ::testing::Test
{
  // Do your common stuff here
};

// FooTest
class FooTest: public BaseTest, public testing::WithParamInterface<int>
{
 public:
  FooTest() : BaseTest() {}
};

TEST_P(FooTest, DoesFoo)
{
  ASSERT_TRUE(true);
}

INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));

// BarTest
class BarTest: public BaseTest, public testing::WithParamInterface<int>
{
 public:
  BarTest() : BaseTest() {}
};

TEST_P(BarTest, DoesBar)
{
  ASSERT_TRUE(true);
}

INSTANTIATE_TEST_SUITE_P(TenToTwentyRange, BarTest, ::testing::Range(10, 20));


int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

嗨CharonX,非常感谢您详细的回复。我现在已经实施了这种方法,一切都完美地运作。再次感谢。 - Yos
很高兴能够帮助 :) - CharonX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接