Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1543073
  • 博文数量: 596
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 173
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-06 15:50
个人简介

在线笔记

文章分类

全部博文(596)

文章存档

2016年(1)

2015年(104)

2014年(228)

2013年(226)

2012年(26)

2011年(11)

分类: C/C++

2013-12-04 10:59:30


  1. #include "gtest/gtest.h"


  2. #if GTEST_HAS_PARAM_TEST
  3. using ::testing::TestWithParam;
  4. using ::testing::Values;

  5. class fooTest : public ::testing::TestWithParam<const char*>{
  6. public:
  7.     const char* get() {
  8.         return _str;
  9.     }

  10.     /* 获取参数在 SetUp函数 */
  11.     virtual void SetUp() {
  12. //        _str = GetParam();
  13.         _str = NULL;
  14.     }
  15. protected:
  16.     const char *_str;
  17. };

  18. TEST_P(fooTest, disp) {
  19. //    ASSERT_STREQ("ok", _str);
  20.     ASSERT_STREQ("ok", get());

  21. }

  22. INSTANTIATE_TEST_CASE_P(InstantiationName, fooTest, ::testing::Values("ok"));


  23. #else

  24. // Google Test may not support value-parameterized tests with some
  25. // compilers. If we use conditional compilation to compile out all
  26. // code referring to the gtest_main library, MSVC linker will not link
  27. // that library at all and consequently complain about missing entry
  28. // point defined in that library (fatal error LNK1561: entry point
  29. // must be defined). This dummy test keeps gtest_main linked in.
  30. TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}

  31. #endif // GTEST_HAS_PARAM_TEST




  1. Value Parameterized Tests 正常的做法

  2. Value-parameterized tests allow you to test your code with different parameters without writing multiple copies of the same test.

  3. Suppose you write a test for your code and then realize that your code is affected by a presence of a Boolean command line flag.

  4. TEST(MyCodeTest, TestFoo) {
  5.   // A code to test foo().
  6. }

  7. Usually people factor their test code into a function with a Boolean parameter in such situations. The function sets the flag, then executes the testing code.

  8. void TestFooHelper(bool flag_value) {
  9.   flag = flag_value;
  10.   // A code to test foo().
  11. }

  12. TEST(MyCodeTest, TestFoo) {
  13.   TestFooHelper(false);
  14.   TestFooHelper(true);
  15. }
  16. 缺点:
  17. But this setup has serious drawbacks. First, when a test assertion fails in your tests, it becomes unclear what value of the parameter caused it to fail. You can stream a clarifying message into your EXPECT/ASSERT statements, but it you'll have to do it with all of them. Second, you have to add one such helper function per test. What if you have ten tests? Twenty? A hundred?

  18. Value-parameterized tests will let you write your test only once and then easily instantiate and run it with an arbitrary number of parameter values.

  19. Here are some other situations when value-parameterized tests come handy:

  20.     You want to test different implementations of an OO interface.
  21.     You want to test your code over various inputs (a.k.a. data-driven testing). This feature is easy to abuse, so please exercise your good sense when doing it!

