12
votes

Since there's basically no documentation on the Google Test webpage—how do I do that? What I have done until now:

  • I downloaded googletest 1.6 from the project page and did a ./configure && make inside it
  • I added -Igtest/include -Lgtest/lib to my compiler/linker flags
  • I wrote a small sample test:

    #include "gtest/gtest.h"
    
    int main(int argc, char **args)
    {
      return 0;
    }
    
    TEST(someTest,testOne)
    {
      ASSERT_EQ(5,5);
    }
    

    This compiles fine, but the linker seems not to be amused at all. I get a huge pile of error messages in the style of

    test/main.o: In function someTest_testOne_Test::TestBody()': main.cpp:(.text+0x96): undefined reference totesting::internal::AssertHelper::AssertHelper(testing::TestPartResult::Type, char const*, int, char const*)'

Now what did I forget to do?

4
Did you add the libraries to the linker flags? It looks like you told it to look in the correct library location, but didn't actually tell it to link to the library itself.Xymostech
I tried adding -lgtest and -lgtest_main, but then I got the error that it couldn't find them. Although the files libgtest.la and libgtest_main.la are in the lib directory.Daniel Ziltener
Those .la files are not really the libraries. If you look in the $YOUR_BUILD_DIR/libs directory, you'll see a hidden directory called .libs. In that directory are normal .so files. You can configure things so that the la/hidden-so thing works, or just do what I did and copy the .so files to your library path.deong
Oh. That's embarassing. I'd downvote myself if I could... Actually I now changed it to -Lgtest/lib/.libs.Daniel Ziltener

4 Answers

3
votes

The best example Makefile is the one distributed with Google Test. It shows you how to link gtest_main.a or gtest.a with your binary based on whether you want to use Google's main() function or your own.

2
votes

Before I add something to a project makefile, I like to figure out what commands it is actually running. So here is a list of commands that I used to build the sample1 unit test by hand.

g++ -c -I../include sample1.cc

g++ -c -I../include sample1_unittest.cc

g++ -pthread -o s1_ut sample1.o sample1_unittest.o ../lib/.libs/libgtest.a ../lib/.libs/libgtest_main.a

Note: If you get a bunch of pthread related linker errors, you forgot the -pthread in the 3rd command. If you get a bunch of C++ runtime library related linker errors, you typed gcc instead of g++.

1
votes

Just as a reference I have a docker system setup with g++ and gtest which works properly. I provide all the files here for future reference:

Dockerfile

FROM gcc:9.2.0

WORKDIR /usr/src/app

RUN apt-get -qq update \
    && apt-get -qq install --no-install-recommends cmake \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN git clone --depth=1 -b master https://github.com/google/googletest.git
RUN mkdir googletest/build

WORKDIR /usr/src/app/googletest/build

RUN cmake .. \
    && make \
    && make install \
    && rm -rf /usr/src/app/googletest

WORKDIR /usr/src/app

COPY . .
RUN mkdir obj

RUN make

CMD [ "./main" ]

Makefile

CXX = g++
CXXFLAGS = -std=c++17 -Wall -I h -I /usr/local/include/gtest/ -c
LXXFLAGS = -std=c++17 -I h -pthread
OBJECTS = ./obj/program.o ./obj/main.o ./obj/program_unittest.o
GTEST = /usr/local/lib/libgtest.a
TARGET = main


$(TARGET): $(OBJECTS)
    $(CXX) $(LXXFLAGS) -o $(TARGET) $(OBJECTS) $(GTEST)
./obj/program.o: ./cpp/program.cpp
    $(CXX) $(CXXFLAGS) ./cpp/program.cpp -o ./obj/program.o
./obj/program_unittest.o: ./cpp/program_unittest.cpp
    $(CXX) $(CXXFLAGS) ./cpp/program_unittest.cpp -o ./obj/program_unittest.o
./obj/main.o: ./cpp/main.cpp
    $(CXX) $(CXXFLAGS) ./cpp/main.cpp -o ./obj/main.o
