CPP

GoogleTest

Required files:

test_plan.py

#!/usr/bin/env python
# This plan contains tests that demonstrate failures as well.
"""
This example shows how to use GTest test runner.

To be able to run the test, you need to compile the files
under `test` directory first to a binary target named `runTests`
"""

import os
import sys

from testplan import test_plan
from testplan.report.testing.styles import Style
from testplan.testing.cpp import GTest

BINARY_PATH = os.path.join(os.path.dirname(__file__), "test", "runTests")


def before_start(env, result):
    result.log("Executing before start hook.")


def after_start(env, result):
    result.log("Executing after start hook.")


def before_stop(env, result):
    result.log("Executing before stop hook.")


def after_stop(env, result):
    result.log("Executing after stop hook.")


@test_plan(
    name="GTest Example",
    stdout_style=Style(passing="testcase", failing="assertion-detail"),
)
def main(plan):

    if not os.path.exists(BINARY_PATH):
        raise RuntimeError("You need to compile test binary first.")

    else:
        plan.add(
            GTest(
                name="My GTest",
                binary=BINARY_PATH,
                # You can apply GTest specific filtering via `gtest_filter` arg
                # gtest_filter='SquareRootTest.*',
                # You can also shuffle test order via `gtest_shuffle` arg
                # gtest_shuffle=True
                before_start=before_start,
                after_start=after_start,
                before_stop=before_stop,
                after_stop=after_stop,
            )
        )


if __name__ == "__main__":
    sys.exit(not main())

app.cpp

// app.cpp
#include <math.h>

double squareRoot(const double a) {
    double b = sqrt(a);
    if(b != b) { // nan check
        return -1.0;
    }else{
        return sqrt(a);
    }
}

tests.cpp

#include "app.cpp"
#include <gtest/gtest.h>

TEST(SquareRootTest, PositiveNos) {
  ASSERT_EQ(6, squareRoot(36.0));
  ASSERT_EQ(4, squareRoot(36.0));
  ASSERT_EQ(2, squareRoot(10.0));
  ASSERT_EQ(18.0, squareRoot(324.0));
  ASSERT_EQ(25.4, squareRoot(645.16));
  ASSERT_EQ(0, squareRoot(0.0));
}


TEST(SquareRootTest, NegativeNos) {
  ASSERT_EQ(-1.0, squareRoot(-15.0));
  ASSERT_EQ(-1.0, squareRoot(-0.2));
}

TEST(SquareRootTestNonFatal, PositiveNos) {
  EXPECT_EQ(6, squareRoot(36.0));
  EXPECT_EQ(4, squareRoot(36.0));
  EXPECT_EQ(2, squareRoot(10.0));
  EXPECT_EQ(18.0, squareRoot(324.0));
  EXPECT_EQ(25.4, squareRoot(645.16));
  EXPECT_EQ(0, squareRoot(0.0));
}

TEST(SquareRootTestNonFatal, NegativeNos) {
  EXPECT_EQ(-1.0, squareRoot(-15.0));
  EXPECT_EQ(-1.0, squareRoot(-0.2));
}


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

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

# Locate GTest
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})

# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests tests.cpp)
target_link_libraries(runTests ${GTEST_LIBRARIES} pthread)

CppUnit

Required files:

test_plan.py

#!/usr/bin/env python
# This plan contains tests that demonstrate failures as well.
"""
This example shows how to use Cppunit test runner.

To be able to run the test, you need to compile the files
under `test` directory first to a binary target named `runTests`
"""

import os
import sys

from testplan import test_plan
from testplan.report.testing.styles import Style
from testplan.testing.cpp import Cppunit

BINARY_PATH = os.path.join(
    os.path.dirname(os.path.abspath(__file__)), "test", "runTests"
)


def before_start(env, result):
    result.log("Executing before start hook.")


def after_start(env, result):
    result.log("Executing after start hook.")


def before_stop(env, result):
    result.log("Executing before stop hook.")


def after_stop(env, result):
    result.log("Executing after stop hook.")


