Showing posts with label Google Test. Show all posts
Showing posts with label Google Test. Show all posts

Friday, January 24, 2014

Google Test and Google Mock Using Matchers to change default behavior

This blog is in a series of blogs that talks about how to use Google Test and Google Mock in the VS2012 environment. This is the 8th blog in that series.

Matchers

—Matchers let developers set the default behavior based on the parameters passed into the macro. —Google Mock gives several matching macros

Wildcard

"_"argument can be any value of the correct type.
"A<type>() or An<type>()"argument can be any value of type type.

Generic Comparison

Eq(value) or valueargument == value
Ge(value)argument >= value
Gt(value)argument > value
Le(value)argument <= value
Lt(value)argument < value
Ne(value)argument != value
IsNull()argument is a NULL pointer (raw or smart).
NotNull()argument is a non-null pointer (raw or smart).
Ref(variable)argument is a reference to variable.
TypedEq<type>(value)argument has type type and is equal to value. You may need to use this instead of Eq(value) when the mock function is overloaded.

String Matchers

The argument can be either a C string or a C++ string object:
ContainsRegex(string)argument matches the given regular expression.
EndsWith(suffix)argument ends with string suffix.
HasSubstr(string)argument contains string as a sub-string.
MatchesRegex(string)argument matches the given regular expression with the match starting at the first character and ending at the last character.
StartsWith(prefix)argument starts with string prefix.
StrCaseEq(string)argument is equal to string, ignoring case.
StrCaseNe(string)argument is not equal to string, ignoring case.
StrEq(string)argument is equal to string.
StrNe(string)argument is not equal to string.
ContainsRegex() and MatchesRegex() use the regular expression syntax defined here. StrCaseEq(), StrCaseNe(), StrEq(), and StrNe()work for wide strings as well.

—Class Tested -

If you want to test for specific value returned from a method.
EXPECT_THAT(value, matcher)
ASSERT_THAT(value, matcher)
Here is an example
#include "gmock/gmock.h"

using ::testing::AllOf;
using ::testing::Ge;
using ::testing::Le;
using ::testing::MatchesRegex;
using ::testing::StartsWith;
...

  EXPECT_THAT(bankMock->getAccount(), StartsWith("MyAcc"));
  EXPECT_THAT(bankMock->getAccount(), MatchesRegex("MyAccount \\d+"));
  ASSERT_THAT(bankMock->getBalance(), AllOf(Ge(500), Le(1000)));

—Mocked Class -

If you want the behavior of a MOCKED class to behave based on the values of parameters passed to a method.
ON_CALL(mock_object, method(matchers))
EXPECT_CALL(mock_object, method(matchers) ...
Set up default behavior for you MOCK class in your test fixture SetUp() Method
virtual void SetUp() {
…
ExternalService::theBank = bankMock = new BitcoinBank_Mock();
ON_CALL(*bankMock,changeBalance(_,_))
   .WillByDefault(Return(100));
…
}
Override mock behavior in specific test cases.
TEST_F(BitcoinWallet_ULT,updateLocalBalanceTest) {
…
ON_CALL(*bankMock, changeBalance(StrEq("MyAccount"),_))
.WillByDefault(Return(100));
…
}
This gives me the ability to set up default behavior in the SetUp of the fixture and override it in the test case run of the Test.

I hope this helps clarify more about Matchers. There is actually even more information available at https://code.google.com/p/googlemock/wiki/CheatSheet#Matcher
DWP

Monday, December 30, 2013

Using Test Fixture in Google Test #7

In this Blog you will learn how to optimize setting up common environments for your tests using test fixtures in google test. 

What is a test Fixture

A Test Fixture allows you to creates setup and teardown method to run before each test is run in your test case. Test Fixtures are easy to create in google test. You just need to create a class that is the same name as your test case and inherit from the testing::Test class.
class BitcoinWallet_ULT : public testing::Test { public:  virtual void SetUp() {  }  virtual void TearDown() {  }};

How to use the Test Fixture

Now that you have a test fixture you need to let you tests know how to use the fixture. This is easy as well. Use the TEST_F macro instead of the TEST macro.
  • Without Test Fixture
    • TEST(BitcoinWallet_ULT,updateLocalBalanceTest)
  • With Test Fixture
    • TEST_F(BitcoinWallet_ULT,updateLocalBalanceTest)
Only use the TEST_F macro for tests in you test case that you want to use the test fixture. You don't have to use TEST_F if you test does not require setup.

What happens when TEST_F is called

The TEST_F macro will connect your test into the test fixture. This means that the following things will happen each time the TEST_F macro is run.
  1. Instantiate a fixture class - Calls new on the BitcoinWallet_ULT class
  2. Call SetUp on the fixture 
  3. Call the test
  4. Call TearDown on the fixture
  5. Destroy the fixture - Calls delete on the BitcoinWallet_ULT object created in step 1

What goes in Setup

Anything that is required to run the test (environment) that is common between all of a majority of the tests. Many tests in the same suite will have common variables that they use to run the tests. This typically include Mocks, and setup environment variables. I typically put these variables in the fixture as attributes. Then in the Setup Method I instantiate the objects and assign them to the attributes so they can be used in the tests. Also don't forget to destroy any objects you create in SetUp in the TearDown method. 
class BitcoinWallet_ULT : public testing::Test { public:  string myAccount;  BitcoinWallet* wallet;  BitcoinBank_Mock* bankMock;  BitcoinCommerce_Mock* commerceMock;  BitcoinCurrency_Mock* currencyMock;  virtual void SetUp() {   ExternalService::theBank = bankMock = new BitcoinBank_Mock();   ExternalService::theCommerce = commerceMock = new BitcoinCommerce_Mock();   ExternalService::theCurrency = currencyMock = new BitcoinCurrency_Mock();   wallet = new BitcoinWallet();  }  virtual void TearDown() {   delete(wallet);   delete(bankMock);   delete(commerceMock);   delete(currencyMock);  }};
Notice in the SetUp that I am setting variables for the ExternalService as well as the attribute to be used in the TEST_F macro. This allows me to change the behavior of the mock in the test itself. Also for each object I create in the SetUp I have a corresponding delete in the TearDown.

Using the TEST_F Macro

Now that the fixture is complete setup I can use it in my test case. All I need to do is change the TEST macro to TEST_F and remove any of the environment setup that the fixture now handles for me.

Before TEST_F

TEST(BitcoinWallet_ULT,updateLocalBalanceTestNoAccount) {  BitcoinBank_Mock* bankMock; ExternalService::theBank = bankMock = new BitcoinBank_Mock();   ON_CALL(*bankMock, changeBalance(_,_))    .WillByDefault(Return(-1));   BitcoinWallet* wallet = new BitcoinWallet();   ASSERT_EQ(wallet->updateLocalBalance(),ActionStatus::AccountNotExist); }

With TEST_F

TEST_F(BitcoinWallet_ULT,updateLocalBalanceTestNoAccount) {  ON_CALL(*bankMock, changeBalance(_,_))   .WillByDefault(Return(-1));  ASSERT_EQ(wallet->updateLocalBalance(),ActionStatus::AccountNotExist); }

I hope this helps with making your Unit Level Testing more effective.

DWP