【问题标题】:How to call a template function to test in another file to test it with CppUnit如何调用模板函数在另一个文件中进行测试以使用 CppUnit 对其进行测试
【发布时间】:2023-01-26 12:21:49
【问题描述】:

我正在使用数组类型 (array<int,N>) 创建一个简单的 MergeSort 算法。 mergeSortByMyself函数是用模板写的。 我想用 CppUnit 测试它,但是当我运行代码时,它显示:

我的.h 文件是“mergeModel.h”,其中包含:

#pragma once
#include <bits/stdc++.h>
using namespace std;

template<typename Iterator>
void print(Iterator list);

template<size_t M, size_t P>
array<int,M+P> merge(array<int,M>& arr1, array<int,P>& arr2);

template<size_t N>
array<int,N> mergeSortByMyself(array<int,N>& list);

然后,我在“MergeSortByMyself.cpp”中包含“mergeModel.h”,该文件包含:

#include "mergeSortModel.h"

template<typename Iterator>
void print(Iterator list){
    for(auto item: list ){
        cout << item << " ";
    }
    cout << endl;
}
template<size_t M, size_t P>
array<int,M+P> merge(array<int,M>& arr1, array<int,P>& arr2){
    cout << "Merge starts here......."<<endl;
    int i = 0, j = 0, k = 0;
    array<int,arr1.size()+arr2.size()> joined;
    cout << "a1: " << arr1.size() << " a2: "<< arr2.size() << " a3: "<<joined.size()<< endl;
    for(k = 0; k < joined.size(); k++){
        if(i < arr1.size() && j < arr2.size() && arr1[i] < arr2[j]){
            joined[k] = arr1[i];
            i++;
        }else if( i < arr1.size() && j < arr2.size() &&  arr1[i] > arr2[j]){
            joined[k] = arr2[j];
            j++;
        }else{
            break;
        }
    }
    
    if(i == arr1.size()){
        for(; k < joined.size();k++  ){
            // cout << "j= "<<j << " k= "<<k<< endl;
            joined[k] = arr2[j];
            j++;
        }
    }
    if(j == arr2.size()){
        for(; k < joined.size(); k++){
            joined[k] = arr1[i];
            i++;
        }
    }
    cout << "joined ";
    print(joined);  
    return joined;
}

//array<int,N>
template<size_t N>
array<int,N> mergeSortByMyself(array<int,N>& list){
    if(list.size() <= 1){
        return list;
    }
    const int firstPart = (const int)list.size()/2;
    array<int, firstPart> leftArr;
    int i;
    for(i=0; i < firstPart; i++){
        leftArr[i] = list[i];
    }
    array<int,list.size() - firstPart> rightArr;
    for(i=firstPart; i < list.size(); i++){
        rightArr[i-firstPart] = list[i];
    }
    print(list);
    print(leftArr);
    print(rightArr);

    leftArr = mergeSortByMyself(leftArr);
    rightArr = mergeSortByMyself(rightArr);

    array<int,list.size()> joined;
    if(leftArr[leftArr.size() -1] > rightArr[0]){
        joined = merge(leftArr,rightArr);
    }else{
        int y = 0;
        for(int g = 0; g < joined.size(); g++){
            if(y < leftArr.size()){
                joined[g] = leftArr[y];
            }else{
                joined[g] = rightArr[y-leftArr.size()];
            }
            y++;
        }
    }
    return joined;
}

显然,代码在 main() 函数中运行良好:

int main(){
    array<int,3> arr = {3,2,1};
    array<int,3> sorted = mergeSortByMyself(arr);
    print(sorted);
}   

但是当我尝试使用 CppUnit 运行“mergeSortByMyself()”函数时。它显示了一个错误: 文件“testing.cpp”使用 CppUnit 和“mergeModel.h”:

//testing.cpp
#include "mergeSortModel.h"
#include <cppunit/TestRunner.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
// #define N 100;

template<typename Iterator>
void print(Iterator list){
    for(auto item: list){
        cout << item << " ";
    }
    cout << endl;
}
template<typename Iterator>
string toStr(Iterator list){
    string str="";
    for(auto item: list){
        str += to_string(item);
    }
    return str;
}

