乐哈哈yoyo 发表于 2017-6-15 10:02:36

用 gtest 实现数据驱动的单元测试

后端技术在testhome算不上火热,贴代码选项里面竟然没有c这个项目,这里列举个gtest的例子
/使用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 = "\001\003";
      const string fieldSeparator = "\001\002";
      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;
            d.standardAttr = vStrArray;
            d.customAttr = vStrArray;
            d.resultsExpect = vStrArray;
            d.attrValueExpect = vStrArray;
            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;
}

草帽路飞UU 发表于 2017-6-15 10:26:52

学习

乐哈哈yoyo 发表于 2017-6-15 10:27:34

草帽路飞UU 发表于 2017-6-15 10:26
学习

:lol

岛屿soliloquy 发表于 2017-6-16 17:18:49

先浏览,留言咯。默默围观。
学习共同成长,版主棒棒的
页: [1]
查看完整版本: 用 gtest 实现数据驱动的单元测试