轻量级测试框架TUT

原创 2011年07月07日 20:08:01

单元测试框架

在开发实践中,我目前常用的单元测试框架主要是两个:GTest与TUT。关于GTest我会在其他文章中详细介绍,本文将主要介绍TUT框架的特点及简单的使用方法。

TUT(Template Unit Tests)

TUT的官方主页:http://tut-framework.sourceforge.net/index.html

TUT的SVN地址:http://tut-framework.svn.sourceforge.net/svnroot/tut-framework/trunk

TUT的用户手册:http://tut-framework.sourceforge.net/doxygen/index.html

TUT是一个使用C++编写的单元测试框架,正如名称所示,它是一套C++模板库。下载代码后我们可以发现:它的全部核心是由一系列的.hpp文件组成,不包含任何源文件(example除外),因此,我们在进行单元测试时只需要包含tut的文件即可,无需对TUT进行编译或者链接,像使用STL一样轻松自由,这也是我喜欢它的原因。

 

TUT使用方法

既然是一个轻量级测试框架,我们应该在半个小时内上手,行了,废话少说,假定我们开发了下面的一个类库:

COperator.h

#include <stdio.h>
class COperator
{
private:
    int m_value;
public:
    COperator(int value)
    {
        m_value = value;
    }
    
    int add(int value)
    {
           return  m_value += value;
    }
    
    int  sub(int value)
    {
           return  m_value -= value;
    }
};


我们希望对COperator的每个接口进行单元测试,则可以针对COperator类定义一个TestGroup,然后在这个TestGroup编写多个TestCase,每个TestCase对一个或几个接口进行测试,测试代码如下:

test_COperator.cpp

#include <stdio.h> 
#include <tut/tut.hpp> 

namespace tut
{
     // 每个测试组都必须基于一个测试数据的类型才能创建,可以在这个数据结构中放一些可能被该组中多个测试用例使用的数据或者方法,
     // 如果没有,也可以什么都不填。最好不要通过此结构的成员在不同测验用例间传递数据。
     struct COperatorTestData
     {
            int GetTestNum()
            {
                    static const int  TestNums[] = { 1, 3, 5, 7, 9 };
                    static int i = 0;
                    static const int num = sizeof(TestNums) / sizeof(int);
                    return  TestNums[ i++  %  num];            
            }
     };
     
     // 创建一个test_group对象时,在构造函数中用一个字符串指明该test group的名称;
     // 当存在多个test group时,每个group的名称应该不同,这样可以在启动时单独指定某个test group进行测试;
     // 缺省情况下,一个test_group最多50个test case,如果希望更多case,可以在定义时指明上限,如:
     // test_group   testgroup("COperator",1000);
     static  test_group   testgroup("COperator");
     
     template<>
     template<>
     void test_group::object::test<1>()   // 编写第一个测试用例
     {
            set_test_name("Test COperatorTestData::add");
            int  src = GetTestNum();
            COperator  op(src) ;
            ensure("Test COperatorTestData::Add Failed",   op.add(1) == src + 1);
     }
      
    template<>
    template<>
    void test_group::object::test<2>()        // 编写第二个测试用例
    {
           set_test_name("Test COperatorTestData::sub");
           int  src = GetTestNum();
           COperator  op(src) ;
           ensure("Test COperatorTestData::Sub Failed",   op.sub(2) == src - 2);
    }
    
    template<>
    template<>
    void test_group::object::test<3>()        // 没事找茬,写个错误case看看
    {
           set_test_name("Test Tut::ensure");
           int  src = GetTestNum();
           COperator  op(src) ;
           ensure("Test COperatorTestData::Sub Failed",   op.sub(2) == src - 1);
    }
}

 

如果还需要测试其他类,我也可以在编写如test_*.cpp等一系列单元测试用例,最终通过main函数将用例综合起来: test_main.cpp

#include <tut/tut.hpp> 
#include <tut/tut_console_reporter.hpp> 
#include <tut/tut_main.hpp> 
#include <iostream> 

static tut::test_runner_singleton runner;

int main(int argc, const char* argv[])
{
    tut::console_reporter reporter;
    tut::runner.get().set_callback(&reporter);

    try
    {
        if(tut::tut_main(argc, argv))
        {
            if(reporter.all_ok())
            {
                return 0;
            }
            else
            {
                std::cerr << "/nFAILURE and EXCEPTION in these tests are FAKE ;)" << std::endl;
            }
        }
    }
    catch(const tut::no_such_group &ex)
    {
        std::cerr << "No such group: " << ex.what() << std::endl;
    }
    catch(const tut::no_such_test &ex)
    {
        std::cerr << "No such test: " << ex.what() << std::endl;
    }
    catch(const tut::tut_error &ex)
    {
        std::cout << "General error: " << ex.what() << std::endl;
    }
    return 0;
}


我们只需要将test_*.cpp连起来编译即可,假如生成一个test.exe文件,我们可以用
test.exe --help                     查看帮助
test.exe                                 运行所有TestGroup
test.exe "COperator"         运行名称为"COperator"的TestGroup
test.exe "COperator"   1    运行名称为"COperator"的TestGroup的第一个测试用例。