@test_plan(
    name="Cppunit Example",
    stdout_style=Style(passing="testcase", failing="assertion-detail"),
)
def main(plan):

    if not os.path.exists(BINARY_PATH):
        raise RuntimeError("You need to compile test binary first.")

    else:
        plan.add(
            Cppunit(
                name="My Cppunit",
                binary=BINARY_PATH,
                file_output_flag="-y",
                before_start=before_start,
                after_start=after_start,
                before_stop=before_stop,
                after_stop=after_stop,
            )
        )
        # You can apply Cppunit specific filtering via `filtering_flag` arg
        # and `cppunit_filter` arg, for example:
        # Cppunit(... filtering_flag='-t', cppunit_filter='LogicalOp::TestOr')
        # And you can also implement listing feature via `listing_flag` arg,
        # for example:
        # Cppunit(... listing_flag='-l')
        # But please be sure that your Cppunit binary is able to recognize
        # those '-y', '-t' and '-l' flags.


if __name__ == "__main__":
    sys.exit(not main())

tests.cpp

#ifndef __cppunit_example__
#define __cppunit_example__

#include <unistd.h>

#include <iostream>
#include <string>

#include <cppunit/TestCase.h>
#include <cppunit/TestFixture.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/XmlOutputter.h>

using namespace CPPUNIT_NS;

using std::cerr;
using std::cout;
using std::endl;
using std::string;
using std::ofstream;

static const int RET_OK = 0;
static const int RET_USAGE = -1;
static const int RET_BAD_TEST = -2;


class Comparison : public TestCase
{
  CPPUNIT_TEST_SUITE(Comparison);
  CPPUNIT_TEST(testNotEqual);
  CPPUNIT_TEST(testGreater);
  CPPUNIT_TEST(testLess);
  CPPUNIT_TEST(testMisc);
  CPPUNIT_TEST_SUITE_END();

  int m_value1;
  int m_value2;

public:
  void setUp();
  void tearDown();

protected:
  void testNotEqual();
  void testGreater();
  void testLess();
  void testMisc();
};

CPPUNIT_TEST_SUITE_REGISTRATION(Comparison);

void Comparison::setUp()
{
  m_value1 = 1;
  m_value2 = 2;
}

void Comparison::tearDown()
{
}

void Comparison::testNotEqual()
{
  CPPUNIT_ASSERT(m_value1 != m_value2);
}

void Comparison::testGreater()
{
  CPPUNIT_ASSERT(m_value1 > 0);
}

void Comparison::testLess()
{
  CPPUNIT_ASSERT(m_value2 < 5);
}

void Comparison::testMisc()
{
  CPPUNIT_ASSERT_EQUAL(m_value1 + 1, m_value2);
  CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, 9.99, 0.5);
}


class LogicalOp : public TestCase
{
  CPPUNIT_TEST_SUITE(LogicalOp);
  CPPUNIT_TEST(testOr);
  CPPUNIT_TEST(testAnd);
  CPPUNIT_TEST(testNot);
  CPPUNIT_TEST(testXor);
  CPPUNIT_TEST_SUITE_END();

  int m_valueT;
  int m_valueF;

public:
  void setUp();
  void tearDown();

protected:
  void testOr();
  void testAnd();
  void testNot();
  void testXor();
};

CPPUNIT_TEST_SUITE_REGISTRATION(LogicalOp);

void LogicalOp::setUp()
{
  m_valueT = 1;
  m_valueF = 0;
}

void LogicalOp::tearDown()
{
}

void LogicalOp::testOr()
{
  CPPUNIT_ASSERT(m_valueT | m_valueF);
}

void LogicalOp::testAnd()
{
  CPPUNIT_ASSERT(m_valueT & !m_valueF);
}

void LogicalOp::testNot()
{
  CPPUNIT_ASSERT(!m_valueF);
}

void LogicalOp::testXor()
{
  CPPUNIT_ASSERT(m_valueT ^ m_valueF);
}


