C++ project with Bazel and GTest
Asked Answered
L

3

22

I want to create a Bazel C++ project with gtest for unit tests.

What is the minimal setup?

(I only have Bazel installed on my computer and I am running under Linux)

Lection answered 22/8, 2017 at 10:5 Comment(0)
D
30

This is even easier now that googletest provides a BUILD file:

In WORKSPACE

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
    name = "gtest",
    remote = "https://github.com/google/googletest",
    branch = "v1.10.x",
)

In BUILD

cc_test (
    name = "hello_test",
    srcs = [
        "hello_test.cc",
    ],
    deps = [
        "@gtest//:gtest",
        "@gtest//:gtest_main" # Only if hello_test.cc has no main()
    ],
)
Dado answered 14/8, 2018 at 18:32 Comment(1)
Thanks! This allows to not have gmock.BUILD in the parent directory.Perineum
L
26

The project structure is:

.
├── bin
│   ├── BUILD
│   ├── hello.cpp
├── MyLib
│   ├── BUILD
│   ├── message.hpp
│   ├── message.cpp
│   ├── ... 
├── test
│   ├── BUILD
│   ├── message_test.cpp
│   ├── ... 
├── gmock.BUILD
└── WORKSPACE

Files related to Bazel+GTest

  • WORKSPACE

There you download gtest from github:

new_git_repository(
    name = "googletest",
    build_file = "gmock.BUILD",
    remote = "https://github.com/google/googletest",
    tag = "release-1.8.0",
)

You define a gmock BUILD file defined below:

  • gmock.BUILD

This BUILD file is in charge of compiling gtest/gmock:

cc_library(
      name = "gtest",
      srcs = [
            "googletest/src/gtest-all.cc",
            "googlemock/src/gmock-all.cc",
      ],
      hdrs = glob([
          "**/*.h",
          "googletest/src/*.cc",
          "googlemock/src/*.cc",
      ]),
      includes = [
          "googlemock",
          "googletest",
          "googletest/include",
          "googlemock/include",
      ],
      linkopts = ["-pthread"],
      visibility = ["//visibility:public"],
  )

  cc_library(
      name = "gtest_main",
      srcs = ["googlemock/src/gmock_main.cc"],
      linkopts = ["-pthread"],
      visibility = ["//visibility:public"],
      deps = [":gtest"],
  )
  • test/BUILD

This build file generate the tests:

cc_test(
    name = "MyTest",
    srcs = glob(["**/*.cpp"]),
    deps = ["//MyLib:MyLib",
           "@googletest//:gtest_main"],
)

The test/message_test.cpp file is defined by:

#include "gtest/gtest.h"

#include "MyLib/message.hpp"

TEST(message_test,content)
{
  EXPECT_EQ(get_message(),"Hello World!");
}

And that is all! The other files are defined as usual:

Files for the supporting example

  • MyLib/BUILD

Creates the libMyLib.so and libMyLib.a libraries.

cc_library(
    name="MyLib",
    hdrs=glob(["**/*.hpp"]),
    srcs=glob(["**/*.cpp"]),
    visibility = ["//visibility:public"],
)

with a basic message.hpp

#include <string>

std::string get_message();

and message.cpp

#include "MyLib/message.hpp"

std::string get_message()
{
   return "Hello World!";
}

example.

  • bin/BUILD

Creates the hello executable.

cc_binary(
    name = "hello",
    srcs = ["hello.cpp"],
    deps = ["//MyLib:MyLib"],
)

which is:

#include "MyLib/message.hpp"

#include <iostream>

int main()
{
  std::cout << "\n" << get_message() << std::endl;

  return EXIT_SUCCESS;
}

Usage:

  • Compiles all targets:

This will also download gtest from its github repo and compile it

bazel build ...
  • Checks the hello target:

You can run it with:

bazel run bin:hello
  • Running your tests using GTest

That was the main point of this note:

bazel test ... --test_output=errors

You should get something like:

INFO: Analysed 3 targets (0 packages loaded).
INFO: Found 2 targets and 1 test target...
INFO: Elapsed time: 0.205s, Critical Path: 0.05s
INFO: Build completed successfully, 2 total actions
//test:MyTest   
PASSED in 0.0s
Executed 1 out of 1 test: 1 test passes.

Reproduce the results

For your ease I have created a github repo containing this example. I hope it works out of the box.

Lection answered 22/8, 2017 at 10:5 Comment(3)
If you also need some data files for your tests, #46101406 describes how to manage that.Lection
googletest repository contains bazel build file github.com/google/googletest/blob/master/BUILD.bazel Could I somehow provide it to Bazel without explicitly copying the file to my project?Hodgepodge
@Hodgepodge That BUILD.bazel is for building gtest. When you use gtest as a third party library in your project, all you need is a git_repository or local_repository rule. Then bazel knows how to compile gtest as a library, so you don't need to explicitly copy the BUILD file.Brotherinlaw
A
0

The current recommended practice is to use http_archive to avoid depending on the system git and take advantage of repository cache.

In WORKSPACE

# 5376968f6948923e2411081fd9372e71a59d8e77 is the commit sha for v1.12.0. 
# Periodically update to the latest to "live at head"
http_archive(
    name = "com_google_googletest",
    sha256 = "199e68f9dff997b30d420bf23cd9a0d3f66bfee4460e2cd95084a2c45ee00f1a",
    strip_prefix = "googletest-5376968f6948923e2411081fd9372e71a59d8e77",
    urls = ["https://github.com/google/googletest/archive/5376968f6948923e2411081fd9372e71a59d8e77.zip"],
)

In test/BUILD

cc_test(
    name = "test_greet",
    srcs = ["greeting_test.cpp"],
    deps = [
        "//src:greeting",
        "@com_google_googletest//:gtest_main",
    ],
)
Agace answered 26/6, 2022 at 0:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.