2012-10-04 31 views
1

我是C++自動單元測試的新手。我遵循boost :: unit_test的指令,並通過在boost :: unit_test中調用函數unit_test_main完成了一個測試方案。運行測試程序對我來說不成問題。但是,將測試函數傳遞給測試函數時遇到問題。也許,下面的代碼就可以說明我的問題要好得多:如何編寫一個腳本來執行boost :: unit_test的自動測試?

#ifndef MAIN_CPP_ 
#define MAIN_CPP_ 



#include <string> 
#include <vector> 
#include <iostream> 
#include <assert.h> 

#include <boost/program_options.hpp> 
#include <boost/test/test_tools.hpp> 
#include <boost/test/execution_monitor.hpp> 
#include <boost/test/unit_test.hpp> 




using namespace boost::program_options; 
using namespace std; 
using namespace boost; 
using namespace boost::unit_test; 




/** 
* the global test suite 
*/ 

boost::unit_test::test_suite* get_feelfree_test_suite(); 
boost::unit_test::test_suite* main_global_test_suite; 

/** 
* name of the test suite 
*/ 
std::string current_global_test_suite_name; 

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API 

bool run_global_test_suite() { 
    boost::unit_test::test_suite& masterTestSuite = framework::master_test_suite(); 

    if(masterTestSuite.size() != 0) { 
     test_unit_id formerTestSuite = masterTestSuite.get(current_global_test_suite_name); 
     masterTestSuite.remove(formerTestSuite); 

    } 
    masterTestSuite.add(main_global_test_suite); 
    current_global_test_suite_name = main_global_test_suite->p_name.get(); 

    return true; 
} 
#else 
    test_suite* run_global_test_suite(int, char* []) { 
    return main_global_test_suite; 
} 
#endif 

/** 
* Obtain test program options 
*/ 
int obtain_options(char **optionLine, int argc, char** argv); 





/** 
* This function is used to run the test program, and the procedure is really standard. 
*/ 
int main(int argc, char* argv[]) 
{ 
    try 
    { 
     /** 
     * Step 1. obtain options 
     */ 
     char* optionLine[1024]; 
     int len ; 
     len = obtain_options(optionLine, argc, argv); 
     /** 
     * Step 2. perform unit test based on user's options 
     */ 
     int test_status=0; 
     main_global_test_suite = get_feelfree_test_suite(); 
     test_status = unit_test_main(run_global_test_suite, len, optionLine); 
     return test_status; 
    } 
    catch(std::exception& e) 
    { 
     std::cout << e.what() << std::endl; 
     return 1; 
    } 
    catch (const std::string& s) 
    { 
     std::cout << s << std::endl; 
     return 1; 
    } 
    catch (...) 
    { 
     return 1; 
    } 


} 
/** @} */ 


int obtain_options(char **optionLine, int argc, char* argv[]) 
{ 
    // 1. All the options for testing the program 
     options_description desc("Allowed options"); 
     desc.add_options()("help", "produce help message") 
     ("detect_memory_leaks", value<bool>()->default_value(false), "test configuration option (option of boost framework)"); 
     // 2. Perform parsing 
     variables_map vm; 
     store(parse_command_line(argc, argv, desc), vm); 
     notify(vm); 
     // 3. Illustrate the input 
     std::vector<const char*> options; 
     std::string testSuiteToRun; 
     if(vm.count("test_suite")){ 
      testSuiteToRun = vm["test_suite"].as<string>(); 
     } 
     else { 
      testSuiteToRun = "main"; 
     } 

     options.push_back(argv[0]); 
     if(vm.count("detect_memory_leaks")) { 
      bool detect = vm["detect_memory_leaks"].as<bool>(); 
      if(detect) { 
       options.push_back("--detect_memory_leaks=1"); 
      } 
      else { 
      options.push_back("--detect_memory_leaks=0"); 
      } 
     } 
     else { 
      options.push_back("--detect_memory_leaks=0"); 
     } 

     // 4. Obtain all the parameters in the format of char** 

     assert(options.size() < 1024); 
     std::copy(options.begin(), options.end(), const_cast<const char**>(optionLine)); 

     return options.size(); 

} 