void usage(const char *path)
{
  string image(path);
  image = image.substr(image.find_last_of("/\\") + 1);

  cout << endl;
  cout << "Usage: " << image << " [ -l | -h | -t test]" << endl << endl;

  cout << "A test example built against cppunit version: ";
  cout << CPPUNIT_VERSION << endl << endl;

  cout << "Options:" << endl;
  cout << "    -t  Runs the given test only. Default: All Tests" << endl;
  cout << "    -l  List all available tests." << endl;
  cout << "    -h  Print this usage message." << endl << endl;

  cout << "Returns:" << endl;
  cout << "    0 on success" << endl;
  cout << "    positive for number of errors and failures" << endl;
  cout << "    otherwise no test ever runs" << endl << endl;
}

// Recursive dumps the given Test heirarchy to cout
void dump(Test *test, int depth)
{
  if (test == 0) {
    return;
  }

  if (test->getName() == "All Tests") {
    for (int i = 0; i < test->getChildTestCount(); i++) {
      dump(test->getChildTestAt(i), 0);
    }
  }
  else {
    for (int i = 0; i < depth; ++i)
      cout << "  ";

    if (depth == 0) {
      cout << test->getName() << "." << endl;
    }
    else {
      string testName = test->getName();
      cout << testName.substr(testName.find_last_of(":") + 1) << endl;
    }

    for (int i = 0; i < test->getChildTestCount(); i++) {
      dump(test->getChildTestAt(i), depth + 1);
    }
  }
}

// Recursively seeks test matching the given filter, otherwise returns 0.
Test *find(Test *test, const string &name)
{
  if (test == 0) {
    return 0;
  }

  string testName = test->getName();
  if (testName == name
      || testName.substr(testName.find_last_of(":") + 1) == name) {
    return test;
  }

  for (int i = 0; i < test->getChildTestCount(); i++) {
    Test *found = find(test->getChildTestAt(i), name);
    if (found) {
      return found;
    }
  }

  return 0;
}


int main(int argc, char **argv)
{
  TestResult result;
  // register listener for collecting the test-results
  TestResultCollector collector;
  result.addListener(&collector);

  Test *test = 0;
  char flag = 0;
  string filter = "";
  string fileOut = "";

  while ((flag = getopt(argc, argv, "t:y:lh")) != -1) {

    switch(flag) {

    case 'l':
      {
        dump(TestFactoryRegistry::getRegistry().makeTest(), 0);
        return RET_OK;
      }

    case 't':
      {
        filter = optarg;
      }
      break;

    case 'y':
      {
        fileOut = optarg;
      }
      break;

    case 'h':
    default:
      usage(argv[0]);
      return RET_USAGE;
    }
  }

  if (filter.length())
    test = find(TestFactoryRegistry::getRegistry().makeTest(), filter);
  else
    test = TestFactoryRegistry::getRegistry().makeTest();

  if (test == 0) {
    cerr << "No test case found" << endl;
    return RET_BAD_TEST;
  }

  TestRunner runner;
  runner.addTest(test);
  runner.run(result);

  if (fileOut.length()) {
    ofstream xmlFileOut(fileOut);
    Outputter *outputter = new XmlOutputter(&collector, xmlFileOut);
    outputter->write();
  }
  else {
    Outputter *outputter = new XmlOutputter(&collector, cout);
    outputter->write();
  }

  return collector.testErrors() + collector.testFailures();

}

#endif // __cppunit_example__

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

LIST(APPEND CMAKE_MODULE_PATH ".")

# Locate Cppunit
find_package(Cppunit REQUIRED)
include_directories(${CPPUNIT_INCLUDE_DIRS})

# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests tests.cpp)
target_link_libraries(runTests ${CPPUNIT_LIBRARIES} pthread)

FindCppunit.cmake

