Skip to content

A powerful and easy-to-use C/C++ test framework based on testngpp with lots of simplifications.

License

LGPL-3.0, Unknown licenses found

Licenses found

LGPL-3.0
LICENSE
Unknown
COPYING
Notifications You must be signed in to change notification settings

sinojelly/testngpp2

Repository files navigation

	testngpp2 --- A C/C++ Testing Framework
	-------------------------------------
	https://github.com/sinojelly/testngpp2
	https://gitee.com/sinojelly/testngpp2

testngpp2是基于testngpp演进来的一个轻量级、运行环境简单的测试框架,支持把所有TestSuite编译到一个可执行文件。

testngpp和testngpp2相比,测试用例写法,用例管理方式都是保持一致的,只是改变了编译运行方式,简化了编译运行环境:

特性 testngpp testngpp2 改进成testngpp2的原因
编译 每个测试.h文件内容
编译成一个so
可以任意多个测试.h文件内容
编译到一个可执行文件
更好的使用并行编译加速
运行 测试工具是可执行文件,
动态加载listener和
各个TestSuite的so
直接运行可执行文件即可 ①可执行文件运行可靠性更高;
②对不同平台的动态库加载机制依赖较少,
更容易跨平台(比如支持Android+Termux环境);
③运行命令简单,可以不加任何命令行参数;
④静态链接testngpp2.a,不是使用可执行文件或so,
相同架构机器不同编译器版本可能复用

相比testngpp,目前精简去掉了一些功能:

  • Sandbox运行机制
  • 文件句柄等资源泄露检查,它与平台紧密相关(独立的内存泄露检查是保留的)
  • xml文件输出(该功能目前未使用,所以没有测试)

testngpp2 features

OS Compiler Base function① Memory leak check Parameterized test
Linux GCC Yes Yes Yes
Win10 MinGW② Yes No Yes
Win10 VS2019 Yes Yes Yes
Android③ Clang Yes Yes Yes

注:

  • ① Base function包括:用例编写(包括tag,用例依赖)、用例管理(包括运行时过滤fixture/tag)等。
  • ② MinGW可靠性较差,比如.a rename fail, .cpp的函数实现无法链接等,不适合开发大的项目。
  • ③ Android+Termux,也可以使用VHEditor。

testngpp2基本概念

testngpp2用例编译运行流程如下:

注:

  • 可执行文件名 Tests 用户可自定义。

几个主要的概念:

  • TestSuite: 一个测试.h文件,就是一个TestSuite。
  • TestFixture: 测试用例中用 FIXTURE(TestFixtureName)声明的一个用例集合, 它组织了若干相关的用例,这些用例可以共享一些成员变量。一个TestSuite中可以有多个TestFixture。
  • TestCase: TestFixture中的每个用例都是一个TestCase。
  • SETUP,TEARDOWN: 每个TestFixture可以有 SETUP, TEARDOWN方法,在每个用例运行前会执行SETUP,每个用例运行结束执行TEARDOWN。

testngpp2命令行

一般直接运行编译生成的可执行文件即可。 如果希望只运行部分测试用例,或者定制输出格式,则需要了解命令行参数。

testngpp2命令行说明:

Tests [--filter-fixtures <fixture name>]...
      [--filter-testcase <full testcase name>]...
      [--filter-tags     <tag>]
      [-o <output> [-c] [-s] [-f] [-t] [-v] [-l <output level>]] 
      [-m]

执行 Tests -h 就可以查看上述帮助信息。命令行参数分为如下几类:

用例选择: 选择要运行的用例,默认运行全部用例。

  • --filter-fixtures : 后面跟TestFixture名称,可以用*通配符,可以用多个--filter-fixtures 指定多个Fixture。
  • --filter-testcase : 后面跟TestCase完整名称, 可以用多个--filter-testcase 指定多个TestCase。暂不支持指定中文用例名。
  • --filter-tags : 后面跟Tag名称,标记相应Tag的用例才会执行。

注意: 参数化的用例,要根据打印的用例名信息,来确定过滤时使用的用例名。 比如打印的用例信息:

