<!DOCTYPE html>
<html lang="en"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.7.1 --> <title>使用 IAR Embedded Workbench IDE 做单元测试 | Bingwhispers</title> <meta name="generator" content="Jekyll v3.8.7" /> <meta property="og:title" content="使用 IAR Embedded Workbench IDE 做单元测试" /> <meta property="og:locale" content="en_US" /> <meta name="description" content="一、欢迎 很高兴你能看到这篇文章,我将在这篇文章中介绍如何使用 IAR 做单元测试。" /> <meta property="og:description" content="一、欢迎 很高兴你能看到这篇文章,我将在这篇文章中介绍如何使用 IAR 做单元测试。" /> <link rel="canonical" href="/2019/12/20/iar-unit-test" /> <meta property="og:url" content="/2019/12/20/iar-unit-test" /> <meta property="og:site_name" content="Bingwhispers" /> <meta property="og:type" content="article" /> <meta property="article:published_time" content="2019-12-20T20:00:00+08:00" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="使用 IAR Embedded Workbench IDE 做单元测试" /> <script type="application/ld+json"> {"@type":"BlogPosting","url":"/2019/12/20/iar-unit-test","headline":"使用 IAR Embedded Workbench IDE 做单元测试","dateModified":"2019-12-20T20:00:00+08:00","datePublished":"2019-12-20T20:00:00+08:00","mainEntityOfPage":{"@type":"WebPage","@id":"/2019/12/20/iar-unit-test"},"description":"一、欢迎 很高兴你能看到这篇文章,我将在这篇文章中介绍如何使用 IAR 做单元测试。","@context":"https://schema.org"}</script> <!-- End Jekyll SEO tag --> <link rel="stylesheet" href="/assets/main.css"><link type="application/atom+xml" rel="alternate" href="/feed.xml" title="Bingwhispers" /></head> <body><header class="site-header" role="banner"> <div class="wrapper"><a class="site-title" rel="author" href="/">Bingwhispers</a><nav class="site-nav"> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger"> <span class="menu-icon"> <svg viewBox="0 0 18 15" width="18px" height="15px"> <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/> </svg> </span> </label> <div class="trigger"><a class="page-link" href="/about/">About</a></div> </nav></div> </header> <main class="page-content" aria-label="Content"> <div class="wrapper"> <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting"> <header class="post-header"> <h1 class="post-title p-name" itemprop="name headline">使用 IAR Embedded Workbench IDE 做单元测试</h1> <p class="post-meta"> <time class="dt-published" datetime="2019-12-20T20:00:00+08:00" itemprop="datePublished">2019年12月20日 </time></p> </header> <div class="post-content e-content" itemprop="articleBody"> <h1 id="一欢迎">一、欢迎</h1> <p> 很高兴你能看到这篇文章,我将在这篇文章中介绍如何使用 IAR 做单元测试。</p> <p> 大部分嵌入式开发者一般都按照“编码——编译——运行——调试”的循环完成开发工作,这很可能只会用到 IAR Embedded Workbench IDE(以下简称“IAR”)极少一部分(同时也是最常用的)功能。实际上,IAR 为开发者提供了很多丰富的功能,使我们能做更多事情。</p> <p> IAR 集成了“IAR C-SPY Debugger”,IAR C-SPY Debugger 里面又提供了“C-SPY Simulator”功能。它通过软件完整地模拟了目标处理器,使目标处理器的代码可以脱离硬件环境运行。这样就可以随时做单元测试而不必等待硬件环境就绪。对单元测试而言,这是一个极大的便利。顺便提一下,我使用的 IAR 版本是 IAR Embedded Workbench for ARM 8.32.3.20228。</p> <h1 id="二创建工程">二、创建工程</h1> <p> 创建一个名为“test”的 C 语言模板工程,然后打开工程选项菜单,在”General Option”选项中的“Library Configuration”选项卡中,按下图所示配置。</p> <p><img src="/assets/iar-ut/semihost.png" alt="debugger" /></p> <p> Semihosting 是 ARM 处理器独有的特性。它能使 ARM 目标机通过调试器和主机通讯,或者使用主机的I/O设备。此功能可以单元测试程序使用 printf 等方法输出测试信息。非常方便。其他类型的处理器也会有相应的机制完成此任务。</p> <p> 接下来,在“Debugger”选项中将调试驱动选为“Simulator”。如下图所示:</p> <p><img src="/assets/iar-ut/debugger.png" alt="debugger" /></p> <p> 打开 main.c 文件,修改其中的代码。</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/*main.c*/ #include <stdio.h> int main() { printf("Hello World\n"); return 0; } </code></pre></div></div> <p> 这时候可以按“Ctrl+d”启动调试。进入调试界面后,选择“View”菜单的“Terminal I/O”,打开终端输入输出窗体。按“F5”继续运行代码,可以看到“Hello World”输出信息。这样,一个简单的工程就创建完成了。</p> <h1 id="三添加单元测试框架">三、添加单元测试框架</h1> <p> C 语言的单元测试框架很多,在这里不一一详述。我选择了Unity,项目地址见文末参考资料。下载“Unity-2.5.0.tar.gz”并解压。分别从“Unity-2.5.0/src”、“Unity-2.5.0/extras/fixture/src”和“Unity-2.5.0/extras/memory/src”中找到下列文件,并复制到 test 的工程目录中。</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>unity.c unity.h unity_fixture.c unity_fixture.h unity_fixture_internals.h unity_internals.h unity_memory.c unity_memory.h </code></pre></div></div> <p> 在 test 工程中添加以上的所有“.c”源文件,然后新建一个“foo.c”源文件作为待测文件。在 foo.c 中添加如下内容:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/*foo.c*/ int add(int a, int b) { return a + b; } </code></pre></div></div> <p> 再次修改 main.c,使用 Unity 框架,为 add 函数添加两个测试用例。</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/*main.c*/ #include <stdio.h> #include "unity_fixture.h" extern int add(int a, int b); static void run_all_test(void); int main() { const char *arg = "test"; return UnityMain(1, &arg, run_all_test); } void run_all_test(void) { RUN_TEST_GROUP(add); } TEST_GROUP(add); TEST_SETUP(add) { } TEST_TEAR_DOWN(add) { } TEST(add, case1) { TEST_ASSERT_EQUAL(2, add(1, 1)); } TEST(add, case2) { TEST_ASSERT_EQUAL(-3, add(-1, -2)); } TEST_GROUP_RUNNER(add) { RUN_TEST_CASE(add, case1); RUN_TEST_CASE(add, case2); } </code></pre></div></div> <p> 运行程序后,可以看到终端输出信息。这两个测试用例已经全部通过了。</p> <p> 如何设计测试用例不在本文的讨论范围内,感兴趣的读者可以阅读 James W. Grenning 著的<a href="https://www.amazon.com/Driven-Development-Embedded-Pragmatic-Programmers-ebook/dp/B01D3TWF5M">《Test Driven Development for Embedded C》</a>。这本书从各个方面讲述了在嵌入式领域如何进行测试。</p> <h1 id="四拓展">四、拓展</h1> <p> 在 test/settings 路径下,有这么几个文件:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>test.Debug.cspy.bat test.Debug.cspy.ps1 test.Release.cspy.bat test.Release.cspy.ps1 </code></pre></div></div> <p> Debug 和 release 表示配置,bat 表示 Windows 批处理程序,ps1 表示 Powershell 程序。在终端执行这些脚本可以调用 IAR C-SPY Debugger 运行程序,并且将结果输出至终端。这有助于自动化运行单元测试,我们以后还会详细讨论。</p> <p> IAR 还提供了在终端中构建项目的工具,更多内容请参考<a href="https://www.iar.com/support/tech-notes/general/build-from-the-command-line/">这里</a>。</p> <h1 id="五参考资料">五、参考资料</h1> <ul> <li>https://github.com/ThrowTheSwitch/Unity</li> <li>http://www.keil.com/support/man/docs/armcc/armcc_pge1358787046598.htm</li> </ul> </div><a class="u-url" href="/2019/12/20/iar-unit-test" hidden></a> </article> </div> </main><footer class="site-footer h-card"> <data class="u-url" href="/"></data> <div class="wrapper"> <h2 class="footer-heading">Bingwhispers</h2> <div class="footer-col-wrapper"> <div class="footer-col footer-col-1"> <ul class="contact-list"> <li class="p-name">Bingwhispers</li><li><a class="u-email" href="mailto:zblinuxfun@gmail.com">zblinuxfun@gmail.com</a></li></ul> </div> <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/cyril3"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#github"></use></svg> <span class="username">cyril3</span></a></li><li><a href="https://www.twitter.com/zblinuxfun"><svg class="svg-icon"><use xlink:href="/assets/minima-social-icons.svg#twitter"></use></svg> <span class="username">zblinuxfun</span></a></li></ul> </div> <div class="footer-col footer-col-3"> <p>Hi there!</p> </div> </div> </div> </footer> </body> </html>