Как настроить Catch2 в проекте Bazel

Я запустил простой проект C++, который использует Bazel в качестве системы сборки и хотел бы добавить Catch2 к нему в качестве тестовой среды.

Вот так выглядит мой проект:

WORKSPACE -> empty file
src/
  Money.hpp
  Money.cpp
BUILD

где просто построить

cc_library(
  name = "Money",
  srcs = ["Money.cpp"],
  hdrs = ["Money.hpp"]
)

Я хотел бы иметь возможность создавать тесты для каждого cc_library, в данном случае для денег. Я попытался настроить его, но запутался с Catch2 main. Любой совет о том, как сделать это лучше всего ценится!

4 ответа

Catch2 (v2.13.0) поддерживается Bazel из коробки.

пример

WORKSPACE.bazel:

workspace(name = "Catch2Demo")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "catch2",
    strip_prefix = "Catch2-2.13.0",
    urls = ["https://github.com/catchorg/Catch2/archive/v2.13.0.tar.gz"],
)

BUILD.bazel:

cc_test(
    name = "my_test",
    srcs = ["my_test.cpp"],
    defines = ["CATCH_CONFIG_MAIN"],
    deps = [
        "@catch2",
    ],
)

my_test.cpp:

#include <catch2/catch.hpp>

unsigned int Factorial( unsigned int number ) {
    return number <= 1 ? number : Factorial(number-1)*number;
}

TEST_CASE( "Factorials are computed", "[factorial]" ) {
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

После некоторой перемотки мне удалось заставить это работать, для Bazel 0.16.1 и Catch2 2.4.0.

Сначала давайте создадим каталог test/ рядом с src/, чтобы держать наши тесты там.

Чтобы использовать Catch2, нам нужно скачать catch.hpp, Catch2 - это библиотека только для заголовков, что означает, что нам нужен только один файл. Я положил это в test/vendor/catch2/,
Затем нам нужно определить, как его использовать. В test/vendor/catch2 мы создаем следующий файл BUILD:

cc_library(
  name = "catch2",
  hdrs = ["catch.hpp"],
  visibility = ["//test:__pkg__"]
)

Теперь Базель распознает Catch2 как библиотеку. Мы добавили атрибут видимости, чтобы его можно было использовать из //test пакет (который определяется BUILD в /test каталог).

Далее, Catch2 требует, чтобы мы определили одну единицу перевода с правильно определенным основным методом. Следуя их инструкциям, мы создаем test/main.cpp файл:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

Теперь мы пишем наш тест, в test/Money.test.cpp:

#include "catch.hpp"
#include "Money.hpp"

TEST_CASE("Money works.") {
  ...
}

Наконец, нам нужно объяснить Базелю, как все это построить. Обратите внимание, что мы напрямую включили Money.hpp и catch.hpp в наши файлы без указания относительного пути, так что это также необходимо учитывать. Мы создаем следующие test/BUILD файл:

# We describe to Bazel how to build main.cpp.
# It includes "catch.hpp" directly, so we need to add
# "-Itest/vendor/catch2" compiler option.
cc_library(
    name = "catch-main",
    srcs = ["main.cpp"],
    copts = ["-Itest/vendor/catch2"],
    deps = [
        "//test/vendor/catch2"
    ]
)

# Here we define our test. It needs to build together with the catch2
# main that we defined above, so we add it to deps. We directly
# include src/Money.hpp and test/vendor/catch2/catch.hpp in
# Money.test.cpp, so we need to add their parent directories as copts.
# We also add Money and catch2 as dependencies.
cc_test(
    name = "Money",
    srcs = ["Money.test.cpp"],
    copts = ["-Itest/vendor/catch2/", "-Isrc/"],
    deps = [
        # Or "//test/vendor/catch2:catch2", it is the same.
        "//test/vendor/catch2",
        "catch-main",
        "//src:Money"
    ]
)

# Test suite that runs all the tests.
test_suite(
    name = "all-tests",
    tests = [
        "Money"
    ]
)

Наконец, нам просто нужно добавить visibility приписывать src/BUILD так что к нему можно получить доступ из тестов. Мы модифицируем src/BUILD выглядеть так:

cc_library(
    name = "Money",
    srcs = ["Money.cpp"],
    hdrs = ["Money.hpp"],
    visibility = ["//test:__pkg__"]
)

Окончательная структура файла выглядит следующим образом:

WORKSPACE
src/
  Money.hpp
  Money.cpp
  BUILD
test/
  BUILD
  main.cpp
  Money.test.cpp
  vendor/
    catch2/
      catch.hpp
      BUILD

Теперь вы можете запустить свои тесты с bazel test //test:all-tests!

Я создал Github репо с этим примером, вы можете проверить это здесь. Я также превратил это в сообщение в блоге.

Уловка2 v3 (3.1.1)

Catch2 v3 разделен на несколько заголовков, требует C++14 или выше и больше не предназначен только для заголовков, что немного меняет ситуацию.

РАБОЧАЯ ОБЛАСТЬ.bazel:
      workspace(name = "Catch2Demo")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "catch2",
    strip_prefix = "Catch2-3.1.1",
    urls = ["https://github.com/catchorg/Catch2/archive/v3.1.1.tar.gz"],
)
СТРОЙ.базел:
      cc_test(
    name = "my_test",
    srcs = ["my_test.cpp"],
    copts = ["-std=c++14"],
    deps = [
        "@catch2//:catch2_main",
    ],
)
мой_test.cpp:
      #include <catch2/catch_test_macros.hpp>

unsigned int Factorial( unsigned int number ) {
    return number <= 1 ? number : Factorial(number-1)*number;
}

TEST_CASE( "Factorials are computed", "[factorial]" ) {
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 );
}

Теперь запустите тесты с

      bazelisk test //:my_test --cxxopt='-std=c++14'

Поддержка Bazel была расширена до catch2: https://github.com/catchorg/Catch2/pull/1923

Используя это, вам просто нужно добавить в свое РАБОЧЕЕ МЕСТО:

http_archive(
  name = "com_github_catchorg_catch2",
  urls = ["https://github.com/catchorg/Catch2/archive/v2.12.1.tar.gz"],
  strip_prefix = "Catch2-2.12.1",
  sha256 = "e5635c082282ea518a8dd7ee89796c8026af8ea9068cd7402fb1615deacd91c3",
)

(замените версию и sha256 правильными значениями, если вам нужна более новая версия).

Тогда ваш файл сборки может просто сделать:

cc_library(
  name = "test_main",
  srcs = ["test_main.cpp"],
  deps = ["@com_github_catchorg_catch2//:catch2"],
)

с test_main.cpp который содержит:

#define CATCH_CONFIG_MAIN
#include "catch2/catch.hpp"

Наконец, вы можете определить такие тесты:

cc_library(
  name = "my_test",
  srcs = ["my_test.cpp"],
  deps = [
      ":test_main",
      "@com_github_catchorg_catch2//:catch2",
  ],
)
Другие вопросы по тегам