Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does google test sample put tests in an anonymous namespace?

This is NOT a duplicate of Superiority of unnamed namespace over static? Please read the question carefully before marking it as duplicate. I am not asking why use an unnamed namespace versus static!
I am asking, why are google tests placed inside an unnamed namespace? Is this some convention that google tests follow, and if so, why? The tests work fine whether they are in an unnamed namespace or not, so obviously it is not required.**

I cloned google test from github and built it for my mac. It works fine, but I noticed in the sample test code they give they place the tests in an unnamed namespace. Does anyone know why?

For example, see following file: googletest/googletest/samples/sample1_unittest.cc (https://github.com/google/googletest/blob/master/googletest/samples/sample1_unittest.cc#L41)

Part of the file looks like this:

// Step 1. Include necessary header files such that the stuff your
// test logic needs is declared.
//
// Don't forget gtest.h, which declares the testing framework.

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

// Step 2. Use the TEST macro to define your tests.
...
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);
}
...
}  // namespace

Does anyone know why all the tests are in an unnamed namespace? I tried removing the unnamed namespace and the sample still worked fine, so clearly it is not necessary for this particular sample.

like image 880
Daniel Goldfarb Avatar asked Dec 18 '17 02:12

Daniel Goldfarb


People also ask

What is the point of anonymous namespace?

An anonymous namespace makes the enclosed variables, functions, classes, etc. available only inside that file. In your example it's a way to avoid global variables. There is no runtime or compile time performance difference.

Does Google Test run tests in parallel?

gtest-parallel is a script that executes Google Test binaries in parallel, providing good speedup for single-threaded tests (on multi-core machines) and tests that do not run at 100% CPU (on single- or multi-core machines).

What is test fixture in Google Test?

If you find yourself writing two or more tests that operate on similar data, you can use a test fixture. This allows you to reuse the same configuration of objects for several different tests. To create a fixture: Derive a class from ::testing::Test .

How do I add a Google Test to a C++ project?

Add a Google Test project in Visual Studio 2022In Solution Explorer, right-click on the solution node and choose Add > New Project. Set Language to C++ and type test in the search box. From the results list, choose Google Test Project. Give the test project a name and choose OK.


1 Answers

I think the comment by Mike Kinghan answers the question, especially the part

You don't need to ask a programmer why haven't put stuff into the global namespace. You need to ask why they have.

However, I think its a good idea, pedagogically, to give an example of the kind of horrors that can happen if one doesn't follow good coding practices and as a consequence, violate ODR by mistake.

First, to relate the program below with the question, one needs to know that some of the Google Test macros create new classes. Now, consider the following program

myClass1.h

#ifndef MYCLASS1_H
#define MYCLASS1_H

int f();    

#endif  /* MYCLASS1_H */

myClass2.h

#ifndef MYCLASS2_H
#define MYCLASS2_H

int g();    

#endif  /* MYCLASS2_H */

myClass1.cpp

#include "myClass1.h"

class MyClass {
public:
    void twice() { val *= 2; }
    char val;
};    

int f() {
    MyClass x;
    x.val = 2;
    x.twice();
    return x.val;
}

myClass2.cpp

#include "myClass2.h"

class MyClass {
public:
    void twice() { val *= 2; }
    double val;
};    

int g() {
    MyClass x;
    x.val = 3;
    x.twice();
    return x.val;
}

main.cpp

#include <iostream>
#include "myClass1.h"
#include "myClass2.h"

int main() {
    std::cerr << f() << std::endl << g() << std::endl;
    return 0;
}

Notice how the class MyClass has two different definitions. With g++ 5.4.0-6ubuntu1~16.04.10, compiling and running the program with

g++ -O3 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined

prints 4 and 6, the expected behavior. However, compiling and running with no optimizations, i.e. with

g++ -O0 myClass1.cpp myClass2.cpp main.cpp -o undefined && ./undefined

prints 4 and 3!

Now, put this bug in a non-trivial program and you might easily loose an afternoon of debugging, especially if the bug laid dormant for a while. On the other hand, wrapping the classes in anonymous namespaces up-front takes no time at all and it prevents the bug. I think this illustrates one of the rationale behind some of the good coding practices: basic risk management.

like image 196
Kevin Avatar answered Oct 06 '22 16:10

Kevin