CPP

Google Test

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.testing.cpp import GTest
from testplan.report.testing.styles import Style

from testplan import test_plan

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


@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
            )
        )


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 Test

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.testing.cpp import Cppunit
from testplan.report.testing.styles import Style

from testplan import test_plan

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


@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"
            )
        )
        # 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.testing.cpp import HobbesTest

from testplan import test_plan

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


@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,
                # 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())