void Testsub(const std::string &name) 
{ 
    cout<<"File_name: "<<name<<endl; 
} 
void Testabc() 
{ 
    std::vector<std::string > name_array; 
    name_array.push_back("name 1"); 
    name_array.push_back("name 2"); 
    for(int i=0; i<name_array.size(); i++) 
     Testsub(name_array[i]); 
} 


boost::unit_test::test_suite* get_feelfree_test_suite() 
{ 
    test_suite* ts = BOOST_TEST_SUITE("unit_geometric"); 
    ts->add(BOOST_TEST_CASE(&Testabc)); 
    return ts; 
} 


#endif 

正如你可以看到,在這個測試框架,主要功能我想測試是Testsub,這依賴於輸入參數常量性病:: string & name。但是,我無法通過測試套件函數get_feelfree_test_suite傳遞任何參數。因此,在這個測試程序,我寫了另外一個測試功能testAbc的,在所有可能的文件測試列表中給出,並傳遞給Testsub。這絕對不是最好的解決方案。我想知道是否有其他解決方案。有幾種解決方案在我的腦海,但我不知道他們是否有好的解決辦法:

  • 解決方案1:儘量想出一個辦法將參數從主函數(int main(int argc, char* argv[])傳遞給 get_feelfree_test_suite。之後,編寫腳本幾次運行程序 。在Windows中,一個可能的腳本是.bat腳本。對於 這個解決方案,我不知道如何實現它。
  • 解決方案2:寫一個清單文件,其中所有可能的輸入 檔測試給定名稱,然後閱讀在 程序列表文件。這很容易實現。

我也聽說Python可以很容易地納入測試框架,但我不知道這一點。無論如何,我願意接受所有可能的解決方案,謝謝!

+0

對於像Testsub這樣的簡單函數,這個測試程序似乎有點複雜。爲什麼不使用BOOST_AUTO_TEST_CASE? – Sebastian

回答

0

你真的需要一個單獨的文件有不同的「名字」? 將它們放入測試套件可能會更簡單。每個名字一個BOOST_AUTO_TEST_CASE。或者可以在測試用例中迭代的一組名稱。

0

由於我並不真正瞭解所有代碼的用途,因此我通過從命令行解析元素(如-F file1 -F file2)發佈了執行此工作的最小示例(多次調用Testsub)。它使用BOOST_PARAM_TEST_CASEboost::unittest

#include <boost/test/parameterized_test.hpp> 
//... 
void Testsub(const std::string &name) 
{ 
    cout<<"File_name: "<<name<<endl; 
} 
test_suite* init_unit_test_suite(int argc, char* argv[]) 
{ 
    std::vector<std::string> files_to_run_local; 

    for(int i = 0; i < framework::master_test_suite().argc; i++) 
    { 
    if(std::string(framework::master_test_suite().argv[i]) == "-F") 
    { 
     if(i == framework::master_test_suite().argc - 1) 
     { 
     std::cerr << "Error in the command line" << std::endl; 
     throw boost::unit_test::framework::setup_error("Error in the command line"); 
     } 
     files_to_run_local.push_back(framework::master_test_suite().argv[++i]); 
    } 
    } 

    test_suite* ts = BOOST_TEST_SUITE("unit_geometric"); 
    ts->add(BOOST_PARAM_TEST_CASE(&Testsub, 
            files_to_run_local.begin(), 
            files_to_run_local.end())); 

    framework::master_test_suite().add(ts); 

    return 0; 
} 

現在,我認爲你是在決定使用的文件列表傳遞到單元測試框架的方法只有一個。包含所有文件的文件也是一個很好的解決方案,如果要傳遞的列表很大,可能是合適的,但是使用中間文件來做這件事是不利的。

但在回答這個問題實際上取決於什麼框架是駕駛你的測試(cmake的,外殼等)的Python/cmake的可以很容易對你產生任何命令行或中間文件。

在所有的情況下,清潔方法是調用BOOST_PARAM_TEST_CASE宏。

相關問題