Can I pass parameters to googletest test function
Asked Answered
C

4

10

After building my testfile, xxxxtest, with gtest can I pass a parameter when running the test, e.g. ./xxxxtest 100. I want to control my test function using the parameter, but I do not know how to use the para in my test, can you show me a sample in test?

Colony answered 29/2, 2012 at 9:42 Comment(2)
possible duplicate of How to pass parameters to the gtestContinuo
Here is another option: #5261407Obadiah
G
11

You could do something like the following:

main.cc

#include <string>
#include "gtest/gtest.h"
#include "my_test.h"

int main(int argc, char **argv) {
  std::string command_line_arg(argc == 2 ? argv[1] : "");
  testing::InitGoogleTest(&argc, argv);
  testing::AddGlobalTestEnvironment(new MyTestEnvironment(command_line_arg));
  return RUN_ALL_TESTS();
}


my_test.h

#include <string>
#include "gtest/gtest.h"

namespace {
std::string g_command_line_arg;
}

class MyTestEnvironment : public testing::Environment {
 public:
  explicit MyTestEnvironment(const std::string &command_line_arg) {
    g_command_line_arg = command_line_arg;
  }
};

TEST(MyTest, command_line_arg_test) {
  ASSERT_FALSE(g_command_line_arg.empty());
}
Gmur answered 1/3, 2012 at 3:20 Comment(5)
What's the purpose of the Environment descendant? Why not just g_command_line_arg = argc == 2 ? argv[1] : ""?Continuo
It's just to limit the scope of g_command_line_arg. Since it's in an unnamed namespace in my_test.h, it's not accessible outside of that translation unit.Gmur
Why does it give me an error of free(): invalid pointer <a_number>?Horst
Shouldn't you the inialization of command_line_arg after the InitGoogleTest, so you don't interfere with parameters to gtest itself?Fusillade
What if I want to have multiple arguments to pass?Tailpiece
E
7

You should be using Type-Parameterized Tests. https://github.com/google/googletest/blob/main/docs/advanced.md#type-parameterized-tests

Type-parameterized tests are like typed tests, except that they don't require you to know the list of types ahead of time. Instead, you can define the test logic first and instantiate it with different type lists later. You can even instantiate it more than once in the same program.

If you are designing an interface or concept, you can define a suite of type-parameterized tests to verify properties that any valid implementation of the interface/concept should have. Then, the author of each implementation can just instantiate the test suite with his type to verify that it conforms to the requirements, without having to write similar tests repeatedly.

Example

class FooTest: public ::testing::TestWithParam < int >{....};
    TEST_P(FooTest, DoesBar){
        ASSERT_TRUE(foo.DoesBar(GetParam());
    }

INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
Etem answered 15/9, 2014 at 17:48 Comment(3)
NOTE: INSTANTIATE_TEST_CASE_P is per-test-case, and NOT per-test. This means that for every instantiation the entire test-case (all test functions of it) will be executed with the given parameter, not having the flexibility to pass parameters with more granularity, i.e. to a specific test-function instead.Chloechloette
Also, you meant value-parameterized tests.Chloechloette
I upvoted this comment because it is usually true. However, there are situations where tests depend on some external resource that may differ between environments. And before you say "that's what mocks are for", you can't mock everything. Think about testing a cell-phone capability that actually uses the cell network. You have to call someone...Ceraceous
C
1

If you don't want to make your own main() function. You can also consider passing information via environment variables.

In my case I just wanted a flag to show debug information or not, so I used getenv().

Another option would be to put any needed information in a text file and read it from the test.

Collodion answered 21/1, 2020 at 23:39 Comment(0)
T
1

I have played around with the solutions here.

  • Using a custom testing::Environment is not easy to understand.
  • Using value-parameterized tests does not work, because the parameters are not known when INSTANTIATE_TEST_CASE_P() is evaluated.

So I used a simpler solution. The key part is that InitGoogleTest() removes all --gtest_* args. So we make the remaining ones globally available to all test cases:

#include <gtest/gtest.h>
#include <string>
#include <string_view>
#include <vector>

namespace
{
std::vector<std::string> commandLineArgs;
}

int main(int argc, char** argv)
{
   ::testing::InitGoogleTest(&argc, argv);
   // Save remaining argv into a global vector of strings
   for (int i = 1; i < argc; ++i)
   {
      commandLineArgs.push_back(argv[i]);
   }
   return RUN_ALL_TESTS();
}

TEST(foo, bar)
{
   const std::vector<std::string_view> expectedArgs = {"a", "b", "c", "1", "2", "3"};

   EXPECT_EQ(expectedArgs.size(), commandLineArgs.size());

   for (size_t i{0}; i < commandLineArgs.size(); ++i)
   {
      EXPECT_EQ(expectedArgs[i], commandLineArgs[i]);
   }
}
Trottier answered 12/3 at 10:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.