【问题标题】:How to mark some test cases in TYPED_TEST as expected to fail?如何在 TYPED_TEST 中将某些测试用例标记为预期失败?
【发布时间】:2020-11-15 17:11:33
【问题描述】:

我正在从事一个 C++ 学习项目,其双重目标是学习如何编写模板代码以及学习如何使用 GoogleTest。我的项目目标是实现一个工作四元数类以及使用 GoogleTest 编写的功能测试。

到目前为止,我的课程运行良好,但我想将一些 GoogleTest 测试用例标记为“预期失败”。 这是四元数相关构造函数的签名 -

template <typename T>
class quaternion {
  template <typename U, typename V, typename W, typename X>
  quaternion(U u, V v, W w, X x);
};

我正在使用 GoogleTest 编写一些 TYPED_TEST 测试用例,我尝试使用诸如 unsigned char、char 等初始化器创建给定类型 T 的四元数...

这是我的类型列表

using MyTypes = ::testing::Types<char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double>;

这是测试夹具 -

TYPED_TEST(QuaternionTests, DirectInitialization00) {
  unsigned int i = 5, j = 235, k = 67, l = 82;
  this->SetUp(i, j, k, l);
  EXPECT_EQ(this->q.a, 5);
  EXPECT_EQ(this->q.b, 235);
  EXPECT_EQ(this->q.c, 67);
  EXPECT_EQ(this->q.d, 82);
}

SetUp 只调用 quaternion 构造函数。

当然,当四元数的类型为 char 时,此测试会失败,因为 quaternion 不能为值 235 (unsigned int)成员b

我的问题是 - 有没有办法将 T == charunsigned int 的特定组合在TYPED_TEST 宏?还是我必须切换到常规的 TEST 宏?

【问题讨论】:

    标签: c++ googletest


    【解决方案1】:

    您可以修改测试主体来处理这种情况。据我所知,没有办法将类型参数标记为预期失败。

    [例如,在 Python 的 pytest 框架中,pytest.param(int, marks=pytest.mark.xfail) 可以做到这一点。]

    当然可以自省类型参数并从测试体中跳过测试。我怀疑可以从 Google Test 1.10.0 获得的 Google Test now has a GTEST_SKIP() macro

    如果该宏不可用,您可以使用less explicit SUCCEED() macro,后跟return 语句:

    TYPED_TEST(QuaternionTests, DirectInitialization00) { 
      // Could also check `std::numeric_limits<T>::max()` 
      // or `sizeof(T)`.
      using T = typename QuaternionTests::TypeParam;
      if constexpr (std::is_same_v<T, char>) {
        // with gtest version 1.10.0 and later (?):
        GTEST_SKIP() << "Test is not valid with T equal to `char`.";
    
        // or with older versions gtest:
        SUCCEED() << "Test is not valid with T equal to `char`.";
        return; 
      }
    
      unsigned int i = 5, j = 235, k = 67, l = 82;
      this->SetUp(i, j, k, l);
    
      EXPECT_EQ(this->q.a, 5);  
      EXPECT_EQ(this->q.b, 235);
      EXPECT_EQ(this->q.c, 67);
      EXPECT_EQ(this->q.d, 82);
    }
    

    另一种选择是引入一个更多信息类型参数,其中包含标量类型,以及有关是否期望成功的信息。例如:

    template <typename T, bool ExpectSuccess = true>
    struct QTestParam {
      using type = T;
      using expect_success = std::bool_constant<ExpectSuccess>;
    };
    
    using MyTypes = ::testing::Types<
       QTestParam<char, /*ExpectSuccess*/ false>,
       QTestParam<short int>,
       QTestParam<int>,
       QTestParam<long int>,
       QTestParam<float>,
       QTestParam<double>,
    >;
    

    然后,您可以像这样定义一个测试类模板,它以一种很好的方式提供对布尔指标的访问:

    template <typename Param>
    struct QuaternionTests : public ::testing::Test {
      using T = Param::type;  // scalar type such as int.
    
      constexpr static bool ExpectSuccess() {
        return Param::expect_success{};
      }
      constexpr static bool ExpectFailure() {
        return !ExpectSuccess();
      }
    };
    

    不幸的是,我认为单个测试需要像第一个代码 sn-p 中那样实现“跳过”逻辑:

    TYPED_TEST(QuaternionTests, DirectInitialization00) {
      constexpr if (ExpectFailure()) {
        GTEST_SKIP();
      }
      // [...]
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-02
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多