【问题标题】:Is it possible to distribute unit test modules in diffrent source files if I use Boost.Test?如果我使用 Boost.Test,是否可以在不同的源文件中分发单元测试模块?
【发布时间】:2022-07-06 22:24:43
【问题描述】:

我有很多测试源文件,我在其中使用 Boost.Test 并且我正在尝试运行它们,但是得到了 multiple definition of boost::unit_test::runtime_config::argument_store() 错误,并且对于这个库的许多模块都是一样的。

例如有两个文件:test_size.cpp

#define BOOST_TEST_MODULE Test_Repeats
#include "../include/test_config.h"

BOOST_AUTO_TEST_CASE(test_repeats) {
  int n = 30;
  Repeats r = Repeats(n);
  BOOST_REQUIRE(r.rep == n);
}

还有test_repeats.cpp:

#define BOOST_TEST_MODULE Test_Size
#include "../include/test_config.h"

  BOOST_AUTO_TEST_CASE(test_size) {
  int n = 20;
  int m = 30;
  Size sz = Size(n, m);
  BOOST_REQUIRE(sz.n == n && sz.m == m);
}

还有test_config.h:

#include <boost/test/included/unit_test.hpp>

#include "../include/size.h"
#include "../include/repeats.h"

这是我的Makefile 运行测试:

FAST_HEADERS := $(wildcard Fast/**/*.h)

