?? rcunit_stepbystep.html
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>RCUnit: RCUnit step by step</title><link href="doxygen.css" rel="stylesheet" type="text/css"></head><body><!-- 制作者 Doxygen 1.4.2 --><div class="qindex"><a class="qindex" href="index.html">首頁</a> | <a class="qindex" href="modules.html">模塊</a> | <a class="qindex" href="annotated.html">數據結構</a> | <a class="qindex" href="dirs.html">目錄</a> | <a class="qindex" href="files.html">文件列表</a> | <a class="qindex" href="functions.html">數據字段</a> | <a class="qindex" href="globals.html">全局定義</a> | <a class="qindex" href="pages.html">相關頁面</a></div><div class="nav"><b>rcunit_stepbystep.dox</b></div><h1><a class="anchor" name="rcunit_stepbystep">RCUnit step by step</a></h1><h2><a class="anchor" name="stepbystep_catalog">目錄</a></h2><ul><li><a class="el" href="rcunit_stepbystep.html#build_rcunit">編譯 RCUnit</a></li><li><a class="el" href="rcunit_stepbystep.html#create_project">建立工程</a></li><li><a class="el" href="rcunit_stepbystep.html#settingup_project">配置工程</a></li><li><a class="el" href="rcunit_stepbystep.html#run_all_tests">準備測試程序框架</a></li><li><a class="el" href="rcunit_stepbystep.html#implement_function">編寫功能函數</a></li><li><a class="el" href="rcunit_stepbystep.html#prepare_testcases">準備測試用例</a></li><li><a class="el" href="rcunit_stepbystep.html#add_suite_and_case">添加測試集及測試用例</a></li><li><a class="el" href="rcunit_stepbystep.html#analyse_results">分析測試結果</a></li><li><a class="el" href="rcunit_stepbystep.html#rectify_errors">修改代碼錯誤</a></li><li><a class="el" href="rcunit_stepbystep.html#test_suite_resources">測試集的資源申請及釋放</a></li></ul><p>該示例工程的所有源碼在 rcunit/examples/simple_example 目錄下。<h2><a class="anchor" name="build_rcunit">編譯 RCUnit</a></h2>當獲得 RCUnit 的全部源碼后,你需要自己編譯 RCUnit,生成相應的庫文件。 目前 RCUnit 的 project 目錄中提供了 VC 6 和 Visual Studio.Net 的工程文件,你可以用相應工具打開工程文件,直接編譯即可。 編譯 RCUnit 會生成 Debug 版本的 rcunitd.lib 和 Release 版本的 rcunit.lib ,它們都放在 RCUnit 的 lib 目錄中。 編譯完成之后,需要把 RCUnit 的 include 目錄加到 IDE 的 include 搜索路徑中, 把 RCUnit 的 lib 目錄加到 IDE 庫搜索路徑中。 編譯和準備工作完成,可以開始使用 RCUnit 了。<h2><a class="anchor" name="create_project">建立工程</a></h2>下面我們將以一個實際例子,講述怎樣在 VC 6 下使用 RCUnit。<p>我們的目標是要實現這樣的功能,核心功能函數接口如下: <div class="fragment"><pre class="fragment"><span class="comment">/*************************************************</span><span class="comment">Function: GetPrime</span><span class="comment">Description: 生成 nPrime 個素數,并保存到容器中</span><span class="comment">Calls: 無</span><span class="comment">Called By: 無</span><span class="comment">Input: nPrime: 需要產生的素數個數</span><span class="comment">Output: arr[]: 存素數的數組</span><span class="comment">Return: 實際產生素數的個數</span><span class="comment">Others: 設計思路:對任何整數currentNumer而言,</span><span class="comment"> 如果它不能被小于它的開方的素數整除,</span><span class="comment"> 那么它也是素數。</span><span class="comment">*************************************************/</span></pre></div><p>我們首先建立正式工程 GetPrime ,然后建立測試工程 TestGetPrime 。<p><div align="center"><img src="rcunit_stepbystep_two_project.gif" alt="rcunit_stepbystep_two_project.gif"><p><strong>正式工程與測試工程</strong></p></div> <h2><a class="anchor" name="settingup_project">配置工程</a></h2>我們需要在測試工程 TestGetPrime 中加入 RCUnit 庫,具體操作為 Project | Settings , 在左邊的工程列表中選中 TestGetPrime ,在Settings for 下拉框中選中 Win32 Debug, 然后選擇 Link 屬性頁,在 Object/library modules 中加入 rcunitd.lib。 對于 Win32 Release 設置,加入 rcunit.lib 。<p><div align="center"><img src="rcunit_stepbystep_project_settings.gif" alt="rcunit_stepbystep_project_settings.gif"><p><strong>工程設置</strong></p></div> 你還需要添加編譯后執行事件,使得 IDE 編譯完成之后,自動執行 RCUnit 測試。 具體操作為 Project | Settings, 在左邊的工程列表中選中 TestGetPrime , 在Settings for 下拉框中選中 All Configurations,選擇 Post-build step 屬性頁, 添加測試工程生成文件全路徑到 Post-build command(s) 列表。 MSVC6 為方便工程設置,定義了一些特殊路徑宏。 宏為生成文件全路徑,所以你只需要在 Post-build command(s) 列表中加入 即可。<p><div align="center"><img src="rcunit_stepbystep_post_build.gif" alt="rcunit_stepbystep_post_build.gif"><p><strong>設置“編譯后事件”</strong></p></div> <h2><a class="anchor" name="run_all_tests">準備測試程序框架</a></h2>我們在 TestGetPrime 工程中添加一個 TestGetPrime.c 文件,用以編寫測試用例。 在文件中定義一個空測試集并添加測試用例,測試集和相應測試函數一般定義在同一個文件中。 <div class="fragment"><pre class="fragment"><a class="code" href="group__rcunit__write__test__suite.html#ga0">CUNIT_TEST_SUITE_BEGIN</a>(TestSample); <span class="comment">// 把測試用例注冊到這里</span><a class="code" href="group__rcunit__write__test__suite.html#ga4">CUNIT_TEST_SUITE_END</a>();</pre></div><p>在 main 文件中注冊這個測試集。 <div class="fragment"><pre class="fragment"><span class="preprocessor">#ifdef __cplusplus</span><span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {<span class="preprocessor">#endif</span><span class="preprocessor"></span><span class="preprocessor">#include <<a class="code" href="rcunit_8h.html">rcunit/rcunit.h</a>></span><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>* argv[]){ <a class="code" href="group__rcunit__registing__test__suite.html#ga0">CUNIT_ADD_TEST_SUITE</a>(TestSample); <a class="code" href="group__rcunit__running__test__case.html#ga0">CUNIT_RUN_TEST</a>(); <span class="keywordflow">return</span> <a class="code" href="group__rcunit__running__test__case.html#ga1">CUNIT_IS_PASSED</a>();}<span class="preprocessor">#ifdef __cplusplus</span><span class="preprocessor"></span>}<span class="preprocessor">#endif</span></pre></div><p>到此為止,你已經完成了所有的工程設置和測試程序框架的準備, 當你編譯 TestGetPrime 工程后,會自動執行生成的測試程序,并在 Build 窗口輸出測試信息。 之后你所需要做的事情,就是針對各功能函數,添加相應的測試用例。<h2><a class="anchor" name="implement_function">編寫功能函數</a></h2>在測試功能函數之前,我們首先要實現功能函數。<p>當然,其實我們更加推薦先寫測試用例、再編寫代碼、并交替進行的開發方式,即所謂“測試先行”或者“測試驅動開發”, 不過由于敘述麻煩,暫時假設我們先實現功能函數。<p>在 GetPrime 工程中添加一個新的文件 Prime.c ,用以編寫 GetPrime 函數。 (注意:不要把 GetPrime 函數和 main 函數寫在同一文件中。 我們需要把功能函數所在文件加入到測試工程中測試,如果功能函數所在文件中也存在 mian 函數,會因為測試工程中 有兩個 main 函數而導致錯誤。) GetPrime 函數需要在頭文件中聲明,測試工程在用到 GetPrime 函數之前,需要包含這個頭文件。<p>在前面的函數頭注釋中已經給出了詳細的功能需求,你要是有興趣可以自己實現這個函數,不過我們給出了一個實現,代碼如下:<p><div class="fragment"><pre class="fragment"><span class="keywordtype">int</span> GetPrime(<span class="keywordtype">int</span> arr[],<span class="keywordtype">int</span> nPrime){ <span class="keywordtype">int</span> count; <span class="comment">/*已檢測出是素數的數的個數*/</span> <span class="keywordtype">int</span> currentNumber; <span class="comment">/*當前要檢測是否素數的數*/</span> <span class="keywordtype">int</span> k; <span class="keywordflow">if</span>(arr == NULL) { <span class="keywordflow">return</span> 0; } <span class="keywordflow">else</span> <span class="keywordflow">if</span>(nPrime <= 0) { <span class="keywordflow">return</span> 0; } <span class="keywordflow">else</span> <span class="keywordflow">if</span>(nPrime == 1) { arr[0] = 2; <span class="keywordflow">return</span> 1; } <span class="keywordflow">else</span> { ; } arr[0] = 2; count = 1; currentNumber = 3; <span class="keywordflow">while</span>(count < nPrime) { k=0; <span class="keywordflow">while</span>(arr[k] * arr[k] <= currentNumber) { <span class="keywordflow">if</span>(currentNumber % arr[k] == 0) { <span class="comment">/*currentNumber是合數*/</span> currentNumber += 2; } <span class="keywordflow">else</span> { k++; } } <span class="comment">/*currentNumber是素數*/</span> arr[count++] = currentNumber; currentNumber += 2; } <span class="keywordflow">return</span> nPrime;}</pre></div><h2><a class="anchor" name="prepare_testcases">準備測試用例</a></h2>在寫測試函數之前,我們需要考慮我們針對那些情況測試,即設計測試用例。 測試不可能遍歷所有可能的情況,因此我們需要仔細地設計用例,讓測試用例覆蓋到各種典型情況即可。 在針對函數進行單元測試時,我們主要是根據函數參數及參數間的邏輯關系等設計測試用例。 函數 int GetPrime(int arr[],int nPrime) 有兩個參數。對于指針參數,有空指針和非空指針兩種情況; 對于第二個參數,希望得到的素數個數,有負數、零、正數三種情況。 以上幾種情況及部分條件組合情況,我們都需要在測試用例中覆蓋到。 另外,我們還需要考慮覆蓋到邊界情況等,例如 nPrime = 0。 關于測試用例的設計,沒有統一的方法或準則,只要做到覆蓋各種典型情況即可。<p>我們在此設計了以下幾個測試用例(只是舉例,并未達到完全覆蓋): <br>一般情況 nPrime = 10 預期返回 3 、arr[0] = 2, arr[1] = 3, arr[2] = 5 … <br>邊界情況 nPrime = 0 預期返回 0 <br>非法情況 nPrime = -2 預期返回 0 <br>臨界情況 nPrime = 1 預期返回 1 、arr[0] = 2 <br>非法情況 arr = NULL 預期返回 0<h2><a class="anchor" name="add_suite_and_case">添加測試集及測試用例</a></h2>RCUnit 采用測試集和測試用例的組織方式管理和執行測試用例。 一個測試集即一個測試用例分組,其中可以包含多個測試用例。 測試用例不能單獨存在,必須屬于一個測試集。<p>首先編寫測試函數: <div class="fragment"><pre class="fragment"><span class="comment">/* 測試普通的情況 */</span>CUNIT_DECL_TEST <span class="keywordtype">void</span> TestSample_NormalCase(){ <span class="keywordtype">int</span> arr[11] = {0}; <span class="keywordtype">int</span> nRet = GetPrime(arr, 10); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(10, nRet); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(2, arr[0]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(3, arr[1]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(5, arr[2]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(7, arr[3]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(11, arr[4]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(13, arr[5]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(17, arr[6]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(19, arr[7]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(23, arr[8]); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(29, arr[9]);}<span class="comment">/* 測試n = 0的情況 */</span>CUNIT_DECL_TEST <span class="keywordtype">void</span> TestSample_Zero(){ <span class="keywordtype">int</span> arr[5]; <span class="keywordtype">int</span> nRet = GetPrime(arr, 0); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(0, nRet);}<span class="comment">/* 測試n為負數的情況 */</span>CUNIT_DECL_TEST <span class="keywordtype">void</span> TestSample_Negative(){ <span class="keywordtype">int</span> arr[5]; <span class="keywordtype">int</span> nRet = GetPrime(arr, -2); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(0, nRet);}<span class="comment">/* 測試n = 1的情況 */</span>CUNIT_DECL_TEST <span class="keywordtype">void</span> TestSample_One(){ <span class="keywordtype">int</span> arr[5]; <span class="keywordtype">int</span> nRet = GetPrime(arr, 1); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(1, nRet); <a class="code" href="group__rcunit__making__assertion.html#ga0">CUNIT_ASSERT_EQUAL</a>(2, arr[0]);}<span class="comment">/* 測試空指針的情況 */</span>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -