googletest: как пропустить тест из внутреннего метода - PullRequest
0 голосов
/ 13 декабря 2018

С GTEST_SKIP, мы можем (условно) пропустить тест.Это реализуется следующим образом:

#define GTEST_SKIP_(message) \
  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)

Если мы находимся в основном теле теста, все в порядке.

Как я могу пропустить тест из глубины моегокодовая база? Это не работает:

int skip_this(int x) {
  if (x == 3) GTEST_SKIP();
  return x;
}

TEST(X, Y) {
  skip_this(2);
  skip_this(3);
  throw std::runtime_error("Did not skip");
}

Ошибка:

/Users/markus/Projekte/Opossum/Git/src/test/operators/aggregate_test.cpp:183:15: error: cannot initialize return object of type 'int' with an rvalue of type 'void'
  if (x == 3) GTEST_SKIP();
              ^~~~~~~~~~~~

Другими словами: как я могу изменить skip_this, чтобы тест прошел или был отмеченкак "пропущено"?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Это не очень хорошо, но работает для моей цели.Идея состоит в том, чтобы размотать стек, найти метод googletest, который вызвал тест, и сбросить указатель инструкции на этот кадр стека.

Обратите внимание, что стек не уничтожен должным образом, что означает, например,ресурсы могут просочиться.

#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <cxxabi.h>
#include <iostream>

#include <gtest/gtest.h>

void skip() {
  unw_cursor_t cursor;
  unw_context_t context;

  unw_getcontext(&context);
  unw_init_local(&cursor, &context);

  while (unw_step(&cursor)) {
    unw_word_t off;

    char symbol[256] = {"<unknown>"};
    char* name = symbol;

    if (!unw_get_proc_name(&cursor, symbol, sizeof(symbol), &off)) {
      int status;
      if ((name = abi::__cxa_demangle(symbol, nullptr, nullptr, &status)) == nullptr) name = symbol;
    }

    if (std::string(name) == "testing::Test::Run()") {
      ::testing::internal::AssertHelper(::testing::TestPartResult::kSkip, __FILE__, __LINE__, "skipped") = ::testing::Message();
      unw_resume(&cursor);
    }

    if (name != symbol) free(name);
  }

  throw std::runtime_error("Did not find test method on the stack, could not skip test");
}

Пример теста (может быть вставлен под кодом выше):

int foo(int x) {
  if (x == 3) skip();
  return 11;
}

TEST(SkipTest, ShouldNotBeSkipped) {
  foo(2);
  EXPECT_TRUE(false);
}

TEST(SkipTest, ShouldBeSkipped) {
  foo(3);
  EXPECT_TRUE(false);
}

TEST(SkipTest, TestExecutionContinues) {
  EXPECT_FALSE(false);
}

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

Вывод:

[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from SkipTest
[ RUN      ] SkipTest.ShouldNotBeSkipped
skip_test.cpp:44: Failure
Value of: false
  Actual: false
Expected: true
[  FAILED  ] SkipTest.ShouldNotBeSkipped (0 ms)
[ RUN      ] SkipTest.ShouldBeSkipped
[  SKIPPED ] SkipTest.ShouldBeSkipped (0 ms)
[ RUN      ] SkipTest.TestExecutionContinues
[       OK ] SkipTest.TestExecutionContinues (0 ms)
[----------] 3 tests from SkipTest (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.
[  SKIPPED ] 1 test, listed below:
[  SKIPPED ] SkipTest.ShouldBeSkipped
[  FAILED  ] 1 test, listed below:
[  FAILED  ] SkipTest.ShouldNotBeSkipped

 1 FAILED TEST
0 голосов
/ 13 декабря 2018

Вы не можете использовать GTEST_SKIP во внутренней функции.Это не вступит в силу.Я могу предложить только это решение или что-то подобное:

#define SKIPCODE -1

int skip_this(int x)
{
   if (x == 3)
      return SKIPCODE;
   else return x;
}

TEST(Test)
{
   int n = 3;

   if (skip_this(n) == SKIPCODE)
      GTEST_SKIP();
   ASSERT_TRUE(false);
}

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