clean:
    rm -fv $(TARGET) $(OBJECTS)

cpp/maincpp

#include <iostream>
#include "program.h"
#include "gtest/gtest.h"

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    std::cout << "RUNNING TESTS ..." << std::endl;
    int ret{RUN_ALL_TESTS()};
    if (!ret)
        std::cout << "<<<SUCCESS>>>" << std::endl;
    else
        std::cout << "FAILED" << std::endl;
    return 0;
}

cpp/program.cpp

#include "program.h"

// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
int Factorial(int n)
{
    int result = 1;
    for (int i = 1; i <= n; i++)
    {
        result *= i;
    }

    return result;
}

// Returns true if and only if n is a prime number.
bool IsPrime(int n)
{
    // Trivial case 1: small numbers
    if (n <= 1)
        return false;

    // Trivial case 2: even numbers
    if (n % 2 == 0)
        return n == 2;

    // Now, we have that n is odd and n >= 3.

    // Try to divide n by every odd number i, starting from 3
    for (int i = 3;; i += 2)
    {
        // We only have to try i up to the square root of n
        if (i > n / i)
            break;

        // Now, we have i <= n/i < n.
        // If n is divisible by i, n is not prime.
        if (n % i == 0)
            return false;
    }

    // n has no integer factor in the range (1, n), and thus is prime.
    return true;
}

cpp/program_unittest.cpp

#include <limits.h>
#include "program.h"
#include "gtest/gtest.h"
namespace
{

// Tests Factorial().

// Tests factorial of negative numbers.
TEST(FactorialTest, Negative)
{
    // This test is named "Negative", and belongs to the "FactorialTest"
    // test case.
    EXPECT_EQ(1, Factorial(-5));
    EXPECT_EQ(1, Factorial(-1));
    EXPECT_GT(Factorial(-10), 0);

}

// Tests factorial of 0.
TEST(FactorialTest, Zero)
{
    EXPECT_EQ(1, Factorial(0));
}

// Tests factorial of positive numbers.
TEST(FactorialTest, Positive)
{
    EXPECT_EQ(1, Factorial(1));
    EXPECT_EQ(2, Factorial(2));
    EXPECT_EQ(6, Factorial(3));
    EXPECT_EQ(40320, Factorial(8));
}

// Tests IsPrime()

// Tests negative input.
TEST(IsPrimeTest, Negative)
{
    // This test belongs to the IsPrimeTest test case.

    EXPECT_FALSE(IsPrime(-1));
    EXPECT_FALSE(IsPrime(-2));
    EXPECT_FALSE(IsPrime(INT_MIN));
}

// Tests some trivial cases.
TEST(IsPrimeTest, Trivial)
{
    EXPECT_FALSE(IsPrime(0));
    EXPECT_FALSE(IsPrime(1));
    EXPECT_TRUE(IsPrime(2));
    EXPECT_TRUE(IsPrime(3));
}

// Tests positive input.
TEST(IsPrimeTest, Positive)
{
    EXPECT_FALSE(IsPrime(4));
    EXPECT_TRUE(IsPrime(5));
    EXPECT_FALSE(IsPrime(6));
    EXPECT_TRUE(IsPrime(23));
}

h/program.h

#ifndef GTEST_PROGRAM_H_
#define GTEST_PROGRAM_H_

// Returns n! (the factorial of n).  For negative n, n! is defined to be 1.
int Factorial(int n);

// Returns true if and only if n is a prime number.
bool IsPrime(int n);

#endif // GTEST_PROGRAM_H_

cpp/program.cpp and h/program.h files are from the googletest repo sample 1. Dockerfile is adapted from here.

1
votes

I installed Google Test on my system with sudo apt-get install libgtest-dev and the Fixture I'm working on doesn't have a main() and can be build with:

g++ unitTest.cpp -o unitTest /usr/src/gtest/src/gtest_main.cc /usr/src/gtest/src/gtest-all.cc -I /usr/include -I /usr/src/gtest -L /usr/local/lib -lpthread