[   RUN    ] ut_TestParameterized::ParameterizedTests::Test a plus b(1, 5, 6)
[    OK    ] (0 us)

过滤时,需要使用的参数:

--filter-testcase "Test a plus b(1, 5, 6)"

更复杂的参数化用例名: 打印的用例信息:

[  FAILED  ] st_test_single_video_player_fast::DataDrivenSingleVideoPlayerTestFast::Test single player play url video, and finished automatically(std::string(RESOURCE_DIR "/MP4/9_AVC_1280x720_59.940fps_AAC_128Kbps_2channels.mp4"))

过滤时,需要使用的参数:(注意其中的引号需要转义)

--filter-testcase "Test single player play url video, and finished automatically(std::string(RESOURCE_DIR \"/MP4/9_AVC_1280x720_59.940fps_AAC_128Kbps_2channels.mp4\")"

输出配置: 配置输出参数。

  • -o stdout : 输出到屏幕。后面还可以带如下参数:
    • -c : colourful
    • -s : show suite name
    • -f : show suite name and fixture name
    • -t : show tags
    • -v : show verbose info
    • -l level : set output level (0 ~ 3) 其中 level具体含义如下:
      • error/failure - always output
      • info - level 0 (output when level <= 0)
      • warning - level 1 (output when level <= 1)
      • skipped - level 2 (output when level <= 2)
  • -o xml:file : 输出到xml (使用较少,暂未支持)

默认输出配置是:-o stdout -c -v

运行配置: 配置运行时参数。

  • -m : 关闭内存泄露检查。

用例编写方法

简单样例

    TEST(测试: 1+1 = 2)
    {
        ASSERT_EQ(2, 1+1);
    }

常用的判断执行结果的宏有:

ASSERT_TRUE(expr) 
ASSERT_FALSE(expr) 
ASSERT_EQ(expected, value)
ASSERT_NE(expected, value)
ASSERT_DBL_EQ(expected, value)
ASSERT_DBL_NE(expected, value)
ASSERT_THROWS(expr, except)
ASSERT_THROWS_ANYTHING(expr)
ASSERT_THROWS_NOTHING(expr)
ASSERT_THROWS_EQ(expr, except, expected, value) // 执行expr后应该抛出except异常,并且expected与value相等
ASSERT_SAME_DATA(addr1, addr2, size) 
ASSERT_DELTA(x, y, d) // x与y的差小于d

这些宏都有对应的EXPECT版本(把ASSERT改为EXPECT即可),它与ASSERT版本的差异是:判断失败,该用例仍然继续执行。

使用Do-Cleanup避免资源泄漏

把资源清理代码写在Cleanup中。

    TEST(__DO__/__CLEANUP__/__DONE__)
    {
        __DO__
            FAIL("I'm gonna fail");
            WARN("I should not be shown");
        __CLEANUP__
            INFO("I should be shown always");
        __DONE__
    }

使用Annotation

使用id给用例起名字
    // @test(id=face-to-south)
    TEST(robot should face to south after turn right)
    {
       robot.turnRight();
       ASSERT_TRUE(robot.faceToSouth());
    }
使用depends设置用例的依赖关系
    // @test(id=face-to-west, depends=face-to-south)
    TEST(robot should face to west after another turn right)
    {
       robot.turnRight();
       ASSERT_TRUE(robot.faceToWest());
    }
使用tags设置Fixture/TestCase的标签

标签的作用:在testngpp-runner.exe运行命令行中,通过-f pattern来指定运行哪些用例。 多个标签用空格隔开。

    // @fixture(tags="ft something")
    FIXTURE(RobotTest)
    {
        // @test(tags="ut slow")
        TEST(robot should face to west after another turn right)
        {
             robot.turnRight();
             ASSERT_TRUE(robot.faceToWest());
        }
    };
使用memcheck设置Fixture/TestCase是否进行内存泄漏检查
//@fixture(memcheck=on)
FIXTURE(TestFixtureMemCheckOnAnnotation)
{
   TEST(fixture has been set to memcheck on, its tests all memcheck on)
   {
       char *p = new char; // should fail     
   }

   //@test(memcheck=off)
   TEST(fixture has been set to memcheck on, its test can use memcheck off to close mem leak check)
   {
        char *p = new char; // should success
   }
};
使用data进行参数化测试

参数化测试,是通过DATA_PROVIDER提供多组参数,每一组参数传入用例,就成了一个可运行的用例。

下面这个简单的用例,因为有三组数据,所以它执行时会运行三个用例。

这种测试方法非常适合于 一个测试方法,有多组输入数据时,可以构成多个用例的情况。

FIXTURE(DataDrivenTest)
{
	DATA_PROVIDER( mydata, 3
		, DATA_GROUP(1, 2, 3) 
		, DATA_GROUP(77, 20, 97) 
		, DATA_GROUP(101, 503, 604));

	// @test(data="mydata")
	PTEST( (int a, int b, int c), this is a parameterized test)
	{
		ASSERT_EQ(c, add(a, b));
	}
};

编译系统说明

  • build.bat /.sh
    • 编译并运行samples程序。
    • samples是用testngpp2写的一些样例,因为历史原因,用例风格有多种,建议参考TestMemLeak.h中的testngpp风格。
    • 参考samples/CMakeLists.txt即可配置一个产品项目的测试工程。
  • build_install.bat / .sh
    • 编译并安装,请先修改安装路径。
  • build_test.ps1 /.sh
    • 编译并运行testngpp2的测试用例。
    • testngpp2的测试用例仍然用testngpp写成,并且使用到mockcpp。

FAQ

1. 如果遇到类似下面的编译错误,删除自动生成的 测试 .cxx 文件 重新编译即可。

这是概率出现的 测试 .h 文件更新, 比如加入一些注释行,使得TEST所在行号改变,但是cmake未触发重新生成对应的.cxx文件导致的。

gen_testsuites\ut_TestRightValueOld.cxx(35,18): error C2039: "test_56": 不是 "TestTestRightValue" 的成员 [D:\Develop\cpp\learn-cpp\build\tests\ut\LearnCppTests.vcxproj]
2. Be carefull that the "{" after FIXTURE(xxx) and TEST(xxx) should be in the new line.

The test code below in TestXXX.h cause failure in generating TestXXX.cxx file.

FIXTURE(TestXXX) {
    TEST(test something) {
    }
};

It should be:

FIXTURE(TestXXX)
{ // Must like this, or else generate TestXXX.cpp fail.
    TEST(test something) 
    {  // Must like this, or else no testcase
    }
};

3. DataProvider各个参数的含义。

如下面代码,的参数:

  • mydata : data provider name
  • 3 : 一个DATA_GROUP包含的参数个数,这里是3.
	DATA_PROVIDER( mydata, 3
		, DATA_GROUP(1, 4, 5) 
		, DATA_GROUP(101, 503, 604));

4. 每个用例执行前的处理放在 SETUP() 中,每个用例执行后的处理放在TEARDOWN()中。

// @fixture(tags=debuging)
FIXTURE(DataDrivenSingleAudioRecorderTestFast)
{
    DATA_PROVIDER(pcmSources, 4,
    DATA_GROUP(AudioRecordSource(std::string(RESOURCE_DIR "/PCM/44100_2_02.pcm"), 44100, 2, 320000)));

    SETUP()
    {
        OHOS::Media::OSAL::FileSystem::RemoveFilesInDir(TestRecorder::GetOutputDir());
    }

    TEARDOWN()
    {
    }

    // @test(data="pcmSources", tags=fast)
    PTEST((AudioRecordSource recordSource), Test single audio recorder)
    {
    }
 };

Email to the current maintainers may be sent to [email protected].

About

A powerful and easy-to-use C/C++ test framework based on testngpp with lots of simplifications.

Resources

License

LGPL-3.0, Unknown licenses found

Licenses found

LGPL-3.0
LICENSE
Unknown
COPYING

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published