class Test : public CPPUNIT_NS::TestCase
{
  CPPUNIT_TEST_SUITE(Test);
  CPPUNIT_TEST(testMergeSort);
  CPPUNIT_TEST_SUITE_END();

public:
  void setUp(void) {}
  void tearDown(void) {} 

protected:
    void testMergeSort(void){
        const size_t n = 12;
        array<int,n> tosort;
        array<int,n> tosort_test;

        for(int i = 0; i < n; i++){
            tosort[i] = rand()%100;
            tosort_test[i] = tosort[i];
        }

        // copy(tosort.begin(), tosort.end(), tosort_test);
        sort(tosort.begin(),tosort.end());

        array<int,n> sorted = mergeSortByMyself<tosort_test.size()>(tosort_test);        

        CPPUNIT_ASSERT(toStr(tosort)==toStr(tosort_test));
        // print(tosort);

    }
};

CPPUNIT_TEST_SUITE_REGISTRATION(Test);

int main( int ac, char **av )
{
    srand(time(0));
 
    CPPUNIT_NS::TestResult controller;

    CPPUNIT_NS::TestResultCollector result;
    controller.addListener( &result );        

    CPPUNIT_NS::BriefTestProgressListener progress;
    controller.addListener( &progress );      

    CPPUNIT_NS::TestRunner runner;
    runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest());
    runner.run( controller );

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

运行我使用的代码的命令:g++ mergeSortByMyself.cpp testing.cpp -lcppunit -o test

【问题讨论】:

标签: c++ unit-testing cppunit


【解决方案1】:

