Jump to content
  • Advertisement
  • entries
    28
  • comments
    29
  • views
    5467

C++ Set Up GTest for TDD. C++, VS

8Observer8

3052 views

Before I will start I want to advise you to read this book: The Art of Unit Testing: with examples in C#. Yes, as you can see this book contains examples in C# but it is not important. This book contain very useful and important information how to write unit tests.

I made an example of project in VS 2015: SortFunctions.zip  This project will show you how set up Google Test in Visual Studio and run simple unit tests.

Note. If you have another version of VS then before you will run unit tests you need to select VS 2017, like in this screenshot:

Spoiler

PlatformToolset.png.3c9a59798e0e30baeee97b337b6bbe48.png

Google Test library is included in the project as source folder and it is placed in "Libs" folder. You need to:

  • open the solution. The solution is file with name: "SortFunctions.sln"
  • select your version of VS, for example VS 2017 instead of VS 2015 as in screenshot above
  • make the "SortFunction_UnitTests" project as "StartUp Project". For this: make right mouse button click on the "SortFunction_UnitTests" project -> select "Set as StartUp Project"
  • press Ctrl+F5 to run unit tests

You will see this settings in the "SortFunction_UnitTests" project properties:

$(SolutionDir)Libs\gtest-1.8.1\include
$(SolutionDir)Libs\gtest-1.8.1
$(SolutionDir)SortFunction

This solution include two projects:

  • SortFunctions - this project contains modules that we want to test. For example, bubbleSort() method
  • SortFunctions_UnitTests - this project contains unit tests

Add existing files to the "SortFunctions_UnitTests" project:

  • YourSolutionDir/Libs/gtest-1.8.1/src/gtest-all.cc
  • YourSolutionDir/SortFunctions/SortFunctions.cpp

The "SortFunctions" project has two files:

SortFunctions.h

#pragma once
 
extern void bubbleSort(int *array, unsigned int amount);
 
extern void countingSort(int *array, unsigned int amount);

SortFunctions.cpp

#include "SortFunctions.h"
 
void bubbleSort(int *array, unsigned int amount)
{
 
}
 
void countingSort(int *array, unsigned int amount)
{
 
}

The "SortFunctions_UnitTests" project has tests. For example, this is the "bubbleSortTests.cpp" with two tests. The first test is for positive numbers and the second test is for negative numbers:

bubbleSortTests.cpp

#include <gtest/gtest.h>
 
#include "SortFunctions.h"
 
TEST(bubbleSortTest, AllPositiveElements)
{
    // Arrange
    const unsigned int amount = 5;
    int actualArray[amount] = { 5, 3, 10, 2, 7 };
    int expectedArray[amount] = { 2, 3, 5, 7, 10 };
 
    // Act
    bubbleSort(actualArray, amount);
 
    // Assert
    for (size_t i = 0; i < amount; i++)
    {
        ASSERT_EQ(expectedArray[i], actualArray[i]);
    }
}
 
TEST(bubbleSortTest, AllNegativeElements)
{
    // Arrange
    const unsigned int amount = 5;
    int actualArray[amount] = { -5, -3, -10, -2, -7 };
    int expectedArray[amount] = { -10, -7, -5, -3, -2 };
 
    // Act
    bubbleSort(actualArray, amount);
 
    // Assert
    for (size_t i = 0; i < amount; i++)
    {
        ASSERT_EQ(expectedArray[i], actualArray[i]);
    }
}

main.cpp

#include <gtest/gtest.h>

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

 



6 Comments


Recommended Comments

" I opened Setting of the project and add these lines to "C/C++" -> "General" -> "Additional Include Directories": "

It's a lot better creating .prop files for you projects under Property Manager. You can reuse them (put in a common folder) for every other project that uses similar libs/settings. Or you can copy and 'fork' them for a new project. It also relieves the frustration of not picking Release settings when in Debug or vice-versa (What a load of crap that is, right?). If interested, it's has a tab near the Solution Explorer pane tab, close to the bottom.

Oh and... Tests? Tests? We don't need no stinkin' tests. :D j/k

Share this comment


Link to comment
7 hours ago, fleabay said:

It's a lot better creating .prop files for you projects under Property Manager. You can reuse them (put in a common folder)