#
# Find the CppUnit includes and library
#
# The cache variable CPPUNIT_ROOT (root directory of the Cppunit installation)
# should be set by passing argument or set as an environment variable.
#
# This module defines
# CPPUNIT_INCLUDE_DIRS, the directories containing heanders to be included.
# CPPUNIT_LIBRARIES, the libraries to link against to use CppUnit.
# CPPUNIT_DEBUG_LIBRARIES, the debug libraries to link against to use CppUnit.
# CPPUNIT_FOUND, If false, do not try to use CppUnit.

# also defined, but not for general use are
# CPPUNIT_INCLUDE_DIR, where to find header files.
# CPPUNIT_LIBRARY, where to find the CppUnit library.
# CPPUNIT_DEBUG_LIBRARY, where to find the CppUnit library in debug mode.

FIND_PATH(CPPUNIT_INCLUDE_DIR cppunit/TestCase.h
  $ENV{CPPUNIT_ROOT}/include
  ${CPPUNIT_ROOT}/include
  /usr/local/include
  /usr/include
)
mark_as_advanced(CPPUNIT_INCLUDE_DIR)

IF(WIN32)
  FIND_LIBRARY(CPPUNIT_LIBRARY cppunit
    ${CPPUNIT_INCLUDE_DIR}/../lib
    /usr/local/lib
    /usr/lib
  )
  FIND_LIBRARY(CPPUNIT_DEBUG_LIBRARY cppunitd
    ${CPPUNIT_INCLUDE_DIR}/../lib
    /usr/local/lib
    /usr/lib
)
ELSE(WIN32)
  # On unix system, debug and release have the same name
  FIND_LIBRARY(CPPUNIT_LIBRARY cppunit
    ${CPPUNIT_INCLUDE_DIR}/../lib
    /usr/local/lib
    /usr/lib
  )
  FIND_LIBRARY(CPPUNIT_DEBUG_LIBRARY cppunit
    ${CPPUNIT_INCLUDE_DIR}/../lib
    /usr/local/lib
    /usr/lib
  )
ENDIF(WIN32)

IF(CPPUNIT_INCLUDE_DIR)
  set(CPPUNIT_INCLUDE_DIRS ${CPPUNIT_INCLUDE_DIR})
  IF(CPPUNIT_LIBRARY)
    SET(CPPUNIT_FOUND "YES")
    SET(CPPUNIT_LIBRARIES ${CPPUNIT_LIBRARY} ${CMAKE_DL_LIBS})
    SET(CPPUNIT_DEBUG_LIBRARIES ${CPPUNIT_DEBUG_LIBRARY} ${CMAKE_DL_LIBS})
  ENDIF(CPPUNIT_LIBRARY)
ENDIF(CPPUNIT_INCLUDE_DIR)

Hobbes Test

Hobbes is a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis. Note: after downloading this example, replace hobbes-test with the actual test binary.

Required files:

test_plan.py

#!/usr/bin/env python
"""
This example shows how to use HobbesTest test runner.
The example uses a mocked test binary, and you can replace it with a link to your actual test binary.
"""

import os
import sys

from testplan import test_plan
from testplan.testing.cpp import HobbesTest

BINARY_PATH = os.path.join(os.path.dirname(__file__), "test", "hobbes-test")


def before_start(env, result):
    result.log("Executing before start hook.")


def after_start(env, result):
    result.log("Executing after start hook.")


def before_stop(env, result):
    result.log("Executing before stop hook.")


def after_stop(env, result):
    result.log("Executing after stop hook.")


@test_plan(name="HobbesTest Example")
def main(plan):

    if not os.path.exists(BINARY_PATH):
        raise RuntimeError("You need to compile test binary first.")

    else:
        plan.add(
            HobbesTest(
                name="My HobbesTest",
                binary=BINARY_PATH,
                before_start=before_start,
                after_start=after_start,
                before_stop=before_stop,
                after_stop=after_stop,
                # You can run one or more specified test(s)
                # tests=['Arrays', 'Compiler', 'Hog'],
                # You can pass other arguments to the test binary
                # other_args=['--tests', 'Arrays', 'Compiler']
            )
        )


if __name__ == "__main__":
    sys.exit(not main())