📄 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 + -