TUT的输出

TUT目前支持三种报告的输出方式:console_reporter, xml_reporter,cppunit_reporter。另外,也可以自己继承tut::callback,编写自己的输出方式。下面,以xml方式输出为例,可以如下修改test_main.cpp:

...
//#include <tut/tut_console_reporter.hpp> 
#include <tut/tut_xml_reporter.hpp> 
...

int main(int argc, const char* argv[])
{
    tut::xml_reporter reporter(std::cout);    // 将xml输出到stdio,也可以选择输出到某个字符串中
    tut::runner.get().set_callback(&reporter);
    ...
}


执行所有用例,输出结果如下:

<xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuites>
  <testsuite errors="0" failures="1" tests="3" name="COperator">
    <testcase classname="COperator" name="Test COperatorTestData::add"/>
    <testcase classname="COperator" name="Test COperatorTestData::sub"/>
    <testcase classname="COperator" name="Test Tut::ensure">
      <failure message="Test COperatorTestData::Sub Failed" type="Assertion">Test COperatorTestData::Sub Failed</failure>
    <testcase>
  <testsuite>
<testsuites>


TUT的断言

TUT支持一系列ensure开头的断言函数,一旦断言失败则该case不再继续执行,转而执行下一个case,下面介绍几种常用的断言,其余的建议自己参考tut_assert.hpp与tut_posix.hpp

// 断言某个条件为真
void ensure(bool cond);


// 断言某个条件为假
void ensure_not(bool cond);

// 断言某个条件为真,否则输出msg
template <typename M>
void ensure(const M& msg, bool cond);

// 与ensure类似,不过在posix系统中会在msg后输出errno
template<typename M>
void ensure_errno(const M& msg, bool cond);

// 断言某个条件假,否则输出msg  
template <typename M>
void ensure_not(const M& msg, bool cond);

// 断言两个值相等
template <typename LHS, typename RHS>
void ensure_equals(const LHS& actual, const RHS& expected);

// 断言两个值相等,否则输出msg  
template <typename M, typename LHS, typename RHS>
void ensure_equals(const M& msg, const LHS& actual, const RHS& expected);

// 断言两个浮点数相差不超过某个限定值,否则输出msg
template<typename M>
void ensure_equals(const M& msg, const double& actual, const double& expected, const double& epsilon);

// 断言两个集合相等,否则输出msg
template<typename LhsIterator, typename RhsIterator>
void ensure_equals(const std::string &msg,
                   const LhsIterator &lhs_begin, const LhsIterator &lhs_end,
                   const RhsIterator &rhs_begin, const RhsIterator &rhs_end);
// 断言两个值距离小于distance,否则输出msg
template <typename M, class T>
void ensure_distance(const M& msg, const T& actual, const T& expected, const T& distance);

// 相当于直接断言错误,并输出msg
void fail(const char* msg = "");

// 跳过某个测试用例剩余的代码(不视为断言错误),并打印msg
void skip(const char* msg = "");

TUT的断言
作者:icefireelf

出处:http://blog.csdn.net/icefireelf/article/details/6363126

QTP自动化测试框架源码-轻量级

  • 2017年07月20日 10:51
  • 294KB
  • 下载

简单分享一个轻量级自动化测试框架目录结构设计

很多人在做自动化测试的过程中会遇到一个瓶颈,就是能够写脚本,但是不知道怎么去组织代码,怎么搭建测试框架,今天博主就放点干货,分享一个轻量级的自动化测试框架的目录结构,如下图:分层如下: config层...

轻量级自动化测试框架(QTP)

  • 2015年02月04日 23:37
  • 326KB
  • 下载

QTP自动化轻量级测试框架

  • 2011年03月18日 10:03
  • 2KB
  • 下载

CUnit C单元测试轻量级框架

CUnit下载地址: http://sourceforge.net/projects/cunit/ CUnit 在线文档帮助:http://cunit.sourceforge.net/doc/ind...

QTP轻量级自动化测试框架

  • 2009年11月09日 19:45
  • 278KB
  • 下载

EUnit——erlang的轻量级单元测试框架

EUnit——erlang的轻量级单元测试框架 译文: 目录: 3.1 包含EUnit头文件 3.2 写一个简单的生成函数 3.3 运行EUnit 3.4 写一个测试的生成函数 3.5 ...

EUnit—erlang的轻量级单元测试框架

EUnit—erlang的轻量级单元测试框架 目录: 3.1 包含EUnit头文件 3.2 写一个简单的生成函数 3.3 运行EUnit 3.4 写一个测试的生成...

一种轻量级、可重用、可扩展的 OSGi 应用程序测试框架

引言OSGi 是一个基于 Java 的,提供动态模块加载和管理的运行时框架,在业界已经得到广泛应用。OSGi 框架使用 Bundle 把复杂的应用程序模块化。在 OSGi 的框架中,Bundle 的生...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:轻量级测试框架TUT
举报原因:
原因补充:

(最多只允许输入30个字)