Friday, April 14, 2023

C++ unit test using the Google Test framework

Google provides a comprehensive learning guide for its C++ testing framework, Google Test, which is available at https://google.github.io/googletest/. The guide covers a range of topics including writing tests, assertions, test fixtures, parameterized tests, and advanced topics such as death tests, type-parameterized tests, and custom test listeners. The guide also includes code examples and best practices to help developers write effective and maintainable unit tests.


  1. Google Test is a C++ testing framework developed by Google that supports a wide range of testing types, including unit testing, integration testing, and system testing.
  2. Google Test provides a rich set of macros and assertions that make it easy to write and maintain unit tests.
  3. Google Test supports test fixtures, which allow developers to write reusable setups and teardown code for their tests.
  4. Google Test also supports parameterized tests, which allow developers to run the same test code with different input values.
  5. Google Test provides a test runner that can automatically discover and run tests, and generate detailed test reports.
  6. Google Test integrates well with continuous integration (CI) systems, such as Jenkins and Travis CI, to enable automated testing and deployment pipelines.

Overall, Google Test is a powerful and flexible testing framework that can help developers write high-quality, reliable software. The official learning guide is a great resource to get started with Google Test, and there are also many online tutorials and examples available to help developers apply the framework in their own projects.

This code defines a simple string class MyString with a few member functions and a corresponding unit test mystring_test.cpp that tests the constructor, constructor with a parameter, and SetString function using the Google Test framework. To build and run the unit test, you'll need to download and install the Google Test library and link it with your code during the build process.


File: mystring.h

#include <string>

class MyString 

{

public:

  MyString();

  MyString(const char* str);

  ~MyString();


  int Length() const;

  const char* GetString() const;

  void SetString(const char* str);


private:

  char* m_buffer;

};


File: mystring.cpp

#include "mystring.h"

#include <cstring>


MyString::MyString() 

{

  m_buffer = new char[1];

  m_buffer[0] = '\0';

}

MyString::MyString(const char* str) 

{

  int len = strlen(str);

  m_buffer = new char[len + 1];

  strcpy(m_buffer, str);

}

MyString::~MyString() 

{

  delete[] m_buffer;

}

int MyString::Length() const 

{

  return strlen(m_buffer);

}

const char* MyString::GetString() const 

{

  return m_buffer;

}

void MyString::SetString(const char* str) 

{

  int len = strlen(str);

  delete[] m_buffer;

  m_buffer = new char[len + 1];

  strcpy(m_buffer, str);

}


File: mystring_test.cpp

#include "mystring.h"

#include <gtest/gtest.h>


TEST(MyStringTest, Constructor) 

{

  MyString s;

  EXPECT_EQ(0, s.Length());

  EXPECT_STREQ("", s.GetString());

}


TEST(MyStringTest, ConstructorWithParam) 

{

  MyString s("hello");

  EXPECT_EQ(5, s.Length());

  EXPECT_STREQ("hello", s.GetString());

}


TEST(MyStringTest, SetString) 

{

  MyString s("hello");

  s.SetString("world");

  EXPECT_EQ(5, s.Length());

  EXPECT_STREQ("world", s.GetString());

}


Google Test to test an inner class inside a C++ DLL:

C++ code with a corresponding unit test for a DLL inner class using the Google Test framework:

Assuming we have a DLL called mydll.dll with the following interface:

File: mydll.h #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif class MyClass

{ public: MYDLL_API MyClass(); MYDLL_API int GetValue() const; private: int m_value; }; MYDLL_API int Add(int a, int b);

File: mydll.cpp
#include "mydll.h"

MyClass::MyClass() : m_value(0) {}

int MyClass::GetValue() const 
{
  return m_value;
}

int Add(int a, int b) 
{
  return a + b;
}

Now, let's create a separate test project to test the MyClass inner class and Add function in mydll.dll. Here's an example code for mydll_test.cpp:

File: mydll_test.cpp

#include <gtest/gtest.h>
#include <Windows.h>
#include "mydll.h"

// Define a function pointer type to dynamically load the DLL function
typedef int (*AddFunc)(int, int);

TEST(MyClassTest, Constructor) 
{
  MyClass myClass;
  EXPECT_EQ(0, myClass.GetValue());
}

TEST(MyDllTest, Add) 
{
  // Load the DLL
  HINSTANCE hDll = LoadLibrary("mydll.dll");
  ASSERT_TRUE(hDll != nullptr);

  // Get the function pointer for Add function
  AddFunc add = (AddFunc)GetProcAddress(hDll, "Add");
  ASSERT_TRUE(add != nullptr);

  // Call the Add function and verify the result
  EXPECT_EQ(3, add(1, 2));

  // Free the DLL
  FreeLibrary(hDll);
}

This test creates an instance of MyClass and verifies the default value of m_value using the Google Test framework. It also dynamically loads the mydll.dll using LoadLibrary function and gets the function pointer for Add function using GetProcAddress. It then calls the Add function with two input integers and verifies the result using the Google Test framework. To build and run the test, you'll need to link the Google Test library and the mydll.dll with your test project during the build process.


For C++, the most commonly used unit testing frameworks are:

  1. Google Test (also known as GTest) - a widely used testing framework that provides a lot of powerful features such as advanced assertions, test fixtures, parameterized tests, and test discovery. It is actively maintained by Google and has a large community of users and contributors.
  2. Catch2 - a modern, header-only testing framework that focuses on being easy to use and providing expressive test cases. It provides a lot of features such as assertions, test fixtures, and test discovery.
  3. Boost.Test - part of the Boost library collection, it is a powerful testing framework that provides a lot of advanced features such as test fixtures, mock objects, and unit test logs. It is widely used in the C++ community and is actively maintained.

For Java, the most commonly used unit testing frameworks are:

  1. JUnit - a widely used testing framework that provides a lot of powerful features such as assertions, test fixtures, and parameterized tests. It is integrated into many Java IDEs such as Eclipse and IntelliJ IDE and is supported by many build tools such as Maven and Gradle.
  2. TestNG - a testing framework that provides a lot of advanced features such as test grouping, data providers, and test configuration through XML files. It is widely used in the Java community and is supported by many build tools such as Maven and Gradle.
  3. Mockito - a mocking framework that allows developers to create mock objects for their tests. It provides a lot of features such as verifying method calls, stubbing method responses, and configuring mock behavior. It is widely used in the Java community and is often used in conjunction with JUnit or TestNG.

These are just a few examples of the many unit testing frameworks available for C++ and Java. The choice of framework often depends on the specific needs of the project and the preferences of the development team.


No comments:

Post a Comment

LeetCode C++ Cheat Sheet June

🎯 Core Patterns & Representative Questions 1. Arrays & Hashing Two Sum – hash map → O(n) Contains Duplicate , Product of A...