It useful for projects on my computer where each library has only on copy. But I include libraries in some projects because I need to public VS projects and everyone can open it and run them immediately. I make the "Libs" folder inside each such solution, put all necessary libraries to the "Libs" folder and connect them to the project using "$(SolutionDir)Libs\..." paths.

Share this comment


Link to comment

I added this information:

Quote

Before I will start I want to advise you to read this book: The Art of Unit Testing: with examples in C#. Yes, as you can see this book contains examples in C# but it is not important. This book contain very useful and important information how to write unit tests.

 

Edited by 8Observer8

Share this comment


Link to comment

I added:

Add existing files to the "SortFunctions_UnitTests" project:

  • YourSolutionDir/Libs/gtest-1.8.1/src/gtest-all.cc
  • YourSolutionDir/SortFunctions/SortFunctions.cpp

Share this comment


Link to comment

I add contents of the "main.cpp" for running the unit tests:

main.cpp

#include <gtest/gtest.h>

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

 

Edited by 8Observer8

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By Harry Loretz
      Hello everyone, 

      I appreciate any help i can get. So i recently started getting this message listed bellow in visual studio when i would compile any game i have for UE4.23.0. 

      1>EXEC : [1/28] error : Unable to create child process
      I have no idea how to fix this, and also i really don't want to have to set all the classes again in a new project.

      Second thing is that i can not move my Character on the Sever when testing multiplayer after adding "Role = ROLE_Authority" to sections in an AI Tracker bot class that i created as a part of Tom Loomans Course on Udemy. I am not following Tom Loomans course 100%, Do i need to add sever implementation to my character because i am using different movement code then what Tom uses? I Am happy to share some screen shots if needed. 
       
      Please help, thankyou for your time.
    • By phil67rpg
      I have a very simple question, I am trying to rotate some vertex's around an arbitrary axis. basically I want to use glRotatef and glTranslatef to rotate a space ship I have drawn on the screen. here is my code of my  ship. what it does do is rotate around the origin when I  use the arrow keys left and right.
      void drawShip() { glPushMatrix(); glColor3f(255.0f, 0.0f, 0.0f); glTranslatef(-50.0f, 0.0f, 0.0f); glRotatef(rotateship, 0.0f, 0.0f, 1.0f); glBegin(GL_LINE_LOOP); glVertex3f(50.0f, 0.0f, 0.0f); glVertex3f(45.0f, -5.0f, 0.0f); glVertex3f(50.0f, 10.0f, 0.0f); glVertex3f(55.0f, -5.0f, 0.0f); glEnd(); glTranslatef(50.0f, 0.0f, 0.0f); glPopMatrix(); }  
    • By mujina
      What could be a way of avoiding using inheritance and virtual methods when designing components for an entity-component-system?
      I'll be more specific about my design issue:
      I currently have different classes for different kinds of colliders (let's say, CircleCollider and LineCollider).
      My system that checks for collisions and updates the positions and/or velocities of my entities should be something like:
      for entity_i in alive_entities { collider_i = get_collider_of_entity(entity_i) // components of same kind are stored contiguously in separate arrays transform_i = get_transform_of_entity(entity_i) for entity_j in alive_entities { collider_j = get_collider_of_entity(entity_j) transform_j = get_transform_of_entity(entity_j) if check_collision(collider_i, collider_j) { update(transform_i) update(transform_j) } } } my problem is that I don't have a generic `get_collider_of_entity` function, but rather a function `get_circle_collider_of_entity` and a separate one `get_line_collider_of_entity`, and so on. (This happens because under the hood I am keeping a mapping (entity_id -> [transform_id, sprite_id, circle_collider_id, line_collider_id, ...]) that tells me whether an entity is using certain kinds of components and which are the indices of those components in the arrays containing the actual components instances. As you can see, each component class is corresponding to a unique index, namely the index position of the array of the mapping described above. For example, transforms are 0, sprites are 1, circle colliders are 2, line colliders are 3, and so on.)
      I am in need to write a system as the one in the snippet above. I can write several overloaded `check_collision` functions that implement the logic for collision detection between different kinds of geometric primitives, but my problem is that I am not sure how to obtain a generic `get_collider_of_entity` function. I would need something that would get me the collider of an entity, regardless of whether the entity has a circle collider, a line collider, a square collider, etc.
      One solution could be to write a function that checks whether in my internal entity_id -> [components_ids] mapping a certain entity has a collider at any of the indices that correspond to colliders. For example, say that the indices related to the collider classes are indices 10 to 20, then my function would do
      get_collider_of_entity (entity_id) { for comp_type_id in 10..20{ if mapping[entity_id][comp_type_id] not null { return components_arrays[comp_type_id][entity_id] } } return null } This could turn out to be pretty slow, since I have to do a small search for every collider of every entity. Also, it may not be straightforward to handle returned types here. (I'm working with C++, and the first solution - that is not involving inheritance in any way - would be returning a std::variant<CircleCollider, LineCollider, ... all kinds of components>, since I would need to return something that could be of different types).
      Another solution could be having some inheritance among components, e.g. all specific component classes inherit from a base Collider, and overrride some virtual `collide_with(const Collider& other)` method. Then I would redesign my mapping to probably reserve just one index for colliders, and then I would actual colliders in a polymorphic array of pointers to colliders, instead of having a separate array for CircleColliders, another for LineColliders, and so on. But this would destroy any attempt to be cache-friendly in my design, wouldn't it? That's why I am looking for alternatives.
      A third alternative would be to just have a single, only, Collider class. That would internally store the "actual type" ( aka what kind of collider it is ) with dynamic information (like an enum ColliderType). Then I would have all colliders have all members needed by any kind of colliders, and specific collision detection functions which I can dispatch dynamically that only use some of that data. (Practical example: a "Collider" would have a radius, and the coordinate for 2 points, and in case its type was "circle" it would only make use of the radius and of one of the 2 points - used as the center -, while if it was a "segment" it would only make use of the 2 points). My gut feeling is that this would bloat all colliders, and, even if the bloat could be reduced - using unions in some smart way for storing members? I wouldn't know how -, then still the design would be pretty brittle.
      I'm clueless and open for ideas and advice! How do you handle in general situations in which you have components that can be naturally modeled as subclasses of a more generic component class? Inheritance? Smart hacks with variants, templates, macros, custom indexing? Dynamic "internal" type?
    • By hyyou
      In my most complex gameplay source file (single .cpp) with a lot of necessary #include,  
      ... whenever I edit it (e.g. add a single space character), it needs to recompile 40 seconds.
      Linking takes only 3-5 seconds.
      Is it what to be expected?   Do you also face this issue?  Should I just buy a new computer or more RAM? I am using Visual Studio 2017.  I am not using Unity Build (single compilation unit technique).
      Just thinking that the cause is my code, I can't eat and sleep well.  It also induces nightmare at my bedtime. Please help.
    • By C3D_
      I have two curves. One handdrawn and one is a smoothed version of the handdrawn. The data of each curve is stored in 2 seperate vector arrays. Time Delta is also stored in the handdrawn curve vector, so i can replay the drawing process and so that it looks natural.   Now i need to transfer the Time Delta from Curve 1 (Raw input) to Curve 2 (the already smoothed curve).   Sometimes the size of the first vector is larger and sometimes smaller than the second vector.
      (Depends on the input draw speed)   So my question is: How do i fill the whole vector PenSmoot.time with the correct interpolated values?   Case 1: Input vector is larger
      PenInput.time[0] = 0 PenSmoot.time[0] = 0 PenInput.time[1] = 5 PenSmoot.time[1] = ? PenInput.time[2] = 12 PenSmoot.time[2] = ? PenInput.time[3] = 2 PenSmoot.time[3] = ? PenInput.time[4] = 50 PenSmoot.time[4] = ? PenInput.time[5] = 100 PenInput.time[6] = 20 PenInput.time[7] = 3 PenInput.time[8] = 9 PenInput.time[9] = 33 Case 2: Input vector is smaller PenInput.time[0] = 0 PenSmoot.time[0] = 0 PenInput.time[1] = 5 PenSmoot.time[1] = ? PenInput.time[2] = 12 PenSmoot.time[2] = ? PenInput.time[3] = 2 PenSmoot.time[3] = ? PenInput.time[4] = 50 PenSmoot.time[4] = ? PenSmoot.time[5] = ? PenSmoot.time[6] = ? PenSmoot.time[7] = ? PenSmoot.time[8] = ? PenSmoot.time[9] = ?  
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!