高档做法

  1. How to Write Value-Parameterized Tests

  2. To write value-parameterized tests, first you should define a fixture class. It must be derived from both ::testing::Test and ::testing::WithParamInterface (the latter is a pure interface), where T is the type of your parameter values. For convenience, you can just derive the fixture class from ::testing::TestWithParam, which itself is derived from both ::testing::Test and ::testing::WithParamInterface. T can be any copyable type. If it's a raw pointer, you are responsible for managing the lifespan of the pointed values.
  3. 第一步 继承 ::testing::TestWithParam
  4. 用法1
  5. class FooTest : public ::testing::TestWithParam<const char*> {
  6.   // You can implement all the usual fixture class members here.
  7.   // To access the test parameter, call GetParam() from class
  8.   // TestWithParam<T>.
  9. };
  10. 用法2
  11. // Or, when you want to add parameters to a pre-existing fixture class:
  12. class BaseTest : public ::testing::Test {
  13.   ...
  14. };
  15. class BarTest : public BaseTest,
  16.                 public ::testing::WithParamInterface<const char*> {
  17.   ...
  18. };

  19. Then, use the TEST_P macro to define as many test patterns using this fixture as you want. The _P suffix is for "parameterized" or "pattern", whichever you prefer to think.
  20. 第二步使用
  21. TEST_P(FooTest, DoesBlah) {
  22.   // Inside a test, access the test parameter with the GetParam() method
  23.   // of the TestWithParam<T> class:
  24.   EXPECT_TRUE(foo.Blah(GetParam()));
  25.   ...
  26. }

  27. TEST_P(FooTest, HasBlahBlah) {
  28.   ...
  29. }

  30. Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test case with any set of parameters you want. Google Test defines a number of functions for generating test parameters. They return what we call ( parameter generators. Here is a summary of them, which are all in the testing namespace:

  31. Range(begin, end[, step])     Yields values {begin, begin+step, begin+step+step, ...}. The values do not include end. step defaults to 1.
  32. Values(v1, v2, ..., vN)     Yields values {v1, v2, ..., vN}.
  33. ValuesIn(container) and ValuesIn(begin, end)     Yields values from a C-style array, an STL-style container, or an iterator range [begin, end). container, begin, and end can be expressions whose values are determined at run time.
  34. Bool()     Yields sequence {false, true}.
  35. Combine(g1, g2, ..., gN)     Yields all combinations (the Cartesian product for the math savvy) of the values generated by the N generators. This is only available if your system provides the <tr1/tuple> header. If you are sure your system does, and Google Test disagrees, you can override it by defining GTEST_HAS_TR1_TUPLE=1. See comments in include/gtest/internal/gtest-port.h for more information.

  36. For more details, see the comments at the definitions of these functions in the source code.

  37. The following statement will instantiate tests from the FooTest test case each with parameter values "meeny", "miny", and "moe".
  38. 第三步 初始化的值
  39. INSTANTIATE_TEST_CASE_P(InstantiationName,
  40.                         FooTest,
  41.                         ::testing::Values("meeny", "miny", "moe"));

  42. To distinguish different instances of the pattern (yes, you can instantiate it more than once), the first argument to INSTANTIATE_TEST_CASE_P is a prefix that will be added to the actual test case name. Remember to pick unique prefixes for different instantiations. The tests from the instantiation above will have these names:

  43.     InstantiationName/FooTest.DoesBlah/0 for "meeny"
  44.     InstantiationName/FooTest.DoesBlah/1 for "miny"
  45.     InstantiationName/FooTest.DoesBlah/2 for "moe"
  46.     InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
  47.     InstantiationName/FooTest.HasBlahBlah/1 for "miny"
  48.     InstantiationName/FooTest.HasBlahBlah/2 for "moe"

  49. You can use these names in --gtest_filter.

  50. This statement will instantiate all tests from FooTest again, each with parameter values "cat" and "dog":

  51. const char* pets[] = {"cat", "dog"};
  52. INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest,
  53.                         ::testing::ValuesIn(pets));

  54. The tests from the instantiation above will have these names:

  55.     AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
  56.     AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
  57.     AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
  58.     AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"

  59. Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests in the given test case, whether their definitions come before or after the INSTANTIATE_TEST_CASE_P statement.

  60. You can see these files for more examples.

  61. Availability: Linux, Windows (requires MSVC 8.0 or above), Mac; since version 1.2.0.

总结

  1. Creating Value-Parameterized Abstract Tests

  2. In the above, we define and instantiate FooTest in the same source file. Sometimes you may want to define value-parameterized tests in a library and let other people instantiate them later. This pattern is known as abstract tests. As an example of its application, when you are designing an interface you can write a standard suite of abstract tests (perhaps using a factory function as the test parameter) that all implementations of the interface are expected to pass. When someone implements the interface, he can instantiate your suite to get all the interface-conformance tests for free.

  3. To define abstract tests, you should organize your code like this:

  4.     Put the definition of the parameterized test fixture class (e.g. FooTest) in a header file, say foo_param_test.h. Think of this as declaring your abstract tests.
  5.     Put the TEST_P definitions in foo_param_test.cc, which includes foo_param_test.h. Think of this as implementing your abstract tests.

  6. Once they are defined, you can instantiate them by including foo_param_test.h, invoking INSTANTIATE_TEST_CASE_P(), and linking with foo_param_test.cc. You can instantiate the same abstract test case multiple times, possibly in different source files.


阅读(1077) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~