使用Catch测试C++类

5

我决定做一个小项目,尽可能地对其进行测试。我使用的是CLion(使用CMake)和Catch库进行测试。

问题在于,在运行测试类时,我得到了“undefined reference to TestClass::add”方法的错误提示。

以下是我的设置(这只是个虚拟的例子,因为我想确保一切都能正常工作):

TestClass.h

#ifndef LLL_TESTCLASS_H
#define LLL_TESTCLASS_H

class TestClass {
public:
    int add(int a, int b);
};

#endif //LLL_TESTCLASS_H

TestClass.cpp

#include "TestClass.h"
int TestClass::add(int a, int b) {
    return a + b;
}

test.cpp -- 包含测试的文件

#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "../src/TestClass.h"

TEST_CASE("addition") {
    TestClass testClass;
    REQUIRE(testClass.add(2,3) == 5);
    REQUIRE(testClass.add(-1, 1) == 0);
    REQUIRE(testClass.add(2, 4) == 1);
}

CMakeLIsts.txt

cmake_minimum_required(VERSION 3.2)
project(LLL)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(LIB_DIR "lib")
include_directories(${LIB_DIR}/Catch)
include_directories(${LIB_DIR}/Eigen)

set(SRC_DIR src)
set(SOURCE_FILES ${SRC_DIR}/main.cpp src/TestClass.h src/TestClass.cpp)
add_executable(LLL ${SOURCE_FILES})

set(TEST_DIR test)
set(TEST_FILES ${TEST_DIR}/test.cpp)
add_executable(LLL_TEST ${TEST_FILES})
2个回答

6
你的问题已经被Polevoy回答过了,他也正确地提出了将你的类重构成一个库的建议。
我想展示一下这个库版本的代码。你可以自行决定是否需要阅读相关书籍或者是否对TDD有什么额外开销。
cmake_minimum_required(VERSION 3.2)
project(LLL)

set(CMAKE_CXX_STANDARD 11) # adds -std=c++11
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(LIB_DIR "lib")
include_directories(${LIB_DIR}/Catch)
include_directories(${LIB_DIR}/Eigen)

add_library(LLL_LIB src/TestClass.h src/TestClass.cpp)

add_executable(LLL src/main.cpp)
target_link_libraries(LLL LLL_LIB)

add_executable(LLL_TEST test/test.cpp)
target_link_libraries(LLL_TEST LLL_LIB)

此脚本创建静态库LLL_LIB,该库被链接到两个可执行文件中。如果您愿意,也可以构建共享库:

add_library(LLL_LIB SHARED src/TestClass.h src/TestClass.cpp)

但是在这里使用静态的就足够了。


5

您没有指定要在LLL_TEST可执行目标中编译的TestClass.{.h, .cpp}

set(TEST_FILES src/TestClass.h src/TestClass.cpp ${TEST_DIR}/test.cpp)

或者更好的方式是将其移入共享库并链接到它。

问题是因为您的项目生成了2个可执行文件:LLLLLL_TEST目标。它们每个都有一个对象文件和引用。在LLL目标中,对TestClass的引用已经被满足,因为它们编译在LLL目标中,所以ld可以简单地链接它们。但在LLL_TEST目标的情况下,编译器找不到这些符号,因为它们没有在该目标中指定 - 这就是为什么编译器会说它无法解析引用的原因。


谢谢,这个可以用...但是你能解释一下这部分吗:"或者最好将它移动到某个共享库中,然后只需链接到它"?我对整个C++和构建系统的东西都很新,并且使用过相当容易安装和使用的Java和Python库,所以我有点迷失 :/ - Sven Vidak
1
@SvenVidak 如果我的回答有所帮助 - 请接受它作为解决方案,以便其他遇到同样问题的人可以知道答案。关于库,它需要非常非常庞大的文本,也需要很多时间来理解。我建议你阅读一本关于 CC++ 的好书。但是这些库,在我看来,只有在某些Unix/Linux书籍中才得到了很好的解释。 - Victor Polevoy
我还需要等待两分钟才能够接受答案。关于共享库——我对它们有一些了解,但据我所知,每次想要测试某些东西时都必须重新创建它们,如果我想做像TDD这样的事情,那将非常繁琐。我理解得对吗? - Sven Vidak
2
如果你使用TDD - 是的,当然你应该考虑你项目的架构并进行优化。 - Victor Polevoy
我想澄清一下,是的,每次您更改内容并希望进行测试时,都需要重新创建lib,但是如果按照tamas.kenez的答案设置,该过程根本不会令人感到疲劳,就像常规重建一样,无论如何您都必须这样做,就像在Java中一样。 - jmmut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接