Using Google Test with Visual Studio

Google Test (gtest) is a nice framework for test-driving C++ applications. Since I am about to begin working with a team using C++ I decided to give it a try. That team uses Visual Studio so my objective was to use it with that tool. This is my experience.

Installation

It was very easy to build the framework. I simply downloaded and expanded the zip file, made all of the files in the msvc directory writable and then opened up one of the Visual Studio solutions included in the msvc directory. Since I was using VS10 the application converted the corresponding files.

I actually did this twice since the framework contains two solutions – one for using with the Multi-threaded DLL Runtime and another for using with the Multi-threaded static Runtime. I built the Debug and Release configurations for both solutions.

Create a solution that uses gtest

Now it was time to give it a try. I decided to write a simple bowling scorer application. I chose it because it would be small and simple to test drive. I really just wanted to understand how to setup a VS project that uses gtest and then how to use the framework. I started by creating a new solution with three projects.

The first project was a Static library Configuration type with No Common Language Runtime Support. This project was call BowlingGame and was where my production code would reside.

The second project was an Application Configuration type with No Common Language Runtime Support. This project was called RunBowlingGame and would just contain a main which was necessary to run my tests.

The final project was also a Static library Configuration type. It also had No Common Language Runtime Support but there are several additional settings that must exist. First of all under the C/C++ -> General section you must add the directory to the gtest include directory in the Additional Include Directories field. Under the Linker -> General section you must add the gtest directory to the Additional Libraries Directory. Include the msvc/gtest/Debug directory for your Debug configuration and the msvc/gtest/Release directory for you Release configuration. Finally, under the Linker -> Input section you must include the appropriate gtest libraries in the Additional Dependencies field. For Debug it would be gtestd.lib and gtest_maind.lib. This project was called TestBowlingGame and it had a dependency on both of the previous projects. Finally it has a Post-Build Event Command Line setup which was $(TargetDir)$(TargetFileName).

The Code

The code for the RunBowlingGame was very simple. Just a main. Here it is:

  
int main(int argc, char* argv[])
{
	return 0;
}

Once I wrote this code I was able to build the project and verify it worked. Now it was time to start writing tests. My first test is here:

  
TEST(BowlingGameTest, AllGuttersGetsZero)
{
	BowlingGame game;
	vector<int> rolls(20, 0);
	ASSERT_EQ(0, game.score(rolls));
}

I ran a build and got the error that BowlingGame didn’t exist. After creating the BowlingGame, adding a score method that returned 0, and performing another build the tests passed.

I’m not going to bore you will a step-by-step solving this kata. There are plenty of examples to be found that does this. I will just say that I found Google Test to be very easy to configure and use. I was also using a VS plugin called Visual Assist that provides very nice refactoring for C++.

Here the finished test suite:

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

using namespace std;

TEST(BowlingGameTest, AllGuttersGetsZero)
{
	BowlingGame game;
	vector%lt;int> rolls(20, 0);
	ASSERT_EQ(0, game.score(rolls));
}

TEST(BowlingGameTest, ThreeAndFourGetsSeven)
{
	BowlingGame game;
	vector<int> rolls(20, 0);
	rolls[0] = 3;
	rolls[1] = 4;
	ASSERT_EQ(7, game.score(rolls));
}

TEST(BowlingGameTest, AllOnesGetsTwenty)
{
	BowlingGame game;
	vector<int> rolls(20, 1);
	ASSERT_EQ(20, game.score(rolls));
}

TEST(BowlingGameTest, SpareAndTwoGetsFourteen)
{
	BowlingGame game;
	vector<int> rolls(20, 0);
	rolls[0] = 5;
	rolls[1] = 5;
	rolls[2] = 2;
	ASSERT_EQ(14, game.score(rolls));
}

TEST(BowlingGameTest, SpareOnLastFrameGetsExtraBall)
{
	BowlingGame game;
	vector<int> rolls(21, 0);
	rolls[18] = 5;
	rolls[19] = 5;
	rolls[20] = 2;
	ASSERT_EQ(12, game.score(rolls));
}

TEST(BowlingGameTest, StrikePlusTwoTwosGetsEighteen)
{
	BowlingGame game;
	vector<int> rolls(19, 0);
	rolls[0] = 10;
	rolls[1] = 2;
	rolls[2] = 2;
	ASSERT_EQ(18, game.score(rolls));
}

TEST(BowlingGameTest, StrikeGetsTwoExtraBalls)
{
	BowlingGame game;
	vector<int> rolls(21, 0);
	rolls[18] = 10;
	rolls[19] = 2;
	rolls[20] = 2;
	ASSERT_EQ(14, game.score(rolls));
}

TEST(BowlingGameTest, AllStrikesGetThreeHundred)
{
	BowlingGame game;
	vector<int> rolls(12, 10);
	ASSERT_EQ(300, game.score(rolls));
}

  
using namespace std;

class BowlingGame
{
public:
	int score(vector<int> rolls);

private:
	void ScoreOpenFrame( int &score, vector<int> rolls, int &pos );
	void ScoreSpare( int &score, vector<int> rolls, int &pos );
	void ScoreStrike( int &score, vector<int> rolls, int &pos );

	bool Spare( vector<int> rolls, int pos );
	bool Strike( vector<int> rolls, int pos );

	int FirstBall( vector<int> rolls, int pos );
	int SecondBall( vector<int> rolls, int pos );
	int ThirdBall( vector<int> rolls, int pos );
};

And finally the BowlingGame implementation:

  
int BowlingGame::score( vector<int> rolls )
{
	int score = 0;
	int pos = 0;
	for (int frame = 1; frame <= 10; ++frame) {
		if ( Strike(rolls, pos) )
			ScoreStrike(score, rolls, pos);
		else if ( Spare(rolls, pos) )
			ScoreSpare(score, rolls, pos);
		else
			ScoreOpenFrame(score, rolls, pos);
	}
	return score;
}

void BowlingGame::ScoreOpenFrame( int &score, vector<int> rolls, int &pos )
{
	score += FirstBall(rolls, pos) + SecondBall(rolls, pos);
	pos += 2;
}

void BowlingGame::ScoreSpare( int &score, vector<int> rolls, int &pos )
{
	score += FirstBall(rolls, pos) + SecondBall(rolls, pos) + ThirdBall(rolls, pos);
	pos += 2;
}

void BowlingGame::ScoreStrike( int &score, vector<int> rolls, int &pos )
{
	score += FirstBall(rolls, pos) + SecondBall(rolls, pos) + ThirdBall(rolls, pos);
	pos += 1;
}

bool BowlingGame::Spare( vector<int> rolls, int pos )
{
	return 10 == FirstBall(rolls, pos) + SecondBall(rolls, pos);
}

bool BowlingGame::Strike( vector<int> rolls, int pos )
{
	return 10 == FirstBall(rolls, pos);
}

int BowlingGame::FirstBall( vector<int> rolls, int pos )
{
	return rolls[pos];
}

int BowlingGame::SecondBall( vector<int> rolls, int pos )
{
	return rolls[pos+1];
}

int BowlingGame::ThirdBall( vector<int> rolls, int pos )
{
	return rolls[pos+2];
}

2 thoughts on “Using Google Test with Visual Studio

  1. Pingback: Tweets that mention Using Google Test with Visual Studio | CheezyWorld -- Topsy.com

Leave a Reply

Your email address will not be published. Required fields are marked *