//使用gtest进行数据驱动的单元测试 #include <gtest/gtest.h> #include <iostream> #include <vector> #include <string> #include <fstream> #include "BuildAttrDesc.h" using namespace std; using namespace testing; //定义一个结构体,用于保存输入数据和期望结果的对比数据 typedef struct { string myString; string productId; string standardAttr; string customAttr; string resultsExpect; string attrValueExpect; }datatype; //把vector返回给TEST_P,然后由TEST_P来处理相关的数据 typedef ::std::vector<datatype> data; static data vec; //声明一个测试类,用来进行参数传递的类 /* To write value-parameterized tests, first you should define a fixture class. It must be derived from both ::testing::Test and ::testing::WithParamInterface<T> (the latter is a pure interface), where T is the type of your parameter values. For convenience, you can just derive the fixture class from ::testing::TestWithParam<T>, which itself is derived from both ::testing::Test and ::testing::WithParamInterface<T>. T can be any copyable type. If it's a raw pointer, you are responsible for managing the lifespan of the pointed values. */ class testBuildAttrDesc : public::testing::TestWithParam<datatype>{}; /* The following class reads the envonrimental data from file "./dump_data/commodity_attribute_name_en","./dump_data/commodity_value_name_en", every row consisted of the input and expected output from file "./dump_data/product_attribute/standard_custom_expect_attr.txt" and then push them into the vector */ class Singleton { public: CBuildAttrDesc* m_pBuildAttrDesc; static Singleton* getInstance() { if(_instance==NULL) _instance=new Singleton(); return _instance; } ~Singleton() { delete m_pBuildAttrDesc; m_pBuildAttrDesc = NULL; } protected: Singleton() { datatype d; const string recordSeparator = " 01 03"; const string fieldSeparator = " 01 02"; string myString = ""; string productId = ""; string standardAttr = ""; string customAttr = ""; string resultsExpect = ""; string attrValueExpect = ""; vector<string> vStrArray; m_pBuildAttrDesc = new CBuildAttrDesc; m_pBuildAttrDesc->loadAttrNameValueMap("./dump_data/commodity_attribute_name_en","./dump_data/commodity_value_name_en", recordSeparator, fieldSeparator); if (!m_pBuildAttrDesc->initOk()) { cout<<"CBuildAttrDesc init failed!"<<endl; exit(1); }else cout<<endl<<"sucess: Open files commodity_attribute_name_en.dump and commodity_value_name_en.dump"<<endl<<endl; ifstream inData("./dump_data/product_attribute/standard_custom_expect_attr.txt");//open the input files while(getline(inData, myString)) { m_pBuildAttrDesc->splitStr(myString, "", vStrArray); if(5 != vStrArray.size())//total have five segments { cout<<"Format Error(the total record): "<<myString<<endl; continue; } d.productId = vStrArray[0]; d.standardAttr = vStrArray[1]; d.customAttr = vStrArray[2]; d.resultsExpect = vStrArray[3]; d.attrValueExpect = vStrArray[4]; if(m_pBuildAttrDesc->isDigits(d.productId)==false) { cout<<"Format Error(the product id): "<<d.productId<<endl; continue; } cout<<endl<<"product id: "<<d.productId<<endl; cout<<endl<<"standardAttr: "<<d.standardAttr<<endl; cout<<endl<<"customAttr: "<<d.customAttr<<endl; cout<<endl<<"resultsExpect: "<<d.resultsExpect<<endl; cout<<endl<<"attrValueExpect:"<<d.attrValueExpect<<endl; vec.push_back(d); } } private: static Singleton *_instance; }; Singleton* Singleton::_instance = NULL ; Singleton *single=Singleton::getInstance(); /* Then, use the TEST_P macro to define as many test patterns using this fixture as you want. The _P suffix is for "parameterized" or "pattern", whichever you prefer to think. */ TEST_P(testBuildAttrDesc,HandleTrueReturn) { datatype n = GetParam(); string results = ""; string attrValue = ""; // expected test single->m_pBuildAttrDesc->getAttrDesc(n.standardAttr,n.customAttr,results,attrValue); cout<<n.standardAttr<<endl<<n.customAttr<<endl<<results<<endl<<attrValue<<endl; EXPECT_STREQ(n.resultsExpect.c_str(),results.c_str()); EXPECT_STREQ(n.attrValueExpect.c_str(),attrValue.c_str()); } /* Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test case with any set of parameters you want. Google Test defines a number of functions for generating test parameters. They return what we call (surprise!) parameter generators. Here is a summary of them, which are all in the testing namespace: */ INSTANTIATE_TEST_CASE_P(TrueReturn,testBuildAttrDesc,::testing::ValuesIn(vec)); int main(int argc,char *argv[]) { testing::InitGoogleTest(&argc,argv); RUN_ALL_TESTS(); delete single; return 0; }
gtest官方关于数据驱动单元测试的文档
http://code.google.com/p/googletest/wiki/AdvancedGuide