代码之家  ›  专栏  ›  技术社区  ›  Joe Jankowiak

Google使用全局向量测试ValuesIn

  •  1
  • Joe Jankowiak  · 技术社区  · 11 年前

    我正在尝试基于目录中的配置文件运行一堆谷歌测试。这样,我就可以添加一个新文件并运行测试,而无需将其添加到参数化测试中并重新编译。这是我的代码:

    typedef std::pair<QString, int> TestParam;
    
    QString generatedLogic;
    
    std::vector<TestParam> badExpressionTests;
    
    class LogicBuilderTest : public ::testing::TestWithParam<TestParam> {};
    
    GTEST_API_ int main(int argc, char **argv) {
        testing::InitGoogleTest(&argc, argv);
    
        ::generatedLogic = "/home/mitydsp/trunk/System/logicExecutionEngine/engine/include/GeneratedLogic.h";
    
        QString dir = "/home/mitydsp/trunk/System/logicExecutionEngine/unittest/expressions/bad/";
        QDirIterator it(dir, QStringList() << "*.txt", QDir::Files, QDirIterator::Subdirectories);
    
        while (it.hasNext()) {
            QString path = it.next();
            QStringList nameParts = it.fileName().split("_");
            int exitCode = nameParts[0].toInt();
            ::badExpressionTests.push_back(TestParam(path, exitCode));
        }
    
        std::cout << "Size of vector: " << badExpressionTests.size() << std::endl;
    
        return RUN_ALL_TESTS();
    }
    
    /**
     * Run parameterized test
     */
    TEST_P(LogicBuilderTest, TestExitWithCode)
    {    
        ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    
        // Simulate fake main()
        char  arg0[] = "logicTest";
        char* argv[] = { &arg0[0], NULL };
        int argc = (int)(sizeof(argv) / sizeof(argv[0])) - 1;
    
        EXPECT_EXIT({
            // Need to run Qt Application because logic builder uses async QTimer::singleShot()
            QCoreApplication app(argc, argv);
    
            // Create a logic builder instance
            LogicBuilder logicBuilder(
                (int) ParameterStoreInterface::DEFAULT_PARAM_STORE_VALUES_KEY,
                (int) ParameterStoreInterface::DEFAULT_PARAM_STORE_NAMES_KEY,
                (int) ParameterStoreInterface::DEFAULT_PARAM_STORE_LOCK_KEY,
                QString(GetParam().first),
                QStringList(""),
                QStringList(generatedLogic),
                QString(LogicBuilder::DEFAULT_INTERMEDIATE_DIR),
                QString(LogicBuilder::DEFAULT_OUTPUT_SRC),
                QString(LogicBuilder::DEFAULT_OUTPUT_LIB),
                true );
    
            app.exec();
        }, ::testing::ExitedWithCode(GetParam().second), "");
    } 
    
    INSTANTIATE_TEST_CASE_P(TestBadExpressions, LogicBuilderTest,
                            ::testing::ValuesIn(::badExpressionTests));
    

    当我运行这个时,它显示正在运行0个测试,尽管向量表示其大小为2。为什么这些参数化测试没有运行?

    Size of vector: 2
    [==========] Running 0 tests from 0 test cases.
    [==========] 0 tests from 0 test cases ran. (0 ms total)
    [  PASSED  ] 0 tests.
    

    最初我是通过手动定义配置文件来运行测试,但我不喜欢这样:

        INSTANTIATE_TEST_CASE_P(TestBadExpressions, LogicBuilderTest,
                            ::testing::Values(
                                TestParam("unittest/expressions/bad/17_no_lhs.txt", LogicBuilder::LB_VARIABLE_NO_LHS),
                                TestParam("unittest/expressions/bad/25_incomplete_rhs.txt", LogicBuilder::LB_PARSE_ERROR)
                            ));
    
    3 回复  |  直到 11 年前
        1
  •  2
  •   Joe Jankowiak    11 年前

    我花了最后一个小时试图弄清楚这一点,然后一发布我就想出了解决方案。我会把这个留在这里,因为它可能会在未来帮助某人:

    不要试图在main中创建文件列表,而是将ValuesIn传递给加载文件并返回向量的函数。

    std::vector<TestParam> GetFilesInDir() 
    {
        std::vector<TestParam> values;
        QString dir = "/home/mitydsp/trunk/System/logicExecutionEngine/unittest/expressions/bad/";
        QDirIterator it(dir, QStringList() << "*.txt", QDir::Files, QDirIterator::Subdirectories);
    
        while (it.hasNext()) {
            QString path = it.next();
            QStringList nameParts = it.fileName().split("_");
            int exitCode = nameParts[0].toInt();
            values.push_back(TestParam(path, exitCode));
        }
    
        return values;
    }
    
    INSTANTIATE_TEST_CASE_P(TestBadExpressions, LogicBuilderTest,
                            ::testing::ValuesIn(GetFilesInDir()));
    

    感谢Maksim Solovjov提醒我INSTANTATE_TEST_CASE_P宏在main之前执行。

        2
  •  1
  •   bicepjai    10 年前

    我们在这个问题上花了几个小时,认为这个片段会有所帮助。

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    #include "gtest/gtest.h"
    
    GTEST_API_ main( int argc, char* argv[] ) {
       testing::InitGoogleTest( &argc, argv );
       return RUN_ALL_TESTS();
    }
    
    struct test_parms_s {
       string         name;             // Simple name of this test
       string         description;      // Description of this test
       void*          function_parms;   // Pointer to test function specific data
    };
    
    std::vector<test_parms_s*> BuildTestData() {
       test_parms_s* pTestDataA = new test_parms_s(); 
       test_parms_s* pTestDataB = new test_parms_s(); 
       test_parms_s* pTestDataC = new test_parms_s();
    
       pTestDataA->name.assign("testA");
       pTestDataA->description.assign("testA_desc");
       pTestDataA->function_parms = NULL;
    
       pTestDataB->name.assign("testB");
       pTestDataB->description.assign("testB_desc");
       pTestDataB->function_parms = NULL;
    
       pTestDataC->name.assign("testC");
       pTestDataC->description.assign("testC_desc");
       pTestDataC->function_parms = NULL;
    
       std::vector<test_parms_s*> values;
       values.push_back(pTestDataA);
       values.push_back(pTestDataB);
       values.push_back(pTestDataC);
       cout << "BuildTestData" << endl;
    
       return values;
    }
    //------------------------------------------------------------------------
    class Testy {
      private:
         string       testname_;
      public:
         Testy( string testname );
         ~Testy();
         string   GetTestName();
         void     SetTestName( string testname );
    };
    Testy::Testy( string testname ) {
       testname_.assign(testname);
    }
    Testy::~Testy() {}
    string Testy::GetTestName() { return testname_; }
    void Testy::SetTestName( string testname ) { testname_ = testname; }
    //------------------------------------------------
    class TestFixture : public ::testing::TestWithParam<test_parms_s*> {
       protected:
         Testy* testy;      
         virtual void SetUp() {
            testy = new Testy( "Test");
         }
         virtual void TearDown() {
            delete( testy );
         }
    };
    //------------------------------------------------
    TEST_P( TestFixture, ParamTest ) {
       test_parms_s* pTestParms = GetParam();
       cout << pTestParms->name << endl;
    } 
    //------------------------------------------------
    INSTANTIATE_TEST_CASE_P( TestFixture_instance, TestFixture,                     
                             ::testing::ValuesIn(BuildTestData()));
    //========================================================================
    

    输出将是

    BuildTestData
    [==========] Running 3 tests from 1 test case.
    [----------] Global test environment set-up.
    [----------] 3 tests from TestFixture_instance/TestFixture
    [ RUN      ] TestFixture_instance/TestFixture.ParamTest/0
    testA
    [       OK ] TestFixture_instance/TestFixture.ParamTest/0 (0 ms)
    [ RUN      ] TestFixture_instance/TestFixture.ParamTest/1
    testB
    [       OK ] TestFixture_instance/TestFixture.ParamTest/1 (0 ms)
    [ RUN      ] TestFixture_instance/TestFixture.ParamTest/2
    testC
    [       OK ] TestFixture_instance/TestFixture.ParamTest/2 (0 ms)
    [----------] 3 tests from TestFixture_instance/TestFixture (0 ms total)
    
    [----------] Global test environment tear-down
    [==========] 3 tests from 1 test case ran. (0 ms total)
    [  PASSED  ] 3 tests.
    
        3
  •  0
  •   Maksim Solovjov    11 年前

    我不是手动实例化Google测试的专家,但你做的方式不可能奏效:你调用 INSTANTIATE_TEST_CASE_P 在静态上下文中,因此它在 main 被称为。

    您可以尝试在之前移动实例化 RUN_ALL_TESTS ; 但是,我不知道宏的作用,这可能是非法的。在这种情况下,我认为您不能使用 实例化测试用例 以您想要的动态方式。