基于Qt_Test的单体测试方法(二)

来源:互联网 发布:逆战磁暴矩阵怎么用 编辑:程序博客网 时间:2024/04/30 08:41

2.1 数据驱动测试简介

在前一章单体测试的例子中,测试的数据只有一条,对于这个简单的被测函数来说也算够用。但是被测函数往往比较复杂,它可能包含多个分支,每个分支有不同的处理。此时应该选取多条测试数据,覆盖到被测函数所有分支。如果按照之前的做法,需要在测试函数中准备多条测试数据,执行多次被测函数并比较结果,这会使得代码臃肿不易阅读。幸好,Qt Test中提供了一种数据驱动的测试方法,能够很好地解决这个问题。

2.2 数据驱动测试方法

这种方法将原来测试函数中的处理拆分成两个部分,准备测试数据和执行被测函数,分别在数据驱动函数和测试函数中来做。数据驱动函数是一个新的函数,它也是以slot形式存在于测试类中。它的命名有个规则:XXX_data(),其中XXX代表测试函数名。这种方法的思路是

  1. 准备测试数据
  2. 取出测试数据作为被测函数的输入和期待结果
  3. 执行被测函数得到实际输出
  4. 将实际输出与期待结果比较

其中第1步在数据驱动函数中进行,2,3,4步在测试函数中进行。下面对它详细介绍。

2.2.1 编写新的被测函数

首先对原来例子做些修改,编写一个复杂些的被测函数。假设Bulk_quote继承自Quote,它新增了两个成员:m_discount折扣,m_minQuantity能够打折所需的最小数量。此外,它还重写了Base类的net_price(int quantity),表示如果购买一定数量的书籍,则给予这个折扣。

class Bulk_quote: public Quote{public:    Bulk_quote(const string& bookNo, double salePrice, int minQty, double discount):        Quote(bookNo,salePrice)      ,m_minQuantity(minQty)      ,m_discount(discount)    {}    //override base function    double net_price(int quantity) const    {        if(quantity >= m_minQuantity){            return quantity*(1 - m_discount)*m_salePrice;        }        else{            return quantity*m_salePrice;        }    }private:    int m_minQuantity;    double m_discount;}

2.2.2 编写数据驱动函数

测试类的编写在1.2中有过介绍,此处再写个测试类Test_Bulk_quote,并向其中加入测试函数和数据驱动函数。按照之前的介绍,数据驱动函数名应为net_price_data(),其中做的工作就是准备测试数据。这里的测试数据以数据集的形式存在,测试数据集可以看成是一个拥有行和列数据表格,类似于数据库中的表,这个表格中每一行代表一条测试数据,可见数据集提供了多条测试数据。Qt提供了两个方法用于添加测试数据集QTest::addColumn()QTest::newRow()
其中,QTest::addColumn(const char * name, T * dummy = 0)是指向这个数据集添加一列,name代表这列的名称,dummy可以忽略。它还是一个模板函数,可以指定这列数据的类型。而QTest::newRow(const char * dataTag)表示向数据集中添加一行测试数据,dataTag表示这个测试case的名称,便于定位测试数据。
在1.2.3中叙述了如何编写测试函数,现在把准备测试数据移动到数据驱动函数来做(测试数据包含被测函数输入和期待结果),就不必在测试函数中编写多个测试数据了,也就解决了开头说的函数臃肿难读的问题。
被测函数输入很多,这里只用quantity作为输入,因为类成员那些输入在构造对象时已经确定了。比如m_salePrice为128.0元,如果购买超过10本,则9折折扣,即m_discount为0.1,m_minQuantity为10。
数据驱动函数的编写如下:

void Test_Bulk_quote::net_price_data(){    QTest::addColumn<int>("quantity");    QTest::addColumn<double>("result");    QTest::newRow("less than ten") << 9 << 1152.0;    QTest::newRow("more than ten") << 11 << 1408.0;}

newRow()<<用于添加这行数据,其后的数据分别代表quantityresult列的值。在less than ten这行数据中,表示的意思就是,如果购买9本书(不打折),期待的结果是1152.0元。

2.2.3 编写测试函数

测试函数中需要做的处理就是2.2中的2,3,4步骤。这里再介绍另一个宏QFETCH(type, name),它用于提取测试数据,其中type表示数据类型,name表示数据集中的列名,这两个参数要和数据驱动函数中的定义完全对应,不然会报错。测试函数的编写如下:

void Test_Bulk_quote::net_price(){    //get data form data set    QFETCH(int, quantity);    QFETCH(double, result);    Bulk_quote cppPrimer("0001",128.0,10,0.1);    //actual val    double actual = cppPrimer.net_price(quantity);    //compare    qFuzzyCompare(actual,result);}

如前所述,构造Bulk_quote时,将它的所有成员都确定了。执行这个测试类时,数据驱动函数被执行一次,而测试函数被执行两次,因为数据集中有两条测试数据。
以上就是数据驱动测试的方法,这个方法将准备测试数据和执行被测函数分而治之,减少了代码间的耦合。在应用Qt Test时,尽量都采用这种方法,灵活运用QTest::addColumn()QTest::newRow()Q_FETCH等框架函数和宏,就能更大程度发挥Qt Test的功能了。

1 0
原创粉丝点击