使用Catch C++进行单元测试会干扰我的main()

nhe*_*shy 8 c++ unit-testing catch-unit-test

我是单元测试的新手,并决定将Catch框架用于c ++,因为它似乎很容易与其一个头文件集成.但是,我有一个多文件二进制搜索树程序(文件是:main.cpp,Tree.h,Tree.hxx,TreeUnitTests.cpp,catch.hpp).如果我在main.cpp中注释掉我的int main()函数,我只能运行单元测试.我知道它与我的TreeUnitTests.cpp中的'#define CATCH_CONFIG_MAIN'声明冲突,但如果我不包含该声明,我无法运行单元测试.每次我想运行单元测试时,如何在不必评论main()的情况下运行两者?

这是我正在使用的头文件:https: //raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp

我发现它的Catch教程并用作指南:https: //github.com/philsquared/Catch/blob/master/docs/tutorial.md

一些相关文件供参考: main.cpp:

//******************* ASSN 01 QUESTION 02 **********************

#include "Tree.h"
#include <iostream>

using namespace std;

/*
int main()
{

    //creating tree with "5" as root
    Tree<int> tree(5);
    tree.insert(2);
    tree.insert(88);
    tree.inorder();
    cout << "does tree contain 2?: ";
    cout << tree.find(2) << endl;
    cout << "does tree contain 3?: ";
    cout << tree.find(3) << endl;

    Tree<int> copytree(tree);
    cout << "copied original tree..." << endl;
    copytree.preorder();
    cout << "after deletion of 2:\n";
    copytree.Delete(2);
    copytree.postorder();


    return 0;
}
*/
Run Code Online (Sandbox Code Playgroud)

TreeUnitTests.cpp:

#include <iostream>
#include "Tree.h"
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("Pass Tests")
{
    REQUIRE(1 == 1);
}

TEST_CASE("Fail test")
{
    REQUIRE(1 == 0);
}
Run Code Online (Sandbox Code Playgroud)

(我的测试不是真正的测试,只是为了验证Catch框架是否正常工作.我想你可以说这是一个元测试)

Gro*_*roo 7

由于您使用的是 Visual Studio,正确的方法是使用配置管理器(可通过右键单击解决方案资源管理器工具窗口中的解决方案访问)并创建单独的解决方案配置。

在“新解决方案配置”表单中,为配置指定一个有意义的名称(例如UnitTesting)。还有一个名为“Copy from:”的下拉列表,您可以在其中选择将设置复制到新配置中的配置。不要将其保留在<Empty>,而是选择一些您迄今为止用于构建源的源配置(因为它将正确设置包含文件夹和其他设置)。通过选中“创建新项目配置”复选框,确保您还为解决方案中的所有项目创建匹配的项目配置。

创建配置后,使用工具栏下拉列表选择它,就像在调试和发布配置之间切换一样:

单击以选择您的新配置 单击以选择您的新UnitTesting配置

现在,当您打开某个项目或该项目中的文件的属性页时(右键单击文件或项目,选择Properties),您可以选择特定配置(UnitTesting在您的情况下),并指定某些仅处于活动状态的选项对于这种单一配置。

All Configurations显然,您还可以在属性页中选择将设置应用于所有配置。这在添加额外的包含目录和通用预处理器设置时很重要。如果不小心只在Debug配置中添加了一些include目录,编译器切换到UnitTesting.

因此,要使此配置的行为有所不同,您可以执行以下操作:

1.main.cppUnitTesting构建配置中排除

例如,您可以仅在此配置中右键单击main.cpp、打开Properties并从构建中排除文件:

从构建中排除文件 从特定配置的构建中排除文件

2.使用预处理器宏有条件地排除main()函数

或者,您可以打开项目属性并设置一个特定的预处理器宏,该宏将仅在此配置中定义:

在此处输入图片说明 UNIT_TESTINGUnitTesting配置创建一个宏,再次使用 MS Paint 为图形添加天赋

因此,对于后一种方法,您的实际值main.cpp将更改为:

// remove if UnitTesting configuration is active
#ifndef UNIT_TESTING
int main(void)
{
    ...
}
#endif
Run Code Online (Sandbox Code Playgroud)

第一种方法很简洁,因为它根本不需要您更改生产代码,但是对于在 Visual Studio 中查看您的代码的其他毫无戒心的人来说,当他们开始想知道为什么某些代码没有更改时,后一种方法可能更明显正在编译。我有时会忘记构建配置中缺少某个文件,然后盯着奇怪的编译错误看了一会儿。

而且,使用第二种方法,您还可以轻松地在同一位置提供自定义 Catch 入口点:

#ifdef UNIT_TESTING

    // this is the main() used for unit testing

#   define CATCH_CONFIG_RUNNER
#   include <catch.hpp>

    int main(void)
    {
        // custom unit testing code
    }    

#else

    int main(void)
    {
        // actual application entry point
    }

#endif
Run Code Online (Sandbox Code Playgroud)


Kob*_*uck 6

当你离开时CATCH_CONFIG_RUNNER,Catchmain为你实现。对于大多数测试,它已经足够了,但是如果您需要更多控制,那么您需要告诉它使用您的 main 并在其中引导 Catch。

使用像这样简单的东西:

主程序

#define CATCH_CONFIG_RUNNER // Configure catch to use your main, and not its own.
#include <catch.hpp>
#include <iostream>
#include <exception>

int main(int argCount, char** ppArgs)
{
    try {
        // bootstrap Catch, running all TEST_CASE sequences.
        auto result = Catch::Session().run(argCount, ppArgs);
        std::cin.get(); // Immediate feedback.
        return (result < 0xFF ? result : 0xFF);
    } catch (const std::exception& ex) {
        auto pMessage = ex.what();
        if (pMessage) {
            std::cout << "An unhandled exception was thrown:\n" << pMessage;
        }
        std::cin.get(); // Immediate feedback.
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试.cpp

#include <catch.hpp>

TEST_CASE("Pass Tests")
{
    REQUIRE(1 == 1);
}

TEST_CASE("Fail test")
{
    REQUIRE(1 == 0);
}
Run Code Online (Sandbox Code Playgroud)

这或多或少是我在生产代码中使用的,而且效果很好。