Data-driven unit tests with google test

前端 未结 1 1699
盖世英雄少女心
盖世英雄少女心 2021-01-02 06:48

I am currently writing unit tests for an embedded application using googles unit test framework. Now my boss got upset that the data I test with (i.e. the values with which

相关标签:
1条回答
  • 2021-01-02 07:17

    GTest has support for it - but maybe they do not know...

    Use testing::ValuesIn - like in this simplified example:

    class SomeTests : public TestWithParam<int>
    {
    public:
    
    };
    
    TEST_P(SomeTests, shouldBePositive)
    {
        ASSERT_GT(GetParam(), 0);
    }
    

    And - the way how to get values from input stream:

    std::ifstream inputValuesFromFile("input.txt");
    INSTANTIATE_TEST_CASE_P(FromFileStream,
                            SomeTests,
                            ValuesIn(std::istream_iterator<int>(inputValuesFromFile), 
                                     std::istream_iterator<int>()));
    

    To use more complicated types than "int" you need to write an operator >> for it - like:

    struct A
    {
        int a;
        std::vector<int> b;
    }
    std::istream& operator >> (std::istream& is, A& out)
    {
         std::size_t bSize;
         if ((is >> A.a) && (is >> bSize))
         {
             out.b.reserve(bSize);
             while (bSize-- > 0)
             {
                 int b;
                 if (!(is >> b))
                    break;
                 out.b.push_back(b);   
             }
         }
         return is;
    }
    

    Of course - in more complicated cases - consider to use XMl-like (json?) formats and some more specialized iterators than std::istream_iterator<T>.


    For XML - like formats - you might consider such scheme (this is very hypothetical code - I do not have any such library in my mind):

    SomeLib::File xmlData("input.xml");
    
    class S1BasedTests : public TestWithParam<S1>
    {};
    
    TEST_P(S1BasedTests , shouldXxxx)
    {
        const S1& s1 = GetParam();
        ...
    }
    auto s1Entities = file.filterBy<S1>("S1");
    INSTANTIATE_TEST_CASE_P(S1,
                            S1BasedTests,
                            ValuesIn(s1Entities.begin(), s1Entities .end()));
    

    // etc for any types S1 you want


    If there is no such C++-type-friendly library on the market (I searched for 2 minutes and did not find) - then maybe something like this:

    SomeLib::File xmlFile("input.xml");
    
    struct S1BasedTests : public TestWithParam<SomeLib::Node*>
    {
       struct S1 // xml=<S1 a="1" b="2"/>
       {
           int a;
           int b;
       };
       S1 readNode()
       {
            S1 s1{};
            s1.a = GetParam()->getNode("a").getValue<int>();
            s1.b = GetParam()->getNode("b").getValue<float>();
            return s1;
       }
    };
    
    TEST_P(S1BasedTests , shouldXxxx)
    {
        const S1& s1 = readNode();
        ...
    }
    INSTANTIATE_TEST_CASE_P(S1,
                            S1BasedTests ,
                            ValuesIn(xmlFile.getNode("S1").getChildren()));
                            // xml=<S1s> <S1.../> <S1.../> </S1>
    

    // etc for any node types like S1

    0 讨论(0)
提交回复
热议问题