Skip to content
Alexander edited this page Feb 7, 2014 · 1 revision

Мы используем gtest для написания и запуска юнит-тестов. Эта страничка служит кратким гайдом.

Запуск тестов

Юниттесты сейчас собираются в цель сборки unit_tests (unit_tests.exe на windows). При запуске он запустит все тесты, которые в нем есть и выведет подробную информацию о них.

В случае, если есть необходимость запустить не все тесты, на помощь приходит параметр --gtest_filter. Он принимает список фильтров через запятую. Фильтр может быть включающим (просто маска имен) и исключающим (начинается с минуса). Поддерживается символ * для задания любого имени.

Пример (запустятся все тесты из base/values_unittest.cc, кроме содержащих в названии слово Dictionary):

./unit_tests --gtest_filter=ValuesTest.*,-ValuesTest.*Dictionary*

Написание тестов

Рекомендуется писать тесты в файлах .cc, с суффиксом _unittest. Добавляя файл тестов необходимо добавить его в цель unit_tests в CMakeLists.txt. Тесты автоматически будут зарегистрированы в gtest.

В файл нужно подключить gtest/gtest.h. Там находятся макросы и классы, инфраструктуры тестирования.

Имена тестов состоят из двух частей разделенных точкой. Часть до точки является общей для группы тестов, обычно расположенных в одном файле. Часть после точки индивидуальна для каждого теста.

Существует два типа тестов, тест-функция и тест-фикстура.

Тест-Функция

Самый простой тест, который читается как обычная функция. На самом деле, можно залесть в дебри и выяснить, что на каждую такую функцию генерируется отдельный класс и статическая переменная, а функция является методом этого класса, но это уже подробности реализации. Для создания теста нужно использовать макрос TEST(TestGroupName, TestName).

#include "gtest/gtest.h"

TEST(MyPrettyTest, HelloWorldTest) {
  EXPECT_EQ(4, 2 + 2);
}

Тест-фикстура

Этот тип тестов используется, когда удобно написать отдельный класс, выполняющий тестирование. В этом случае класс нужно унаследовать от testing::Test. Его имя будет совпадать с названием группы тестов, основанной на этом классе. В классе может быть конструктор по умолчанию, должен быть виртуальный деструктор и могут быть переопределены методы void testing::Test::SetUp() и void testing::Test::TearDown(), вызываемые для инициализации и деинициализации объекта. Тест создается с помощью макроса TEST_F(FixtureClassName, TestName), использование которого похоже на использование макроса TEST(group, name).

#include <algorithm>

#include "gtest/gtest.h"

class MyPrettyFixture : public testing::Test {
 public:
  MyPrettyFixture();
  virtual ~MyPrettyFixture();

  virtual void SetUp() override;
  virtual void TearDown() override;

  void DoSomeStuff(int* a, int* b);
};

MyPrettyFixture::MyPrettyFixture() {}
MyPrettyFixture::~MyPrettyFixture() {}

void MyPrettyFixture::SetUp() {}
void MyPrettyFixture::TearDown() {}

void MyPrettyFixture::DoSomeStuff(int* a, int* b) {
  std::swap(*a, *b);
}

TEST_F(MyPrettyFixture, SwapTest) {
  int a = 1, b = 2;
  DoSomeStuff(&a, &b);
  EXPECT_EQ(2, a);
  EXPECT_EQ(1, b);
}

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

Проверки

Для проверок внутри тестов есть набор макросов, которые помимо того, что производят проверку, выводят подробное сообщение в случае если проверка не прошла. Вот только краткий список:

EXPECT_EQ(expected, real)  // OK if equals
EXPECT_NE(expected, real)  // OK if not equals
EXPECT_TRUE(value)         // OK if true
EXPECT_FALSE(value)        // OK if false
EXPECT_GT(expected, real)  // OK if real greater then expected
EXPECT_GE(expected, real)  // OK if real greater then or equals to expected
EXPECT_LT(expected, real)  // OK if real less then expected
EXPECT_LE(expected, real)  // OK if real less then or equals to expected

Также существуют ассерты, эти проверки в случае провала прекращают выполнение теста.

ASSERT_EQ(expected, real)
ASSERT_NE(expected, real)
ASSERT_TRUE(value)
ASSERT_FALSE(value)
ASSERT_GT(expected, real)
ASSERT_GE(expected, real)
ASSERT_LT(expected, real)
ASSERT_LE(expected, real)

Как видно, они полностью соответствуют обычным проверкам.

Тест считается пройденным, если не провалилась ни одна проверка.