<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[小宇飞刀的BLOG]]></title> 
<link>http://vir.jxstnu.edu.cn/xieyunc/index.php</link> 
<description><![CDATA[小宇的网上家园 飞刀的技术博客]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[小宇飞刀的BLOG]]></copyright>
<item>
<link>http://vir.jxstnu.edu.cn/xieyunc/read.php?203</link>
<title><![CDATA[使用SOAPUI对WEBSERVICE进行性能测试]]></title> 
<author>xieyunc &lt;xieyunc@jxstnu.cn&gt;</author>
<category><![CDATA[软件工程]]></category>
<pubDate>Sun, 04 May 2008 23:16:20 +0000</pubDate> 
<guid>http://vir.jxstnu.edu.cn/xieyunc/read.php?203</guid> 
<description>
<![CDATA[ 
	　　性能测试一般使用loadrunner，或者自己写的调用客户端进行测试。loadrunner是全面的性能测试工具，对一般开发人员来说太重，并且需要 license。自己写调用的客户端则测试的统计数据也需要写程序处理，比较麻烦。这里推荐使用soapui，SOAPUI可以直接根据WSDL生成 SOAP数据包，手工填入参数后可以直接进行性能测试。<br/><br/>1、下载soapui的最新安装包，目前的最新版本是soapui-1.7.5，SOAPUI里的TESTSUITE包含一些列的TESTCASE，TESTCASE由若干的测试步骤组成。每个TESTCASE包含TESTSTEP和LOADTEST。<br/><br/>2、解包运行soapui.bat<br/>3、创建File--new WSDL Project，输入WSDL的HTTP URL地址<br/><a href="http://www.soapui.org/gettingstarted/images/getting_started_1.gif" target="_blank"><img src="http://www.soapui.org/gettingstarted/images/getting_started_1.gif" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>4、SOAPUI产生该WSDL的HTTPBinding，里面有WSDL定义的业务方法<br/><a href="http://www.soapui.org/gettingstarted/images/getting_started_3.gif" target="_blank"><img src="http://www.soapui.org/gettingstarted/images/getting_started_3.gif" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>5、每个业务方法下有自动产生的SOAP数据包的文本，编辑数据后可以直接发送软件<br/><a href="http://www.soapui.org/gettingstarted/images/getting_started_7.gif" target="_blank"><img src="http://www.soapui.org/gettingstarted/images/getting_started_7.gif" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>6、性能测试，在TESTCASE的TEST STEP中编辑测试步骤，在LoadTest中填入性能测试的参数，可以直接进行性能测试<br/><a href="http://www.soapui.org/gettingstarted/images/getting_started_loadtest_2.gif" target="_blank"><img src="http://www.soapui.org/gettingstarted/images/getting_started_loadtest_2.gif" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/>7、使用property transfer功能生成复杂的性能测试步骤，假设一个WSDL定义了两个方法，第一个测试步骤调用了第一个方法，返回authorid，作为第二个方法的输入参数（第二个步骤）。<br/><br/>7.1在第一个测试步骤和第二个测试步骤之间添加一个property transfer的步骤，选择transfer的源是第一个方法的Response对象。填写xpath将该属性从Response中选择出来<br/><br/>7.2选择transfer的目的地是第二个方法的request对象。填写xpath将该属性从request中选择出来<br/><br/>7.3属性影射从souce影射到dest<br/><br/>8、更复杂的功能可以由goovy实现<br/>Tags - <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=soapui" rel="tag">soapui</a> , <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=webservice" rel="tag">webservice</a> , <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=%25E6%2580%25A7%25E8%2583%25BD%25E6%25B5%258B%25E8%25AF%2595" rel="tag">性能测试</a>
]]>
</description>
</item><item>
<link>http://vir.jxstnu.edu.cn/xieyunc/read.php?202</link>
<title><![CDATA[soapUI快速入门]]></title> 
<author>xieyunc &lt;xieyunc@jxstnu.cn&gt;</author>
<category><![CDATA[软件工程]]></category>
<pubDate>Sun, 04 May 2008 23:07:52 +0000</pubDate> 
<guid>http://vir.jxstnu.edu.cn/xieyunc/read.php?202</guid> 
<description>
<![CDATA[ 
	　　本文指导你如何根据请求和测试用例来创建你的第一个soapUI工程。文中例子主要用到amazon.com提供的web服务。<br/>soapUI入门非常容易，但要想更深入的掌握soapUI的功能，还需要对下面的概念和技术有较好的了解：<br/><strong>WSDL</strong> – 基本概念（服务、端口、绑定、端口类型），相关的xml-schema<br/><strong>SOAP</strong> – 基本概念，相关的WSDL（绑定、等等），不同的编码类型（soap-encoded/literal）和消息类型 （document/rpc）<br/><strong>XML与XML相关的技术 </strong>– Xpath、XML Schema、命名空间、等等<br/>可以在W3C找到相关的规范；在W3Schools和 zvon.org找到相关的教程。<br/><br/><strong>安装、运行soapUI</strong><br/>根据下面的步骤来安装、运行soapUI：<br/>从站点top page，通过Java WebStart可以在线安装最新的版本<br/>从站点sourceforge，下载安装soapUI的Windows版本，该版本包括了需要的Java运行环境（JRE1.5）。如果你不确定你的系统已经安装了合适的JRE，或者你想有开始菜单并且以后可以卸载，可以用该版本安装<br/>从站点sourceforge，下载二进制发布物（例如：”soapui-1.7.5-bin.zip”），手工解压缩，运行bin目录下面的soapui.bat或者soapui.sh脚本（你的系统需要安装好java环境）<br/>无论上面的那种安装方式，soapUI将会以一个空的工作空间开始。<br/><br/><strong>创建、导入工程</strong><br/><br/>安装并运行soapUI之后，你就可以创建第一个soapUI工程了。<br/>右击左侧导航面板中的工作空间节点，选择”New WSDL Project”<br/>在工程被保存前，应该填写工程名字和相应的本地WSDL文件<br/>上面的内容填写好之后，将会帮你在工作空间创建一个空的工程<br/>如果不是通过在线方式安装的，在下载文件的根目录有个例子工程；选择”Import Project”，找到sample-soapui-project.xml。<br/>可以从用户指南获得更多关于工程的内容。<br/><br/><strong>工程添加Web服务</strong><br/><br/>现在可以为工程增加一个接口（WebService PortTypes）。<br/>右击工程节点，选择” Add WSDL from URL”<br/>输入WSDL接口的url：<br/><a href="http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl" target="_blank">http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl</a><br/><br/>增加amazon的Web服务，选择”OK”按钮<br/>soapUI会提示你是否为每个操作创建一个默认的请求，通常选择”Yes”按钮<br/>soapUI为amazon的端口类型” AWSECommerceServicePortType”创建了一个SOAP/Http绑定，并且为每一个操作创建了一个节点。<br/><br/>可以从用户指南获得更多关于接口的内容。<br/><br/><strong>操作请求</strong><br/><br/>　　上面操作已经增加了amazon Web服务，接下来可以执行请求了。在上面增加接口的时候，已经根据WSDL的Schema定义为每一个操作创建了默认请求。<br/><br/>展开接口下面的任何一个操作节点，能够看到创建的”Request&nbsp;&nbsp;1”节点<br/>双击请求节点，在soapUI的右侧会出现请求编辑器（参照下图）<br/>请求编辑器分为三部分<br/><br/>Ø&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 顶部的工具栏，包含一组请求相关的动作、操作<br/><br/>Ø&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 左边是请求区域<br/><br/>Ø&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 右边是响应区域<br/><br/>　　soapUI默认生成的请求中，”?”表示需要被替换的内容。根据需要，可以替换或者删除掉这些值。通过按下工具栏最左边的按钮（绿色箭头）来发送一个请求<br/>请求会在后台执行，响应内容会出现在编辑器的右边<br/><br/>　　可以从用户指南获得更多关于请求的内容。
]]>
</description>
</item><item>
<link>http://vir.jxstnu.edu.cn/xieyunc/read.php?36</link>
<title><![CDATA[SVN的Local方式：个人源码管理的好办法]]></title> 
<author>xieyunc &lt;xieyunc@jxstnu.cn&gt;</author>
<category><![CDATA[软件工程]]></category>
<pubDate>Tue, 02 May 2006 01:53:43 +0000</pubDate> 
<guid>http://vir.jxstnu.edu.cn/xieyunc/read.php?36</guid> 
<description>
<![CDATA[ 
	<span> &nbsp;<p align="center"><strong><span style="font-size: large">SVN的Local方式：个人源码管理的好办法</span></strong> </p><div><p><span style="font-weight: bold">SVN、Local方式、个人源码管理</span> </p><p>今天在QQ群里，有人在打听Delphi的VSS插件，于是被我B4了一番。正好我最近试用了SVN，感觉很不错，于是在群里强力推荐，以致于几乎被认为是SVN的托儿。-_-&#124;&#124;&#124;</p><p>事实上SVN的确是我用过的最好的源码管理工具，虽然我用过的这类工具并不多，只有VSS、CVS和SVN，其它像PVCS、 TeamSource、ClearCase之类的只有耳闻，因为它们都是商业产品，并且通常用于管理大型的项目，没有机会试用，所以也不知道它们如何。 VSS是我四年前在公司里用过的最早的一款源码管理工具，不过它实在是太一般了，而且也是商业产品。所以除了公司里工作需要，我自己是不用的。从那公司出来以后，我试用了CVS，这才开始对自己的源码进行管理。作为OSS圈里元老级的源码管理工具，CVS有多强我不用再多说。但是现在SVN这颗新星已经渐渐要盖过CVS的光芒了，可见SVN是有自己杀手锏的。还有一点很重要的就是：它也是一个开源免费的软件。</p><p><span style="font-weight: bold">SVN</span>全名Subversion。SVN与CVS一样，是一个跨平台的软件，支持大多数常见的操作系统。本文只讨论Windows的情况。其官方网站是：<a href="http://subversion.tigris.org/"><a href="http://subversion.tigris.org" target="_blank">http://subversion.tigris.org</a></a>(tigris是一个和sourceforge类似的开源网站，与sf不同的是，sf提供的CVS服务，而tigris提供的是SVN服务)。</p><p>在介绍SVN的应用前，先讨论一下源码管理的一个重要的基本概念：<span style="font-style: italic">Repository</span>。Repository 就是源码的集中存放处，所有修改后提交的源码就是保存在这里，并在其中记录所有的修改版本，分支版本，版本合并，以及并发修改处理等。传统的VSS或 CVS都是采用类似C/S的应用方式，有一个独立的服务端来做这些工作。而SVN则要灵活得多，它支持三种方式：<span style="font-style: italic">独立服务器方式</span>、<span style="font-style: italic">Web服务器方式</span>（这是CVS所没有的）和本文将要着重讨论的<span style="font-weight: bold">Local方式</span>。</p><p>回到主题上。<span style="font-weight: bold">个人源码管理</span>是我自己提的一个概念，以区别于团队开发的源码管理。本来像VSS、CVS、SVN这样的工具最主要的功能是用于团队开发时用的，用于处理源码修改的版本控制和并发修改冲突。但对于个人开发来说，就不存在并发修改冲突的问题了。但个人开发又存在一些新的问题：一般个人没有条件搭一个独立的服务器来做Repository，所以实际上即使是用了CVS一类，也是服务端客户端在一台机器上，而且也不需要用户权限管理这样的功能。但有时又需要在不同的机器间拷贝源码作开发，这又带来版本混乱的潜在风险。而SVN的Local方式可以说是最好的解决方案。</p><p>我现在的用法就是：在U盘里建立Repository，然后在每台机器上都装了SVN，这样我就不需要一台单独的Repository服务器，只要在任一台机器上把U盘插上即具备了完整的版本控制功能。<br /> </p><p><span style="font-weight: bold">SVN的安装和使用</span>。</p><p>因为本文只讨论Windows下的Local方式，所以不需要独立服务器或Web服务器。SVN的客户端和CVS一样，也是命令行方式工作。但在Windows平台下，我们有还别的选择，这就是易用性很好的一个实现：<span style="font-weight: bold">TortoiseSVN</span>（注意：这是一个独立于SVN的项目，类似于WinCVS与CVS的关系）。其官方网站是：<a href="http://www.tortoisesvn.org/"><a href="http://www.tortoisesvn.org" target="_blank">http://www.tortoisesvn.org</a></a>，下载其安装程序：<a href="http://tortoisesvn.tigris.org/download.html">TortoiseSVN-1.1.3-UNICODE_svn-1.1.3.msi</a>（这个文件名是指NT/2k/XP版的）。这个集成发布包中包含了Local应用所需要的全部内容。如果想要中文版，还可以下载这个中文语言包：<a href="http://tortoisesvn.berlios.de/l10n/">LanguagePack_1.1.3_zh_CN.exe</a>（这是简体中文包，BTW：从进度上看，繁体中文的完成度还要高些:P）。至于其它的如独立服务器方式，Web服务器方式，命令行方式，Python支持等，都要相应的安装包提供，可自行参考SVN网站说明下载安装。</p><p>安装的过程非常简单，只是安装完成后必须重启一下，因为它要集成到Windows的资源管理器中。<span style="color: #808080; text-decoration: line-through">这也可以算是SVN的又一个大优点</span>（多谢mikeshi指出：CVS也有一个TortoiseCVS，这不算是SVN的优点），虽然CVS也有一个WinCVS不错，但是它毕竟是一个额外的客户端，不如TortoiseSVN这么方便。TortoiseSVN装好后，只要在资源管理器中任何一个文件夹中点右键，即可出现如下图所示的菜单（我打了中文包，所以显示是中文，可以在<span style="text-decoration: underline">Settings</span>中选择任何一种已经安装的语言包）：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_01.png" border="0" width="317" height="268" /><p>第一步：建立Local Repository</p><p>假设现在要开始一个项目，叫做Project1。先在U盘（假设为U:）建立一个文件夹：u:&#92;svn&#92;project1。然后在这个文件夹上点右键，选择：<span style="text-decoration: underline">TortoiseSVN&#124;在此创建文件库</span>。有两种方式供选择，如下图：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_02.png" border="0" width="285" height="171" /><p>Berkeley数据库和本地文件系统。本地文件系统方式有点类似于CVS，但实现方式上有所不同。Berkeley数据库据说是目前最好的嵌入式数据库解决方案，TortoiseSVN默认选择BDB方式，推荐。确定创建后稍等一会即会弹出一个提示窗，说明文件库创建成功。</p><p>第二步：创建工作文件夹</p><p>在本地硬盘（如D盘）创建一个工作文件夹：d:&#92;working&#92;project1。然后在这个文件夹上点右键，选择：<span style="text-decoration: underline">SVN取出</span>。显示如下对话框：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_03.png" border="0" width="456" height="292" /><p>其中唯一需要指定的就是文件库URL，Local方式是使用file协议。确定后显示如下对话框：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_04.png" border="0" width="554" height="274" /><p>点确定后完成创建工作，在文件夹中看到一个隐藏的文件夹：.svn。其中记录了工作文件夹的一些必要信息，功能与CVS的CVS文件夹一样。一个SVN的工作文件夹的图标上将会多了一个绿色的勾，所有被加入Respository的内容都会在图标上加上这样的绿勾，如图：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_09.png" border="0" width="50" height="59" /><p>第三步：开始写程序</p><p>现在可以在此工作目录中创建源程序文件或文件夹。在工作文件夹中的任何文件或文件夹（除了.svn文件夹）的右键菜单上都会增加一些项目，下图分别为<span style="font-style: italic">工作文件夹</span>、<span style="font-style: italic">工作文件夹下的子文件夹</span>、<span style="font-style: italic">工作文件夹中的文件</span>、<span style="font-style: italic">已经提交的文件</span>的右键菜单内容：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_05.png" border="0" width="305" height="432" /><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_06.png" border="0" width="145" height="199" /><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_07.png" border="0" width="132" height="135" /><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_08.png" border="0" width="128" height="321" /><p>从最左边的菜单和最右边的菜单上可以看到，SVN/TortoiseSVN支持了CVS的几乎所有功能，还增加了一些很实用的功能（比如文件/文件夹的重命名，在这CVS里是最让人头疼的问题之一）。这又是SVN的大优点。</p><p>如果你的源程序原来就存在，可以立即导入到Repository里：在你原来的源程序文件夹上点右键，选择<span style="text-decoration: underline">TortoiseSVN&#124;导入</span>。即可。不过要注意：最好先在<span style="text-decoration: underline">TortoiseSVN&#124;设置</span>里设定排除/忽略样式（可以设置文件夹或文件名，支持通配符，区分大小写！！！），或是先删除不必要导入的文件。然后再<span style="text-decoration: underline">取出</span>（Checkout）到工作目录即可。</p><p>第四步：将写好的程序提交到Repository</p><p>选择所有要加入的文件和文件夹，然后点<span style="text-decoration: underline">TortoiseSVN&#124;加入</span>。将显示如下对话框（以将本文提交为例）：</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_10.png" border="0" width="374" height="277" /><p>把它们加入Repository，确定后它的图标上将显示一个&ldquo;+&rdquo;号，表示这个文件已经加入，但还未提交。再在当前文件夹上点右键，选择<span style="text-decoration: underline">SVN提交</span>即可。将显示如下对话框（提交本文，其中的Repository是我实际使用的）</p><img src="http://borland.mblogger.cn/images/borland.mblogger.cn/raptor/855/o_svn01_11.png" border="0" width="458" height="480" /><p>成功提交后，它的图标上也将显示一个前面所示的那样的绿勾。</p><p>第五步：日常使用</p><p>无非是重复前面的<span style="text-decoration: underline">加入/提交</span>等操作。如果在其它机器上使用，则需要重新创建工作目录，并<span style="text-decoration: underline">取出</span>（Checkout）Repository中的源码。如果同时在多台机器上使用，则需要使用<span style="text-decoration: underline">SVN更新</span>功能来将此工作文件夹中的内容更新为Repository中的相应版本。</p><p>更多的功能请参考联机帮助及网站提供的其它文档资料。<br /> </p><p>最后祝大家都能体会到SVN所带来的方便和愉快。</p></div></span><br/>Tags - <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=svn" rel="tag">svn</a> , <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=subversion" rel="tag">subversion</a> , <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=tortoisesvn" rel="tag">tortoisesvn</a>
]]>
</description>
</item><item>
<link>http://vir.jxstnu.edu.cn/xieyunc/read.php?37</link>
<title><![CDATA[敏捷软件开发]]></title> 
<author>xieyunc &lt;xieyunc@jxstnu.cn&gt;</author>
<category><![CDATA[软件工程]]></category>
<pubDate>Tue, 18 Apr 2006 01:55:43 +0000</pubDate> 
<guid>http://vir.jxstnu.edu.cn/xieyunc/read.php?37</guid> 
<description>
<![CDATA[ 
	作为三篇系列文章的第一篇，我们将带你了解敏捷软件开发的重要做法——如何使用它们、你可能会碰到什么样的问题，以及你将从它们那里获得什么。<br/><br/>敏捷软件开发不是一个具体的过程，而是一个涵盖性术语（umbrella term），用于概括具有类似基础的方式和方法。这些方法，其中包括极限编程（Extreme Programming）、动态系统开发方法（Dynamic System Development Method）、SCRUM、Crystal和Lean等，都着眼于快速交付高质量的工作软件，并做到客户满意。<br/><br/>尽管构成这个敏捷开发过程的每种方法都具有类似的目标，但是它们实现这个目标的做法（practice）却不尽相同。我们把在自己完成所有过程中经历过的最佳做法集中到了本系列的文章里。<br/><br/>下面的图表基本勾画出了我们提炼出来的这些敏捷开发最佳做法。最中间的圆环代表一对程序员日常工作的做法。紧接着的中间一个圆环表示开发人员小组使用的做法。最外面的一个圆环是项目所涉及的所有人的做法——客户、开发人员、测试人员、业务分析师等等。<br/><br/>这些圆环里的所有做法都直接与四个角上显示的敏捷开发的核心价值相关：沟通（Communication）、反馈（Feedback）、勇气（Courage）和简单（Simplicity）。也就是说，每个做法都给予我们一条实现敏捷开发价值并让它们成为该过程一部分的具体方法。<br/><br/> <br/><br/>在理想状况下，如果决定采用敏捷软件开发的方法，你就应该在一个经过管理层许可的敏捷开发实验项目里尝试所有的作法。这是掌握敏捷开发的最好方法之一，因为这样能保证得到支持，为你的努力提供更多的回报，帮助捕捉学习到的东西，这样你才能让敏捷开发过程来适应你独特的环境。<br/><br/>然而，这并不总是可行的，所以有的时候最好采用步步为营的方法。在这种情况下，我们建议从最里面的圆环向外面的圆环推进。也就是从开发人员实践开始，然后是小组这一层次的做法，最后再融入“统一小组（one team）”的概念。<br/><br/>为技术优势设个限——开发人员做法<br/>技术优势是敏捷开发过程的核心。为了让其他的做法真正生效，我们必须在开发人员中进行技术优势的培训。从表面上看，技术优势可能看起来并不是核心优先对象，但是如果把我们注意力都放在上面，它将确保我们编写出不同寻常的优秀代码。这反过来同样会给予公司、客户，以及用户对软件和对我们交付能力的信心。<br/><br/>开发人员做法（developer practice）是我们推动技术优势的切实可行的方法。即使是独立完成，而没有其他敏捷开发做法的介入，开发人员做法也能够给你的软件带来巨大的收益。<br/><br/>开发人员做法可以被分解为四个做法（如果你把实际的编写代码的过程加上去就是五个做法）。它们分别是测试－编码－重整循环（Test-Code-Refactor cycle）、配对编程（Pair Programming）和简单设计（Simple Design）等。<br/><br/>测试－编码－重整（TCR）循环——第一步<br/>由测试驱动的开发和重整常常被当作是各自独立做法，但是它们事实上是TCR循环的一部分。要建立我们正在寻求的紧密反馈循环，我们就需要把它们放在一起。<br/><br/>我们在这里的目标有两层：测试让我们对代码质量的充满信心，并能表明我们加入新代码的时候没有破坏任何东西；重整和测试有助于让代码变成我们就代码实际在做什么而进行沟通的最真实形式——任何人都应该可以看到它，并知道什么是什么。<br/><br/>由测试驱动的开发（TDD）是一个循环，它从测试失败开始，然后是编写足够的代码通过测试，再是重整代码，使得代码在实现系统当前功能的条件下尽可能地简单。<br/><br/>测试－编码－重整循环非常短暂——也就几分钟。如果超出这个时间范围那就意味着测试的级别过高，有可能加入了未经测试的实现代码。<br/><br/>在本文的开始部分，我们不会举出TDD的例子，有关的内容会在后面2, 3, 4详细讨论。在这里，从整体上把握并把重点放在TCR循环更有趣的方面上会更加有用。<br/><br/>就同任何极限编程／敏捷开发项目一样，要做的第一个素材（story）是一个经过简化的应用程序，用来完整地说明程序的功能。在本文里，这样的应用程序是一个二十一点纸牌游戏。在经过简化的第一个素材里，只有一个玩家外加一个发牌人，每个玩家只会得到两张牌，获胜者是两张牌发完后点数最大的人。<br/><br/>素材／要求<br/>一个简单的二十一点纸牌游戏<br/><br/>玩家下注 <br/>给玩家和发牌人每人两张牌 <br/>给获胜者支付奖金（玩家获胜的机会为2:1） <br/>验收测试<br/>要知道我们的素材什么时候完成就需要经过一系列验收测试。我们这个简单游戏的验收测试如下：<br/><br/>玩家获胜<br/>发牌人获胜<br/>平局<br/><br/>玩家赌注总额＝100<br/>玩家赌注总额＝100<br/>玩家赌注总额＝100<br/><br/>发牌人赌注总额＝1000<br/>发牌人赌注总额＝1000<br/>发牌人赌注总额＝1000<br/><br/>玩家下注10<br/>玩家下注10<br/>玩家下注10<br/><br/>玩家发到10 & 9<br/>玩家发到8 & 9<br/>玩家发到8 & 9<br/><br/>发牌人发到8 & 9<br/>发牌人发到10 & 9<br/>发牌人发到8 & 9<br/><br/>玩家赌注总额＝110<br/>玩家赌注总额＝90<br/>玩家赌注总额＝100<br/><br/>发牌人赌注总额＝990<br/>发牌人赌注总额＝1010<br/>发牌人赌注总额＝1000<br/><br/> <br/><br/>任务<br/>素材往往单独解决起来往往非常困难，所以在一般情况下我们都把它分解为一系列任务来完成。在本文的二十一点纸牌游戏里，需要进行下列任务：<br/><br/>创建一副牌 <br/>创建一个投注台面 <br/>创建一手牌 <br/>创建游戏 <br/>创建一副牌<br/>在把素材分解成为任务的时候，我们可以把各个任务再分解成一系列待办事项，从而指导我们进行测试。这让我们可以保证在通过所有测试之后完成这个任务。对于这一副牌，我们有下列事项需要完成。<br/><br/>向牌桌上放一张纸牌 <br/>在发牌的同时将其从牌桌上移走 <br/>检查牌桌是否为空 <br/>检查牌桌上纸牌的张数 <br/>将牌桌上的一副牌的张数限制为52张（如果超过，就要显示异常） <br/>不断发牌，直到发完 <br/>洗牌 <br/>检查牌桌上纸牌的张数是否正确 <br/>在进行过第一轮的几个简单测试之后，我们的待办事项列表就像下面这样了：<br/><br/>向牌桌上放一张纸牌 <br/>在发牌的同时将其从牌桌上移走 <br/>检查牌桌是否为空 <br/>检查牌桌上纸牌的张数 <br/>将牌桌上一副牌的张数限制为52张（如果超过，就要显示异常） <br/>不断发牌，直到发完 <br/>洗牌 <br/>检查牌桌上纸牌的张数是否正确 <br/>下一个要进行的测试是从牌桌上发牌。当我们在为测试方法编写代码的时候，我们所扮演的角色就是将要编写的应用程序的用户。这就是为什么我们给自己的类创建的接口要与给用户的接口像类似的原因。在本文的这个例子里，我们将按照命令／查询分离原则（Command/Query Separation Principle5）编写出下面这样的代码。<br/><br/>Deck类。如列表A所示。<br/><br/>列表A<br/>[ocdes=java]<br/>import java.util.List; <br/><br/>import java.util.ArrayList; <br/><br/>public class Deck &#123; <br/><br/> &nbsp;private static final int CARDS_IN_DECK = 52; <br/><br/> &nbsp;private List cards = new ArrayList(); <br/><br/> &nbsp;public boolean isEmpty() &#123; <br/><br/> &nbsp; &nbsp;return size() == 0; <br/><br/> &nbsp;&#125;<br/><br/> &nbsp;public int size() &#123; <br/><br/> &nbsp; &nbsp;return cards.size(); <br/><br/> &nbsp;&#125;<br/><br/> &nbsp;public void add(int card) throws IllegalStateException &#123; <br/><br/> &nbsp;if(CARDS_IN_DECK == size()) <br/><br/> &nbsp; &nbsp;throw new IllegalStateException("Cannot add more than 52 cards"); <br/><br/> &nbsp; &nbsp;cards.add(new Integer(card)); <br/><br/> &nbsp;&#125;<br/><br/> &nbsp;public int top() &#123; <br/><br/> &nbsp; &nbsp;return ((Integer) cards.get(0)).intValue(); <br/><br/> &nbsp;&#125;<br/><br/> &nbsp; &nbsp;public void remove() &#123; <br/><br/> &nbsp; &nbsp;cards.remove(0); <br/><br/> &nbsp;&#125;<br/><br/>&#125; <br/><br/>[/codes]<br/>我们所有的测试都通过了，而且我们没有看到任何重复或者其他必要的重整，所以应该是时候进行下面的测试了。然而事实却不是这样的。我们top和remove方法的实现里有一个潜在的问题。如果对一个空的Deck调用它们，会发生什么？这两个方法都会从纸牌的内部列表里跳出一个IndexOutOfBoundsException异常，但是目前我们还没有就这个问题进行沟通。回头看看简单性的原则，我们知道自己需要沟通。我们的类的用户应该知道这个潜在的问题。幸运的是，我们将这种测试当作是一种沟通的方式，因此我们增加了下面的测试。 <br/><br/>Tags - <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=xp" rel="tag">xp</a> , <a href="http://vir.jxstnu.edu.cn/xieyunc/tag.php?tag=%25E6%2595%258F%25E6%258D%25B7%25E5%25BC%2580%25E5%258F%2591" rel="tag">敏捷开发</a>
]]>
</description>
</item>
</channel>
</rss>