Search code examples
c++unit-testingboostboost-test

getting all boost test suites / test cases


As the title says, I want to get all test suites or test cases (name) from a test application, ether in the console or as xml output. Test framework is the boost test library.

Is there an option to achieve this? I did not found anything useful in the documentation.


Solution

  • This can be done without much intrusion using a global fixture. Assuming you have a translation unit (cpp file) that contains main explicitly or auto generated, you can intercept test execution when a certain command line argument is provided. Then you can traverse the test tree using a customized visitor, which lists all available tests. Here is a small working example, which creates a test runner by compiling and linking files main_test.cpp, a.cpp and b.cpp:

    main_test.cpp

    #include <string>
    #include <iostream>
    
    // --- Boost Includes ---
    #define BOOST_TEST_MODULE MyTestSuite
    #define BOOST_TEST_DYN_LINK
    #include <boost/test/unit_test.hpp>
    
    using namespace boost::unit_test;
    
    struct Visitor : test_tree_visitor
    {
      size_t level = 0;
    
      void visit( test_case const& test )
      {
        std::string indentation( level, '.' );
    
        std::cout << indentation << test.p_name << std::endl;
      }
    
      bool test_suite_start( test_suite const& suite )
      {
        std::string indentation( level, '.' );
        level++;
    
        std::cout << indentation << "Suite: " << suite.p_name << std::endl;
        return true;
      }
    
      void test_suite_finish( test_suite const& suite )
      {
        level--;
      }
    };
    
    struct GlobalFixture
    {
      GlobalFixture( )
      {
        int argc = framework::master_test_suite( ).argc;
        for ( int i = 0; i < argc; i++ )
        {
          std::string argument( framework::master_test_suite( ).argv[i] );
    
          if ( argument == "list" )
          {
            Visitor visitor;
    
            traverse_test_tree( framework::master_test_suite( ), visitor );
    
            exit( EXIT_SUCCESS );
          }
        }
      }
    
    };
    
    BOOST_GLOBAL_FIXTURE( GlobalFixture )
    

    a.cpp

    #include <boost/test/unit_test.hpp>
    
    BOOST_AUTO_TEST_SUITE ( TestA )
    
    BOOST_AUTO_TEST_CASE ( TestFoo )
    {
      BOOST_CHECK(true);
    }
    
    BOOST_AUTO_TEST_CASE ( TestBar )
    {
      BOOST_CHECK(true);
    }
    
    BOOST_AUTO_TEST_SUITE_END() // TestA
    

    b.cpp

    #include <boost/test/unit_test.hpp>
    
    BOOST_AUTO_TEST_SUITE ( TestB )
    
    BOOST_AUTO_TEST_CASE ( TestFoo )
    {
      BOOST_CHECK(true);
    }
    
    BOOST_AUTO_TEST_CASE ( TestBar )
    {
      BOOST_CHECK(true);
    }
    
    BOOST_AUTO_TEST_SUITE_END() // TestA
    

    Invoking the runner without any arguments results in

    ./somelib_testrunner1 
    Running 4 test cases...
    
    *** No errors detected
    

    Passing the argument list used in the fixture defined above results in

    Suite: MyTestSuite
    .Suite: TestA
    ..TestFoo
    ..TestBar
    .Suite: TestB
    ..TestFoo
    ..TestBar