</div>
<!-- Social -->
<div class="ibm-col-6-2 ibm-col-medium-6-4 ibm-col-small-6-2 dw-article-social">
<!-- Sharing links -->
<div id="dw-article-share-inline">
<div class="dw-article-sharelink-inline">
</div>
</div>
<!-- Number of comments and link to comments -->
</div>
</div>
<!-- Article Body -->
<h2 id="major1" class="ibm-h2">背景</h2><h3 id="listing1" class="ibm-h3">并行程序</h3><p>并行程序是指控制计算机系统中两个或多个分别包含一系列指令序列的操作同时执行的程序,是对处理机上多个操作、或者任务同时执行的一种“规划”。处理机在运行并行程序时将同时工作于同一程序的不同方面,同时控制和运行分别包含一系列指令的两个或多个操作。并行程序设计的主要目的是节省大型和复杂问题的解决时间。</p><p>并行程序设计技术的发展已有 20 多年的历史了,高性能并行计算机系统正在进入越来越多的应用领域。但是与硬件的发展相比,并行软件的发展则显得有些滞后,影响了硬件效率的发挥,限制了并行机系统的广泛应用,因此并行程序的开发与研究也越来越多深入到现在软件的开发过程中。相比较串行程序的开发,当前并行程序的开发与研究存在很多的困难,其中主要是因为缺乏有效的并行程序设计方法和工具,使得编写正确并行程序、理解并行程序的行为、调试和优化并行程序的性能都很困难。</p><h3 id="listing2" class="ibm-h3">单元测试</h3><p>单元测试是对程序代码单元进行函数级的测试,是完成对最小软件设计单元的验证工作。</p><p>单元测试贯穿于软件开发的整个过程中,对于保证软件质量的重要性不言而喻。作为一种白盒测试,单元测试很多时候是与开发同时进行的。关于单元测试的工具也很多,其中包含著名的 xUnit 系列。本文将涉及到的多线程单元测试工具就是从 Java 单元测试工具 JUnit 中扩展而来的。</p><h2 id="major2" class="ibm-h2">扩展 JUnit 实现多线程单元测试</h2><p>对于 Java 来说,JUnit 是备受开发人员喜爱的单元测试工具。它甚至还影响了其他语言的测试框架。这点,我们从繁多的 xUnit 框架就可以看出来。随着多核时代的到来,开发人员将需要进行越来越多的并行程序测试。得益于 JUnit 的可扩展性,我们可以使用 Annotation 让 JUnit 更好地支持并行测试。</p><p>得益于 JUnit 良好的可扩展性,扩展 JUnit 实现多线程单元测试这里主要是通过生成实现多线程测试过程中所需 Annotation 的定义并实现运行自定义测试逻辑来实现的。</p><p>关于扩展 JUnit 实现多线程单元测试,我们在另一篇文章《扩展 JUnit 测试并行程序》里有专门的介绍,请参见 <a href="#artrelatedtopics">参考资源</a>,下面我们将主要针对这一扩展说明如何在集成开发环境中创建和运行测试用例。</p><h2 id="major3" class="ibm-h2">在集成开发环境中安装并行单元测试插件</h2><p>在使用集成开发环境创建多线程的测试用例之前,首先需要在环境中安装扩展 JUnit 的插件,在本文中我们主要介绍名为 Unit Test for Multi-Thread 的扩展 JUnit 在集成开发环境 Eclipse 下的安装与使用。</p><p>Unit Test for Multi-Thread 是 IBM 多核软件开发工具 Multicore SDK 下开发的一款用于并行开发中构建多线程测试用例以此来对代码进行单元测试的插件,其是伴随 Multicore SDK 一起发布的,我们可以通过 eclipse 插件安装的方式来安装它。需要注意的是 Unit Test for Multi-Thread 目前仅支持 Eclipse3.5.x ,其安装过程简述如下:</p><p>首先运行开发工具 Eclipse3.5.x,在打开界面上点击‘Help’>‘Install New Software...’>‘Add... ’,然后会跳出一个‘Add Site’对话框,在其上面的‘Location’文本框里添加将要安装插件的地址:<a href="http://awwebx04.alphaworks.ibm.com/ettktechnologies/updates">http://awwebx04.alphaworks.ibm.com/ettktechnologies/updates</a>,点击‘OK’,等待加载,选择‘Multicore SDK’下的‘Unit Test for Multi-Thread’,点击‘Next’进行安装即可。</p><h2 id="major4" class="ibm-h2">在集成开发环境中创建测试用例</h2><p>下面将介绍在集成开发环境 Eclipse 中创建多线程测试用例的过程,首先需要安装上文提到的 Eclipse 插件 Unit Test For Multi-Thread。</p><p>具体将分为下面三个步骤来介绍:测试环境配置、测试用例生成向导、测试用例的运行和结果收集。</p><h3 id="listing3" class="ibm-h3">测试环境配置</h3><p>Unit Test for Multi-Thread 安装好之后,还需要一些简单的配置才能使用,具体步骤可以通过 Eclipse 环境里对项目的 Build Path 下添加 add libraries 设置完成,具体如下所示:</p><h3 id="listing4" class="ibm-h3">第一步 : 添加 JUnit 到项目 Build Path 中,使用版本为 JUnit 4.5 以上</h3><h5 id="fig1" class="ibm-h5">图 1:右键单击项目,在 Build Path 菜单下选择 Add Libraries</h5><img src="add_libs.png" class="ibm-downsize" alt="图 1:右键单击项目,在 Build Path 菜单下选择 Add Libraries" height="320" width="570"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N100BC');return false;" href="#N100BC">点击查看大图</a></p><h5 id="fig2" class="ibm-h5">图 2:选择 JUnit,单击 Next 进入下一页面</h5><img src="select_JUnit.png" class="ibm-downsize" alt="图 2:选择 JUnit,单击 Next 进入下一页面" height="267" width="609"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N100C6');return false;" href="#N100C6">点击查看大图</a></p><h5 id="fig3" class="ibm-h5">图 3:选定 JUnit4,单击完成</h5><img src="select_JUnit_4.png" class="ibm-downsize" alt="图 3:选定 JUnit4,单击完成" height="295" width="608"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N100D0');return false;" href="#N100D0">点击查看大图</a></p><h3 id="listing5" class="ibm-h3">第二步:类似地,添加 Unit Test for Multi-Thread library 到项目 Build Path 中</h3><h5 id="fig4" class="ibm-h5">图 4: 选定 Unit Test for Multi-Thread,单击 Next 完成添加过程</h5><img src="select_UTMT.png" class="ibm-downsize" alt="图 4: 选定 Unit Test for Multi-Thread,单击 Next 完成添加过程" height="267" width="608"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N100DE');return false;" href="#N100DE">点击查看大图</a></p><h5 id="fig5" class="ibm-h5">图 5:配置完成后的页面</h5><img src="add_final_view.png" class="ibm-downsize" alt="图 5:配置完成后的页面" height="174" width="500"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N100E8');return false;" href="#N100E8">点击查看大图</a></p><h3 id="listing6" class="ibm-h3">测试用例生成向导</h3><p>Unit Test for Multi-Thread 为用户提供了测试用例生成向导,通过此向导,用户可以很方便地构建自己的多线程测试用例,具体使用过程如下:</p><p>1. 在 Eclipse 中,选择 File -> New -> Others,选定图中所示:Unit Test for Multi-Thread, 双击进入下一个界面</p><h5 id="fig6" class="ibm-h5">图 6:测试用例生成向导界面</h5><img src="wizard.png" class="ibm-downsize" alt="Sample figure containing an image" height="550" width="570"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N100FA');return false;" href="#N100FA">点击查看大图</a></p><p>2. 将你需要测试的程序类名填入对应位置,图中例子类名是 demo.CoverageDemo。点击 next,进入下一界面</p><h5 id="fig7" class="ibm-h5">图 7: 使用生成测试用例面板创建新的测试用例</h5><img src="wizard_2.png" class="ibm-downsize" alt="Sample figure containing an image" height="491" width="570"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N10106');return false;" href="#N10106">点击查看大图</a></p><p>3. 在 Methods List 栏目下面选择需要进行单元测试的方法;Threaded 栏目下面确定是否使用多线程的方式进行测试,选中为生成多线程,不选则为生成单线程测试用例;在标题为 Thread Numbers for launching the Threaded methods 的文本框中可以设置测试将使用的线程数目列表,图中所示,该单元测试会分别用 1、2、4、8、16、32 和 64 个线程执行需要并行测试的方法。</p><h5 id="fig8" class="ibm-h5">图 8:选择需要进行多线程测试的方法和设定测试线程数</h5><img src="wizard_3.png" class="ibm-downsize" alt="Sample figure containing an image" height="488" width="570"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N10112');return false;" href="#N10112">点击查看大图</a></p><p>Unit Test for Multi-Thread 将根据设置向导自动生成测试用例的完整代码框架,用户可根据被测试代码直接在此框架下添加所需测试的内容,以此提高编写测试用例的效率。</p><h5 id="listing7" class="ibm-h5">自动生成的测试用例形式如下:</h5><span class="dw-code-nohighlight"><div class="ibm-syntax-container"><div><div id="highlighter_971355" class="syntaxhighlighter htmlscript"><table border="0" cellpadding="0" cellspacing="0" role="none"><tbody><tr><td class="gutter"><div class="line number1 index0 alt2">1</div><div class="line number2 index1 alt1">2</div><div class="line number3 index2 alt2">3</div><div class="line number4 index3 alt1">4</div><div class="line number5 index4 alt2">5</div><div class="line number6 index5 alt1">6</div><div class="line number7 index6 alt2">7</div><div class="line number8 index7 alt1">8</div><div class="line number9 index8 alt2">9</div><div class="line number10 index9 alt1">10</div><div class="line number11 index10 alt2">11</div><div class="line number12 index11 alt1">12</div><div class="line number13 index12 alt2">13</div><div class="line number14 index13 alt1">14</div><div class="line number15 index14 alt2">15</div><div class="line number16 index15 alt1">16</div><div class="line number17 index16 alt2">17</div><div class="line number18 index17 alt1">18</div><div class="line number19 index18 alt2">19</div><div class="line number20 index19 alt1">20</div><div class="line number21 index20 alt2">21</div><div class="line number22 index21 alt1">22</div><div class="line number23 index22 alt2">23</div><div class="line number24 index23 alt1">24</div><div class="line number25 index24 alt2">25</div><div class="line number26 index25 alt1">26</div><div class="line number27 index26 alt2">27</div><div class="line number28 index27 alt1">28</div><div class="line number29 index28 alt2">29</div><div class="line number30 index29 alt1">30</div><div class="line number31 index30 alt2">31</div><div class="line number32 index31 alt1">32</div><div class="line number33 index32 alt2">33</div><div class="line number34 index33 alt1">34</div><div class="line number35 index34 alt2">35</div><div class="line number36 index35 alt1">36</div><div class="line number37 index36 alt2">37</div><div class="line number38 index37 alt1">38</div><div class="line number39 index38 alt2">39</div><div class="line number40 index39 alt1">40</div><div class="line number41 index40 alt2">41</div><div class="line number42 index41 alt1">42</div><div class="line number43 index42 alt2">43</div></td><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="htmlscript plain">package test; </code></div><div class="line number2 index1 alt1"> </div><div class="line number3 index2 alt2"><code class="htmlscript plain">import static org.junit.Assert.*; </code></div><div class="line number4 index3 alt1"> </div><div class="line number5 index4 alt2"><code class="htmlscript plain">import org.amino.util.msdk.unit.Parallelized; </code></div><div class="line number6 index5 alt1"><code class="htmlscript plain">import org.amino.util.msdk.unit.annotation.CheckFor; </code></div><div class="line number7 index6 alt2"><code class="htmlscript plain">import org.amino.util.msdk.unit.annotation.InitFor; </code></div><div class="line number8 index7 alt1"><code class="htmlscript plain">import org.amino.util.msdk.unit.annotation.ParallelSetting; </code></div><div class="line number9 index8 alt2"><code class="htmlscript plain">import org.amino.util.msdk.unit.annotation.Threaded; </code></div><div class="line number10 index9 alt1"><code class="htmlscript plain">import org.junit.After; </code></div><div class="line number11 index10 alt2"><code class="htmlscript plain">import org.junit.AfterClass; </code></div><div class="line number12 index11 alt1"><code class="htmlscript plain">import org.junit.Before; </code></div><div class="line number13 index12 alt2"><code class="htmlscript plain">import org.junit.BeforeClass; </code></div><div class="line number14 index13 alt1"><code class="htmlscript plain">import org.junit.runner.RunWith; </code></div><div class="line number15 index14 alt2"> </div><div class="line number16 index15 alt1"><code class="htmlscript plain">@RunWith(Parallelized.class) </code></div><div class="line number17 index16 alt2"><code class="htmlscript plain">@ParallelSetting(threadNumber = { 1, 2, 4, 8, 16, 32, 64 }) </code></div><div class="line number18 index17 alt1"> </div><div class="line number19 index18 alt2"><code class="htmlscript plain">public class TestUnitExtensionSample1 { </code></div><div class="line number20 index19 alt1"> </div><div class="line number21 index20 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@BeforeClass </code></div><div class="line number22 index21 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public static void setUpBeforeClass() throws Exception {} </code></div><div class="line number23 index22 alt2"> </div><div class="line number24 index23 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@AfterClass </code></div><div class="line number25 index24 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public static void tearDownAfterClass() throws Exception {} </code></div><div class="line number26 index25 alt1"> </div><div class="line number27 index26 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@Before </code></div><div class="line number28 index27 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public void setUp() throws Exception {} </code></div><div class="line number29 index28 alt2"> </div><div class="line number30 index29 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@After </code></div><div class="line number31 index30 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public void tearDown() throws Exception {} </code></div><div class="line number32 index31 alt1"> </div><div class="line number33 index32 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@InitFor("testAdd") </code></div><div class="line number34 index33 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public void initfortestAdd(int threadNum){} </code></div><div class="line number35 index34 alt2"> </div><div class="line number36 index35 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@CheckFor("testAdd") </code></div><div class="line number37 index36 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public void checkfortestAdd(int threadNum){} </code></div><div class="line number38 index37 alt1"> </div><div class="line number39 index38 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">@Threaded </code></div><div class="line number40 index39 alt1"><code class="htmlscript spaces"> </code><code class="htmlscript plain">public void testAdd(int rank, int threadNum){ </code></div><div class="line number41 index40 alt2"><code class="htmlscript spaces"> </code><code class="htmlscript plain">} </code></div><div class="line number42 index41 alt1"> </div><div class="line number43 index42 alt2"><code class="htmlscript plain">}</code></div></div></td></tr></tbody></table></div></div></div></span><p>以上测试用例代码中各个 Annotation 的详细说明可以参考 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-junit-ext/">这里</a>。</p><h3 id="listing8" class="ibm-h3">测试用例的运行和结果收集</h3><p>Unit Test For Multi-Thread 从 JUnit 扩展而来,保留了 JUnit 运行和结果显示的方式,其运行方式和结果显示如下所示:</p><h5 id="fig9" class="ibm-h5">图 9:运行 Unit Test For Multi-Thread</h5><img src="run_testcase.png" class="ibm-downsize" alt="Sample figure containing an image" height="377" width="570"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N10131');return false;" href="#N10131">点击查看大图</a></p><p>和运行标准 JUnit 一样,运行 Unit Test for Multi-Thread 很简单,</p><h5 id="fig10" class="ibm-h5">图 10:测试结果无异常</h5><img src="result_noexception.png" class="ibm-downsize" alt="Sample figure containing an image" height="321" width="341"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N1013D');return false;" href="#N1013D">点击查看大图</a></p><p>测试通过时将会以绿色标识,</p><h5 id="fig11" class="ibm-h5">图 11:测试结果存存在 Errors 或 Failures</h5><img src="result_exception.png" class="ibm-downsize" alt="Sample figure containing an image" height="323" width="342"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N10149');return false;" href="#N10149">点击查看大图</a></p><p>测试没有完全通过时将会以红色警告提示,</p><h5 id="fig12" class="ibm-h5">图 12:测试报出的失败信息</h5><img src="result_exception_trace.png" class="ibm-downsize" alt="Sample figure containing an image" height="164" width="341"><p class="ibm-ind-link ibm-hide"><a class="ibm-popup-link" onclick="IBMCore.common.widget.overlay.show('N10155');return false;" href="#N10155">点击查看大图</a></p><p>并生成错误或失败报告给出,整体风格和标准 JUnit 一致,但是其具备独有的生成多线程的测试用例和单元测试的内容,对于熟悉 JUnit 的用户来说使用此来进行并行程序的单元测试将会很方便。</p><h2 id="major5" class="ibm-h2">结论</h2><p>随着多核处理器成为主流,并发程序越来越多的要求运用到软件开发和研究中,开发人员不可避免地需要开发和测试并行程序,本文介绍了一种在集成开发环境 Eclipse 中,创建符合用户要求的多线程单元测试用例的过程,这样开发者可以只关心测试本身的逻辑和结果,而不用去了解测试用例并行执行的琐碎细节,从而大大减少开发人员手工创建线程和同步来进行测试的繁琐工作,提高开发效率。</p><!--CMA ID: 494090--><!--Site ID: 10--><!--XSLT stylesheet used to transform this file: dw-document-html-8.0.xsl-->
<!-- Article Quiz -->
<!-- Article Resources -->
<div class="ibm-alternate-rule"><hr></div><h4 id="artdownload" class="ibm-h4">下载资源</h4><ul class="ibm-link-list"><li><a class="ibm-download-link" href="http://www.ibm.com/developerworks/apps/download/index.jsp?contentid=494090&filename=testMultiThread.zip&method=http&locale=zh_CN">本文中结果显示形式示例时用到的 Java 程序代码</a> (testMultiThread.zip | 10 KB)</li></ul><div class="ibm-alternate-rule"><hr></div>
<!-- Commenting -->
原文地址:https://www.ibm.com/developerworks/cn/java/j-lo-test-multithread/