FAST_TEST_SOURCES := $(filter-out Fast/src/main.cpp, $(wildcard Fast/src/*.cpp Fast/tests/test_size.cpp Fast/tests/test_repeats.cpp))

FAST_TEST_OBJECTS := ${FAST_TEST_SOURCES:.cpp=.o}

fast_test: $(FAST_TEST_OBJECTS)
    g++ $(FAST_TEST_OBJECTS) -lboost_unit_test_framework -o fast_test 
    ./fast_test

%.o: Fast/**/%.cpp  $(FAST_HEADERS)
    g++ $@ -o $< 

我知道可以将所有测试放在一个源文件中,并且效果很好,但我很好奇是否可以将所有测试单元分布在不同的源文件中以使其更有条理。

我的Makefile 或源文件有什么问题?

【问题讨论】:

    标签: c++ boost makefile


    【解决方案1】:
    %.o: Fast/**/%.cpp  $(FAST_HEADERS)
        g++ $@ -o $< 
    

    由于**,这永远不会适用。您还颠倒了$@$&lt;。你可以使用

    Fast/tests/%.o: Fast/tests/%.cpp | $(FAST_HEADERS)
    Fast/src/%.o: Fast/src/%.cpp | $(FAST_HEADERS)
    
    %.o: %.cpp
        g++ -o $@ $<
    

    真正的问题

    也就是说,让我们找出链接器消息的问题所在。老实说,我花了 更多时间 在这里“不经意间”找到它。首先,我显然是按文档使用的,主要是:

    还有一些邮件列表/SO 帖子:

    老实说,我学到的唯一有形的东西就是

    但是,其他记录在案的标志 BOOST_TEST_DYN_LINKBOOST_TEST_NO_MAIN 的效果为零。经过一些试验和错误以及预处理器#error 调试后,我发现这些符号在包含后都只是undef-ined

    #include <boost/test/included/unit_test.hpp>
    

    我没有立即认出/included/ 部分。一时兴起,我想改成:

    #include <boost/test/unit_test.hpp>
    

    这行得通,但现在main未定义。所以,我想出了一个以下重构的 makefile 和一个额外的 Fast/tests/module.cpp 来定义 main.毫无疑问,这一切还不是完全最优的。例如。我认为,由于您要链接动态库,因此应该定义 BOOST_TEST_DYN_LINK,但如果没有那个¯\(ツ)/¯,它似乎可以正常工作。

    因此,此处显示的部分 Makefile 旨在启发您在需要时如何完成特定的高级任务。

    test: # make default target
    
    FAST_HEADERS := $(wildcard Fast/**/*.h)
    FAST_TEST_SOURCES := $(filter-out Fast/src/main.cpp, $(wildcard Fast/src/*.cpp Fast/tests/*.cpp))
    FAST_TEST_OBJECTS := ${FAST_TEST_SOURCES:.cpp=.o}
    
    CPPFLAGS+= $(INCLUDES)
    CPPFLAGS+= -D BOOST_TEST_DYN_LINK
    CXXFLAGS+= -std=c++11 $(CPPFLAGS)
    LDFLAGS+= -lboost_unit_test_framework
    
    Fast/tests/test_%.o: CPPFLAGS+=-DBOOST_TEST_NO_MAIN
    Fast/tests/%.o: Fast/tests/%.cpp | $(FAST_HEADERS)
    Fast/src/%.o: Fast/src/%.cpp | $(FAST_HEADERS)
    
    %.o: %.cpp
        g++ $(CXXFLAGS) -o $@ -c $<
    
    fast_test: $(FAST_TEST_OBJECTS)
        g++ $(CXXFLAGS) $^ $(LDFLAGS) -o $@
    
    test: fast_test
        ./$<
    
    .PHONY: test
    

    使用make -Bsn 进行测试显示了标志如何组合:

    g++ -std=c++11  -D BOOST_TEST_DYN_LINK -o Fast/src/size.o -c Fast/src/size.cpp
    g++ -std=c++11  -D BOOST_TEST_DYN_LINK -o Fast/src/repeats.o -c Fast/src/repeats.cpp
    g++ -std=c++11  -D BOOST_TEST_DYN_LINK -DBOOST_TEST_NO_MAIN -o Fast/tests/test_size.o -c Fast/tests/test_size.cpp
    g++ -std=c++11  -D BOOST_TEST_DYN_LINK -DBOOST_TEST_NO_MAIN -o Fast/tests/test_repeats.o -c Fast/tests/test_repeats.cpp
    g++ -std=c++11  -D BOOST_TEST_DYN_LINK -o Fast/tests/module.o -c Fast/tests/module.cpp
    g++ -std=c++11  -D BOOST_TEST_DYN_LINK Fast/src/size.o Fast/src/repeats.o Fast/tests/test_size.o Fast/tests/test_repeats.o Fast/tests/module.o
     -lboost_unit_test_framework -o fast_test
    ./fast_test
    

    例如的输出./fast_test -l all:

    Running 2 test cases...
    Entering test module "Fast_Tests"
    Fast/tests/test_size.cpp(3): Entering test case "test_size"
    Fast/tests/test_size.cpp(8): info: check sz.n == n && sz.m == m has passed
    Fast/tests/test_size.cpp(3): Leaving test case "test_size"; testing time: 136us
    Fast/tests/test_repeats.cpp(3): Entering test case "test_repeats"
    Fast/tests/test_repeats.cpp(7): info: check r.rep == n has passed
    Fast/tests/test_repeats.cpp(3): Leaving test case "test_repeats"; testing time: 125us
    Leaving test module "Fast_Tests"; testing time: 311us
    
    *** No errors detected
    

    松散的结局

    我只保留了 Size/Repeats 标头的“测试驱动”实现。如果您为真实代码更改依赖对象,则需要链接依赖对象。

    对于我没有解释的 GNU Make 功能,请参阅 https://www.gnu.org/software/make/manual/

    代码转储:

    • 文件Makefile

       test: # make default target
      
       FAST_HEADERS := $(wildcard Fast/**/*.h)
       FAST_TEST_SOURCES := $(filter-out Fast/src/main.cpp, $(wildcard Fast/src/*.cpp Fast/tests/*.cpp))
       FAST_TEST_OBJECTS := ${FAST_TEST_SOURCES:.cpp=.o}
      
       CPPFLAGS+= $(INCLUDES)
       CPPFLAGS+= -D BOOST_TEST_DYN_LINK
       CXXFLAGS+= -std=c++11 $(CPPFLAGS)
       LDFLAGS+= -lboost_unit_test_framework
      
       Fast/tests/test_%.o: CPPFLAGS+=-DBOOST_TEST_NO_MAIN
       Fast/tests/%.o: Fast/tests/%.cpp | $(FAST_HEADERS)
       Fast/src/%.o: Fast/src/%.cpp | $(FAST_HEADERS)
      
       %.o: %.cpp
           g++ $(CXXFLAGS) -o $@ -c $<
      
       fast_test: $(FAST_TEST_OBJECTS)
           g++ $(CXXFLAGS) $^ $(LDFLAGS) -o $@
      
       test: fast_test
           ./$<
      
       .PHONY: test
      
    • 文件Fast/include/repeats.h

       #pragma once
      
       struct Repeats {
           explicit Repeats(int n) : rep(n){}
           int const rep;
       };
      
    • 文件Fast/include/size.h

       #pragma once
      
       struct Size {
           explicit Size(int n, int m)
               : n(n)
               , m(m)
           {
           }
           int const n, m;
       };
      
    • 文件Fast/include/test_config.h

       #include <boost/test/unit_test.hpp>
      
       #include "../include/size.h"
       #include "../include/repeats.h"
      
    • 文件Fast/src/main.cpp

    • 文件Fast/src/repeats.cpp

    • 文件Fast/src/size.cpp

    • 文件Fast/tests/module.cpp

       #define BOOST_TEST_MODULE Fast_Tests
       #include <boost/test/included/unit_test.hpp>
      
    • 文件Fast/tests/test_repeats.cpp

       #include "../include/test_config.h"
      
       BOOST_AUTO_TEST_CASE(test_repeats)
       {
           int n = 30;
           Repeats r = Repeats(n);
           BOOST_REQUIRE(r.rep == n);
       }
      
    • 文件Fast/tests/test_size.cpp

       #include "../include/test_config.h"
      
       BOOST_AUTO_TEST_CASE(test_size)
       {
           int n = 20;
           int m = 30;
           Size sz = Size(n, m);
           BOOST_REQUIRE(sz.n == n && sz.m == m);
       }
      

    【讨论】:

    猜你喜欢
    • 2018-03-11
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多