0

我希望在我的应用程序中添加一些测试,但是我不知道如何执行此操作以及需要什么。我已经能够通过创建测试本身来运行基本测试,但我不能通过将其添加到项目中来做到这一点。如果我创建了自己的测试项目,以下是有效的测试。

测试1.h

#pragma once
#include <C:\cppunit-1.12.1\cppunit-1.12.1\include\cppunit\extensions\HelperMacros.h>
class Test1 : public CPPUNIT_NS::TestCase
{
        CPPUNIT_TEST_SUITE(Test1);
        CPPUNIT_TEST(testStringAssert);
        CPPUNIT_TEST_SUITE_END();

public:

    Test1(void);
    ~Test1(void);

    void testStringAssert ();
};

测试1.cpp

#include "Test1.h"
#include "string"

CPPUNIT_TEST_SUITE_REGISTRATION(Test1);

Test1::Test1(void)
{
}

Test1::~Test1(void)
{
}
void Test1::testStringAssert(){
    std::string s1 = "1234567";
    std::string s2 = "1234567";
    CPPUNIT_ASSERT_EQUAL(s1, s2);

}

CPPUnitMain.cpp(取自 CPPUnit 示例文件夹)

#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <stdexcept>
#include <fstream>


int 
main( int argc, char* argv[] )
{
  // Retreive test path from command line first argument. Default to "" which resolve
  // to the top level suite.
  std::string testPath = (argc > 1) ? std::string(argv[1]) : std::string("");

  // Create the event manager and test controller
  CPPUNIT_NS::TestResult controller;

  // Add a listener that colllects test result
  CPPUNIT_NS::TestResultCollector result;
  controller.addListener( &result );        

  // Add a listener that print dots as test run.
#ifdef WIN32
  CPPUNIT_NS::TextTestProgressListener progress;
#else
  CPPUNIT_NS::BriefTestProgressListener progress;
#endif
  controller.addListener( &progress );      

  // Add the top suite to the test runner
  CPPUNIT_NS::TestRunner runner;
  runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );   
  try
  {
    CPPUNIT_NS::stdCOut() << "Running "  <<  testPath;
    runner.run( controller, testPath );

    CPPUNIT_NS::stdCOut() << "\n";

    // Print test in a compiler compatible format.
    CPPUNIT_NS::CompilerOutputter outputter( &result, CPPUNIT_NS::stdCOut() );
    outputter.write(); 

// Uncomment this for XML output
    std::ofstream file( "tests.xml" );
    CPPUNIT_NS::XmlOutputter xml( &result, file );
    xml.setStyleSheet( "report.xsl" );
    xml.write();
    file.close();
  }
  catch ( std::invalid_argument &e )  // Test path not resolved
  {
    CPPUNIT_NS::stdCOut()  <<  "\n"  
                            <<  "ERROR: "  <<  e.what()
                            << "\n";
    return 0;
  }

  return result.wasSuccessful() ? 0 : 1;
}
4

1 回答 1

2

开始有点复杂。我用过的最好的方法是在两个项目之间建立关系,原始的真实项目(我称之为 RealProject)和一个测试项目(我称之为 TestProject)。你的真实代码将继续存在在您的 RealProject.vcproj 中,但您需要添加第二个项目来存放您的测试代码。

打开包含您的 RealProject 的解决方案文件。在您的解决方案中创建一个新项目,并将其命名为 TestProject。在测试项目中,您将添加 CppUnit 测试代码和 main 函数(如上所示)。如果你现在构建它,它应该会失败。添加将使其链接所需的属性。打开 TestProject 属性,然后在 Linker/Input 屏幕中,编辑 Additional Dependencies 字段。从 CppUnit 添加适当的 .LIB 文件(如 TestRunner.lib) 在继续之前正确构建和链接上面的示例代码。以小步骤思考。

现在,再次打开 TestProject 属性,并在 Linker/Input 屏幕中编辑 Additional Dependencies 值。在此列表中,添加包含您要测试的代码的真实项目的目标文件。例如,如果 RealProject 有一个 Foo.cpp 包含您要测试的一些方法,您将添加 $(SolutionDir)RealProject\Debug\obj\Foo.obj 当然,这是假设这是您的目标文件的正确相对路径。对于不同的构建,您可能有不同的路径,例如发布、x64 或其他。首先让一个版本正常工作,然后应用您新发现的知识来正确构建其他版本。

现在向 TestProject 添加一个测试套件类(称为 FooTest.cpp)来测试 Foo.cpp 模块中的方法。确保它可以构建、链接和运行。您现在正在对您的第一个代码进行单元测试!恭喜!

您可能希望在源代码更改时重新构建测试。右键单击 TestProject 项目文件夹并选择 Project Dependencies。在 RealProject 前面添加复选标记。现在,如果您选择 TestProject 并构建它,它将确保首先构建 RealProject。

如果您想这样做一次而忘记它,您可以通配符整个对象文件夹,如下所示:

$(SolutionDir)RealProject\Debug\obj\*.obj

这样,您添加到 RealProject 的每个模块都可以编写单元测试,而不会弄乱项目设置。

这样做的一个好处是它总是在测试你实际的、事实的、编译的代码。没有“伪造”编译器,没有出于测试目的对源代码进行第二次编译,这是对实时代码的有效测试。另一个优点是通过将测试代码保存在单独的项目中,您不会意外地发布您的单元测试。它们编译在一个完全独立的文件夹中,您不会打包并交付给您的客户。

老实说,我希望它比这容易得多。我希望这是内置到 IDE 中的,并且会自动管理所有的簿记和参考资料等。任何使测试更容易的事情都会提高开发人员实际使用它的机会。

于 2012-01-16T23:25:43.107 回答