最后,你是对的@sklott。 编译器只有两种方式了解特定的模板函数:

  1. 首先:将所有模板定义(您的代码实现)传递到“.h”文件中。
  2. 第二:在“.cpp”文件中编写具体实现。

    一个对我有帮助的有用链接是this

    我认为第二种方式对我的模板函数不可行,因为 mergeSortByMySelf() 函数不断改变模板参数“size_t N“:

    template<size_t N>
    array<int,N> mergeSortByMyself(array<int,N>& list)
    

    所以我决定采用第一种方法,这种方法更简单,但在 isocpp.org 中,在之前提供的链接中,它说:

    第一个解决方案是物理移动的定义 .h 文件中的模板函数,即使它们不是内联的 职能。此解决方案可能(或可能不会!)导致大量代码 膨胀,这意味着您的可执行文件大小可能会急剧增加(或者,如果 您的编译器足够聪明,可能不够;试试看)。

    尽管如此,我还是做到了。 这是“mergeSortModel.h”:

    #pragma once
    #include <bits/stdc++.h>
    using namespace std;
    
    template<typename Iterator>
    void print(Iterator list);
    
    template<size_t M, size_t P>
    array<int,M+P> merge(array<int,M>& arr1, array<int,P>& arr2);
    
    template<size_t N>
    array<int,N> mergeSortByMyself(array<int,N>& list);
    
    //-------------------------DEFINITIONS of TEMPLATES
    template<typename Iterator>
    void print(Iterator list){
        for(auto item: list ){
            cout << item << " ";
        }
        // cout << "
    **********"<<endl;
        cout <<endl;
    }
    template<size_t M, size_t P>
    array<int,M+P> merge(array<int,M>& arr1, array<int,P>& arr2){
        // cout << "Merge starts here......."<<endl;
        int i = 0, j = 0, k = 0;
        array<int,arr1.size()+arr2.size()> joined;
        // cout << "a1: " << arr1.size() << " a2: "<< arr2.size() << " a3: "<<joined.size()<< endl;
    
        // cout << "partA: ";
        // print(arr1);
        // cout << "
    ";
        // cout << "partB: ";
        // print(arr2);
        // cout << "
    ";
        
        for(k = 0; k < joined.size(); k++){
            if(i < arr1.size() && j < arr2.size() && arr1[i] < arr2[j]){
                joined[k] = arr1[i];
                i++;
            }else if( i < arr1.size() && j < arr2.size() &&  arr1[i] >= arr2[j]){
                //arr1[i] >= arr2[j] This is important, 
                //there was an error with "arr1[i] > arr2[j]"
                joined[k] = arr2[j];
                j++;
            }else{
                break;
            }
        }
        
        if(i == arr1.size()){
            for(; k < joined.size();k++  ){
                // // cout << "j= "<<j << " k= "<<k<< endl;
                joined[k] = arr2[j];
                j++;
            }
        }
        if(j == arr2.size()){
            for(; k < joined.size(); k++){
                joined[k] = arr1[i];
                i++;
            }
        }
        // cout << "joined ";
        // print(joined);  
        return joined;
    }
    
    //array<int,N>
    template<size_t N>
    array<int,N> mergeSortByMyself(array<int,N>& list){
        if(list.size() <= 1){
            return list;
        }
        const int firstPart = (const int)list.size()/2;
        array<int, firstPart> leftArr;
        int i;
        for(i=0; i < firstPart; i++){
            leftArr[i] = list[i];
        }
        array<int,list.size() - firstPart> rightArr;
        for(i=firstPart; i < list.size(); i++){
            rightArr[i-firstPart] = list[i];
        }
        // cout << "
    Call starts here.....................
    ";
        // print(list);
        // print(leftArr);
        // print(rightArr);
        // cout << "
    Call ends here.....................
    ";
    
        leftArr = mergeSortByMyself(leftArr);
        rightArr = mergeSortByMyself(rightArr);
    
        array<int,list.size()> joined;
        if(leftArr[leftArr.size() -1] > rightArr[0]){
            joined = merge(leftArr,rightArr);
        }else{
            int y = 0;
            for(int g = 0; g < joined.size(); g++){
                if(y < leftArr.size()){
                    joined[g] = leftArr[y];
                }else{
                    joined[g] = rightArr[y-leftArr.size()];
                }
                y++;
            }
        }
        return joined;
    }
    

    这是带有 CppUnit 的单元测试:

    //testing.cpp
    #include "mergeSortModel.h"
    #include <cppunit/TestRunner.h>
    #include <cppunit/TestResult.h>
    #include <cppunit/TestResultCollector.h>
    #include <cppunit/extensions/HelperMacros.h>
    #include <cppunit/BriefTestProgressListener.h>
    #include <cppunit/extensions/TestFactoryRegistry.h>
    // #define N 100;
    
    // template<typename Iterator>
    // void print(Iterator list){
    //     for(auto item: list){
    //         cout << item << " ";
    //     }
    //     cout << endl;
    // }
    template<typename Iterator>
    string toStr(Iterator list){
        string str="";
        for(auto item: list){
            str += to_string(item)+" ";
        }
        cout <<"
    |"<<str<<"|
    ";
        return str;
    }
    template<size_t M>
    bool test_arrays(array<int,M> a, array<int,M> b){
        if(a.size() != b.size()) 
            return false;
    
        for(int i = 0; i < a.size(); ++i){
            if(!(a[i] == b[i])) 
                return false;
        }
        return true;
    }
    class Test : public CPPUNIT_NS::TestCase
    {
      CPPUNIT_TEST_SUITE(Test);
      CPPUNIT_TEST(testMergeSort);
      CPPUNIT_TEST_SUITE_END();
    
    public:
      void setUp(void) {}
      void tearDown(void) {} 
    
    protected:
        void testMergeSort(void){
            const size_t n = 73;
            array<int,n> tosort;
            array<int,n> tosort_test;
    
            for(int i = 0; i < n; i++){
                tosort[i] = rand()%100;
                tosort_test[i] = tosort[i];
            }
            toStr(tosort);
            toStr(tosort_test);
            // copy(tosort.begin(), tosort.end(), tosort_test);
            sort(tosort.begin(),tosort.end());
            array<int,n> sorted = mergeSortByMyself<tosort_test.size()>(tosort_test);
            cout << "------------RESULTS--------------
    ";
            toStr(tosort);
            toStr(sorted);
            CPPUNIT_ASSERT(test_arrays<n>(tosort,sorted));
    
            // print(tosort);
            // print(sorted);
        }
    };
    
    
    CPPUNIT_TEST_SUITE_REGISTRATION(Test);
    
    int main( int ac, char **av )
    {
        srand(time(0));
     
        CPPUNIT_NS::TestResult controller;
    
        CPPUNIT_NS::TestResultCollector result;
        controller.addListener( &result );        
    
        CPPUNIT_NS::BriefTestProgressListener progress;
        controller.addListener( &progress );      
    
        CPPUNIT_NS::TestRunner runner;
        runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest());
        runner.run( controller );
    
        return result.wasSuccessful() ? 0 : 1;
    }
    

    运行命令:g++ testing.cpp -lcppunit -o test

    “测试”的大小是:

    122792 Jan 25 22:55 test
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-18
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    相关资源
    最近更新 更多