ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>四虎影视精品,在线观看黄色小视频,91欧洲在线视精品在亚洲http://www.aygfsteel.com/lzj520/category/26946.htmlzh-cnTue, 20 Nov 2007 10:19:09 GMTTue, 20 Nov 2007 10:19:09 GMT60071719 rspec在netbeans IED 6 beta上è¿è¡Œæ—¶çš„一些问é¢?/title><link>http://www.aygfsteel.com/lzj520/archive/2007/11/19/161635.html</link><dc:creator>lzj520</dc:creator><author>lzj520</author><pubDate>Mon, 19 Nov 2007 07:45:00 GMT</pubDate><guid>http://www.aygfsteel.com/lzj520/archive/2007/11/19/161635.html</guid><wfw:comment>http://www.aygfsteel.com/lzj520/comments/161635.html</wfw:comment><comments>http://www.aygfsteel.com/lzj520/archive/2007/11/19/161635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/lzj520/comments/commentRss/161635.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/lzj520/services/trackbacks/161635.html</trackback:ping><description><![CDATA[ä¸çŸ¥æ˜¯æˆ‘弄错了什么地方,˜q˜æ˜¯æœ¬æ¥ž®±æ˜¯˜q™æ ·çš„,在netbeans IED 6 beta˜q行rspecæ—Óž¼Œå‡å¦‚先是先è¿è¡Œscaffold_resourceåQŒç„¶åŽæŒ‰ç…§rspec官方的文档的æ–ÒŽ³•æ¥å®‰è£…rspecã€rspec_on_railsåQŒåƈ˜q行rspecã€rspec_modelåQŒç„¶è€Œæ­¤æ—Óž¼Œ‹¹‹è¯•默认生æˆçš„modelåQŒå°±ä¼šå¾—åˆ°ç±»ä¼ÆD¿™æ ïLš„错误æç¤ºåQ?br /> 1.0.1/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:34:in `require': no such file to load -- E:/NetBeansProjects/RailsApplication2/spec/models/../../vendor/generators/rspec/lib/rspec_on_rails (MissingSourceFile)<br /> 此时打开spec_helper.rbåQŒå‘现rspec_on_rails的这一路径默认是ä¸å¯¹çš„åQŒéœ€è¦æ‰‹å·¥æŠŠå®ƒè®¾¾|®äؓ正确的èµ\径。或者我试过把这å¥èµ\径的引用直接删除掉,好åƒä¹Ÿå¯ä»¥ã€?br /> <br /> 处ç†å®Œè¿™ä¸€æ­¥ä¹‹åŽï¼Œä¼šé‡åˆ°çš„è·Ÿç€çš„这样一个错误æ½Cºï¼š<br /> spec/models/../spec_helper.rb:9: undefined local variable or method `use_transactional_fixtures=' for Spec::Runner::Context:Class (NameError)<br /> ˜q™éœ€è¦ä½ åŽ»test_helper.rb里加入一å¥require File.expand_path(File.dirname(__FILE__) + "/test2spec_help")åQŒæŠŠuse_transactional_fixtures加入˜q›æ¥ã€‚ç„¶åŽåœ¨spec_helper.rb里加入require File.expand_path(File.dirname(__FILE__) + "/../test/test_helper")<br /> <br /> ç„¶åŽæ‰èƒ½æ­£å¼çœ‹åˆ°1 example, 1 failure˜q™æ ·æ¯”较正常的æ½Cºã€‚ä¸çŸ¥æ˜¯å¦æˆ‘æ“作错误åQŒè¿˜æ˜¯ä»€ä¹ˆé—®é¢˜ï¼Œæ€ÖM¹‹ž®±æ˜¯¼„°åˆ°äº†è¿™æ ·ä¸€˜qžä¸²çš„é—®é¢? 而这个解军_Šžæ³•ä¹Ÿä¸çŸ¥æ˜¯å¦æ­£ç¡® <img src ="http://www.aygfsteel.com/lzj520/aggbug/161635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/lzj520/" target="_blank">lzj520</a> 2007-11-19 15:45 <a href="http://www.aygfsteel.com/lzj520/archive/2007/11/19/161635.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item><item><title>071030 一个jmock实例http://www.aygfsteel.com/lzj520/archive/2007/10/30/156839.htmllzj520lzj520Tue, 30 Oct 2007 01:18:00 GMThttp://www.aygfsteel.com/lzj520/archive/2007/10/30/156839.htmlhttp://www.aygfsteel.com/lzj520/comments/156839.htmlhttp://www.aygfsteel.com/lzj520/archive/2007/10/30/156839.html#Feedback0http://www.aygfsteel.com/lzj520/comments/commentRss/156839.htmlhttp://www.aygfsteel.com/lzj520/services/trackbacks/156839.html 首先建立‹¹‹è¯•用例åQ?br />

public class PlaceOrderServiceTests extends MockObjectTestCase{

 Mockery context = new Mockery();
   
    public void testUpdateRestaurant_good() throws Exception{
     //setup
     PlaceOrderService service = new PlaceOrderService();
     final RestaurantRepository restaurantRepository  =  context.mock(RestaurantRepository.class);
     final String restaurantId = "1";
     final String pendingOrderId = "1";
     //expectations
     context.checking(new Expectations(){{
      allowing(restaurantRepository).findRestaurant(restaurantId,pendingOrderId);
      }});
     //execute
     service.updateRestaurant(restaurantId,pendingOrderId);
     //verify
     context.assertIsSatisfied();
    }
}
ç„¶åŽåˆ†åˆ«å»ºç«‹ç›¸åº”的类和接å£ï¼š

public interface RestaurantRepository {

 Restaurant findRestaurant(String restaurantId, String pendingOrderId);

}

public class Restaurant {

}

public class PlaceOrderService {

 public void updateRestaurant(String restaurantId, String pendingOrderId) {
  // TODO Auto-generated method stub
  
 }

}



]]>
使用 RSpec ˜q›è¡Œè¡Œäؓ驱动‹¹‹è¯•åQˆè{åQ?/title><link>http://www.aygfsteel.com/lzj520/archive/2007/10/23/155374.html</link><dc:creator>lzj520</dc:creator><author>lzj520</author><pubDate>Tue, 23 Oct 2007 11:01:00 GMT</pubDate><guid>http://www.aygfsteel.com/lzj520/archive/2007/10/23/155374.html</guid><wfw:comment>http://www.aygfsteel.com/lzj520/comments/155374.html</wfw:comment><comments>http://www.aygfsteel.com/lzj520/archive/2007/10/23/155374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/lzj520/comments/commentRss/155374.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/lzj520/services/trackbacks/155374.html</trackback:ping><description><![CDATA[<blockquote>‹¹‹è¯•热潮现在传播åˆîCº† Ruby ¾~–程½C‘ÖŒºåQŒåƈ且愈演愈热。在˜q‡å޻䏀òq´é‡ŒåQŒæµ‹è¯•领域中最为瞩目的创新应属 RSpec 的引入和快速å‘展,˜q™æ˜¯ä¸€¿U行为驱动测试工兗÷€‚通过本文了解 RSpec 如何改å˜äºÞZ»¬æ€è€ƒæµ‹è¯•的方å¼ã€?</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES--> <p>在过åŽÕdòq´ä¸­åQŒèÊYä»¶å¼€å‘äh员对‹¹‹è¯•的热情日æ¸ä½Ž˜q—÷€‚åŒä¸€æ—¶æœŸå‡ºçŽ°çš„åŠ¨æ€è¯­­a€òq¶æ²¡æœ‰æä¾›ç¼–è¯‘ç¨‹åºæ¥æ•æ‰æœ€åŸºæœ¬çš„错误,˜q™ä‹É得测试å˜å¾—更加é‡è¦ã€‚éšç€‹¹‹è¯•½C‘ÖŒºçš„æˆé•¿ï¼Œå¼€å‘äh员开始注æ„到åQŒé™¤äº†æ•èŽ?bug ½{‰æœ€åŸºæœ¬çš„优点外åQŒæµ‹è¯•还å…ähœ‰ä»¥ä¸‹ä¼˜åŠ¿åQ?/p> <ul> <li>‹¹‹è¯•能够改进您的设计。进行测试的æ¯ä¸ªç›®æ ‡å¯¹è±¡å¿…须具备臛_°‘两个客户机:生äñ”代ç å’Œæµ‹è¯•用例。这些客æˆähœºå¼ºåˆ¶æ‚¨å¯¹ä»£ç ˜q›è¡Œè§£è€¦ã€‚测试还鼓励开å‘äh员ä‹É用更ž®ã€æ›´½Ž€å•çš„æ–ÒŽ³•ã€? <li>‹¹‹è¯•å‡å°‘了ä¸å¿…è¦çš„代ç ã€‚在¾~–写‹¹‹è¯•用例æ—Óž¼Œæ‚¨å…»æˆäº†å¾ˆå¥½çš„æµ‹è¯•习惯,å›_ª¾~–写˜q行‹¹‹è¯•用例所需的最ž®‘代ç ã€‚您抵制ä½äº†å¯¹åŠŸèƒ½è¿›è¡Œç¼–ç çš„诱惑åQŒå› ä¸ºæ‚¨ç›®å‰˜q˜ä¸éœ€è¦å®ƒã€? <li>推动了测试优先开å‘。您¾~–写的æ¯ä¸ªæµ‹è¯•用例会¼‹®å®šä¸€ä¸ªå°é—®é¢˜ã€‚ä‹É用代ç è§£å†Œ™¿™ä¸ªé—®é¢˜éžå¸¸æœ‰ç”¨åƈ且å¯ä»¥æŽ¨åЍ开å‘ã€‚å½“æˆ‘è¿›è¡Œæµ‹è¯•é©±åŠ¨å¼€å‘æ—¶åQŒæ—¶é—´è¿‡å¾—飞快ã€? <li>‹¹‹è¯•æä¾›äº†æ›´å¤šçš„自主æƒã€‚在使用‹¹‹è¯•用例æ•获å¯èƒ½çš„错误时åQŒæ‚¨ä¼šå‘现自己éžå¸¸æ„¿æ„对代砘q›è¡Œæ”¹è¿›ã€?</li> </ul> <p><a name="N10062"><span id="wmqeeuq" class="atitle">‹¹‹è¯•驱动的开å‘å’Œ RSpec</span></a></p> <p>有关‹¹‹è¯•的优ç‚ÒŽ— éœ€èµ˜è¿°åQŒæˆ‘ž®†å‘您介¾l一个简å•的使用 RSpec 的测试驱动开å‘示例。RSpec 工具是一ä¸?Ruby 软äšg包,å¯ä»¥ç”¨å®ƒæž„徿œ‰å…³æ‚¨çš„软äšg的规范。该规范实际上是一个æ˜q°ç³»¾lŸè¡Œä¸ºçš„‹¹‹è¯•。ä‹Éç”?RSpec çš„å¼€å‘æµ½E‹å¦‚下:</p> <ul> <li>¾~–写一个测试。该‹¹‹è¯•æè¿°¾pÈ»Ÿä¸­æŸä¸ªè¾ƒž®å…ƒç´ çš„è¡ŒäØ“ã€? <li>˜q行‹¹‹è¯•。由于尚没有为系¾lŸä¸­çš„相应部分构å»ÞZ»£ç ï¼Œ‹¹‹è¯•å¤ÞpÓ|。这一é‡è¦æ­¥éª¤ž®†æµ‹è¯•您的测试用例,‹‚€éªŒæµ‹è¯•用例是å¦åœ¨åº”当å¤ÞpÓ|的时候失败ã€? <li>¾~–写­‘›_¤Ÿçš„代ç ï¼Œä½¿æµ‹è¯•通过ã€? <li>˜q行‹¹‹è¯•åQŒæ£€éªŒæµ‹è¯•æ˜¯å¦æˆåŠŸã€?</li> </ul> <p>实质上,RSpec å¼€å‘äh员所åšçš„工作ž®±æ˜¯ž®†å¤±è´¥çš„‹¹‹è¯•用例调试为æˆåŠŸçš„‹¹‹è¯•用例。这是一个主动的˜q‡ç¨‹ã€‚本文中åQŒæˆ‘ž®†ä»‹¾l?RSpec 的基本用法ã€?</p> <p>首先åQŒå‡è®¾æ‚¨å·²å®‰è£…了 Ruby å’?gems。您˜q˜éœ€è¦å®‰è£?RSpec。输入下é¢çš„内容åQ?</p> <p><code>gem install rspec</code> </p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <br /> <br /> <p><a name="N10086"><span id="wmqeeuq" class="atitle">使用½CÞZ¾‹</span></a></p> <p>接下æ¥ï¼Œæˆ‘将逿­¥æž„å¾ä¸€ä¸ªçŠ¶æ€æœºã€‚我ž®†éµå¾?TDD 规则。首先编写自å·Þqš„‹¹‹è¯•用例åQŒåÆˆä¸”ç›´åˆ°æµ‹è¯•ç”¨ä¾‹éœ€è¦æ—¶æ‰ç¼–写代ç ã€‚Rake çš„åˆ›å»ø™€?Jim Weirich è®¤äØ“˜q™æœ‰åŠ©äºŽè§’è‰²æ‰®æ¼”ã€‚åœ¨¾~–å†™å®žé™…çš„ç”Ÿäº§ä»£ç æ—¶åQŒæ‚¨å¸Œæœ›å……当一å›?jerk å¼€å‘äh员的角色åQŒåªå®Œæˆæœ€ž®‘é‡çš„工作æ¥ä½¿æµ‹è¯•通过。在¾~–写‹¹‹è¯•æ—Óž¼Œæ‚¨åˆ™æ‰®æ¼”‹¹‹è¯•人员的角è‰ÔŒ¼Œè¯•图为开å‘äh员æä¾›ä¸€äº›æœ‰ç›Šçš„帮助ã€?/p> <p>以下的示例展½CÞZº†å¦‚何构å¾ä¸€ä¸ªçŠ¶æ€æœºã€‚如果您以å‰ä»ŽæœªæŽ¥è§¦˜q‡çŠ¶æ€æœºåQŒè¯·æŸ¥é˜… <a >å‚考资æ–?/a>ã€‚çŠ¶æ€æœºå…ähœ‰å¤šç§çжæ€ã€‚毿UçŠ¶æ€æ”¯æŒå¯ä»¥è{æ¢çŠ¶æ€æœºçжæ€çš„事äšg。测试驱动开å‘入门的关键ž®±æ˜¯ä»Žé›¶å…¥æ‰‹åQŒå°½é‡å°‘åœîC‹É用å‡è®¾æ¡ä»¶ã€‚é’ˆå¯Ò޵‹è¯•进行程åºè®¾è®¡ã€?/p> <p>ä½¿ç”¨æ¸…å• 1 的内容创建åä¸?machine_spec.rb 的文件。该文äšgž®±æ˜¯æ‚¨çš„规范。您˜q˜ä¸äº†è§£ machine.rb æ–‡äšg的作用,目å‰å…ˆåˆ›å»ÞZ¸€ä¸ªç©ºæ–‡äšgã€?/p> <br /> <a name="listing1"><strong>æ¸…å• 1. 最åˆçš„ machine_spec.rb æ–‡äšg </strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"> require 'machine' </pre> </td> </tr> </tbody> </table> <br /> <p>接下æ¥ï¼Œéœ€è¦è¿è¡Œæµ‹è¯•。始¾lˆé€šè¿‡è¾“å…¥ <code>spec machine_spec.rb</code> ˜q行‹¹‹è¯•。清å?2 展示了预料之中的‹¹‹è¯•å¤ÞpÓ|åQ?/p> <br /> <a name="listing2"><strong>æ¸…å• 2. ˜q行½Iºçš„规范</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">~/rspec batate$ spec machine_spec.rb /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- machine (LoadError) from /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ./state_machine_spec.rb:1 from ... </pre> </td> </tr> </tbody> </table> <br /> <p>在测试驱动开å‘中åQŒæ‚¨éœ€è¦è¿›è¡Œå¢žé‡å¼€å‘,因此在进行下一‹Æ¡å¼€å‘å‰åQŒéœ€è¦å…ˆè§£å†³æ­¤æ¬¡‹¹‹è¯•出现的问题。现在,我将扮演 jerk å¼€å‘äh员的角色åQŒå³åªå®Œæˆæ»¡­‘›_º”用程åºè¿è¡Œæ‰€éœ€çš„æœ€ž®‘工作é‡ã€‚我ž®†åˆ›å»ÞZ¸€ä¸ªåä¸?machine.rb 的空文äšgåQŒä‹É‹¹‹è¯•通过。我现在å¯ä»¥ä»¥é€¸å¾…劻I¼Œ‹¹‹è¯•通过而我几乎没åšä»ÖM½•事情ã€?/p> <p>¾l§ç®‹è§’色扮演。我现在扮演一个烦íwçš„‹¹‹è¯•人员åQŒä¿ƒä½?jerk å¼€å‘äh员åšäº›å®žé™…的工作。我ž®†ç¼–ç ä»¥ä¸‹è§„范,需è¦ä‹Éç”?<code>Machine</code> ¾c»ï¼Œå¦‚清å?3 所½Cºï¼š</p> <br /> <a name="listing3"><strong>æ¸…å• 3. åˆå§‹è§„范</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">require 'machine' describe Machine do before :each do @machine = Machine end end </pre> </td> </tr> </tbody> </table> <br /> <p>该规范æ˜qîCº†ç›®å‰ž®šä¸å­˜åœ¨çš?<code>Machine</code> ¾c…R€?code>describe</code> æ–ÒŽ³•æä¾›äº?RSpec æè¿°åQŒæ‚¨ž®†ä¼ å…¥æµ‹è¯•类的å¿U°å’ŒåŒ…å«å®žé™…规范的代ç å—。通常åQŒæµ‹è¯•ç”¨ä¾‹éœ€è¦æ‰§è¡Œä¸€å®šæ•°é‡çš„讄¡½®å·¥ä½œã€‚在 RSpec 中,ž®†ç”± <code>before</code> æ–ÒŽ³•完战q™äº›è®„¡½®å·¥ä½œã€‚您å?<code>before</code> æ–ÒŽ³•传递一个å¯é€‰çš„æ ‡å¿—和一个代ç å—。代ç å—中包å«è®¾¾|®å·¥ä½œã€‚标志确å®?RSpec 执行代ç å—的频率。默认的标志ä¸?<code>:each</code>åQŒè¡¨½C?RSpec ž®†åœ¨æ¯æ¬¡‹¹‹è¯•之å‰è°ƒç”¨ set up 代ç å—。您也å¯ä»¥æŒ‡å®?<code>:all</code>åQŒè¡¨½C?RSpec 在执行所有测试之å‰åªè°ƒç”¨ä¸€‹Æ?<code>before</code> 代ç å—。您应该始终使用 <code>:each</code>åQŒä‹Éå„个‹¹‹è¯•彼此独立ã€?</p> <p>输入 <code>spec</code> ˜q行‹¹‹è¯•åQŒå¦‚æ¸…å• 4 所½Cºï¼š </p> <br /> <a name="listing4"><strong>æ¸…å• 4. 存在性测试失è´?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">~/rspec batate$ spec machine_spec.rb ./machine_spec.rb:3: uninitialized constant Machine (NameError) </pre> </td> </tr> </tbody> </table> <br /> <p>现在åQŒçƒ¦íwçš„‹¹‹è¯•人员è¦ä¿ƒä½?jerk å¼€å‘äh员åšç‚¹ä»€ä¹ˆäº† â€?jerk å¼€å‘äh员现在需è¦åˆ›å»ºæŸä¸ªç±»ã€‚对我æ¥è¯ß_¼Œž®±æ˜¯ä¿®å¤‹¹‹è¯•出现的错误。在 <code>machine.rb</code> 中,我输入最ž®‘é‡çš„代ç ï¼Œå¦‚清å?5 所½Cºï¼š</p> <br /> <a name="listing5"><strong>æ¸…å• 5. 创å¾åˆå§‹ Machine ¾c?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">class Machine end</pre> </td> </tr> </tbody> </table> <br /> <p>ä¿å­˜æ–‡äšgåQŒç„¶åŽè¿è¡Œæµ‹è¯•ã€‚æ¯«æ— ç–‘é—®ï¼Œæ¸…å• 6 昄¡¤ºçš„æµ‹è¯•报告没有出现错误:</p> <br /> <a name="listing6"><strong>æ¸…å• 6. ‹¹‹è¯• Machine 是å¦å­˜åœ¨</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">~/rspec batate$ spec machine_spec.rb Finished in 5.0e-06 seconds 0 examples, 0 failures </pre> </td> </tr> </tbody> </table> <br /> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <br /> <br /> <p><a name="N10116"><span id="wmqeeuq" class="atitle">¾~–å†™è¡ŒäØ“</span></a></p> <p>现在åQŒæˆ‘å¯ä»¥å¼€å§‹å®žçŽ°æ›´å¤šçš„è¡ŒäØ“ã€‚æˆ‘çŸ¥é“åQŒæ‰€æœ‰çŠ¶æ€æœºå¿…须在æŸäº›åˆå§‹çжæ€ä¸‹å¯åŠ¨ã€‚ç›®å‰æˆ‘˜q˜ä¸æ˜¯å¾ˆæ¸…楚如何设计˜q™ä¸ªè¡ŒäØ“åQŒå› æ­¤æˆ‘先编写一个éžå¸¸ç®€å•çš„‹¹‹è¯•åQŒé¦–å…ˆå‡è®?<code>state</code> æ–ÒŽ³•会返å›?<code>:initial</code> 标志。我å¯?<code>machine_spec.rb</code> ˜q›è¡Œä¿®æ”¹òq¶è¿è¡Œæµ‹è¯•,如清å?7 所½Cºï¼š</p> <br /> <a name="listing7"><strong>æ¸…å• 7. 实现åˆå§‹çжæ€åƈ˜q行‹¹‹è¯•</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">require 'machine' describe Machine do before :each do @machine = Machine.new end it "should initially have a state of :initial" do @machine.state.should == :initial end end ~/rspec batate$ spec machine_spec.rb F 1) NoMethodError in 'Machine should initially have a state of :initial' undefined method `state' for #<Machine:0x10c7f8c> ./machine_spec.rb:9: Finished in 0.005577 seconds 1 example, 1 failure </pre> </td> </tr> </tbody> </table> <br /> <p>注愘q™æ¡è§„则åQ?code> it "should initially have a state of :initial" do @machine.state.should == :initial end</code>。首先注æ„到˜q™æ¡è§„则读è“væ¥åƒæ˜¯ä¸€ä¸ªè‹±æ–‡å¥å­ã€‚删除标点,ž®†å¾—åˆ?<code>it should initially have a state of initial</code>。然åŽä¼šæ³¨æ„到这æ¡è§„åˆ™åÆˆä¸åƒæ˜¯å…¸åž‹çš„é¢å‘对象代ç ã€‚它¼‹®å®žä¸æ˜¯ã€‚您现在有一个方法,¿UîCØ“ <code>it</code>。该æ–ÒŽ³•å…ähœ‰ä¸€ä¸ªä‹É用引åäh‹¬èµäh¥çš„å­—½W¦ä¸²å‚数和一个代ç å—。字½W¦ä¸²åº”该æè¿°‹¹‹è¯•需求。最åŽï¼Œ<code>do</code> å’?<code>end</code> 之间的代ç å—包嫋¹‹è¯•用例的代ç ã€?</p> <p>å¯ä»¥çœ‹åˆ°åQŒæµ‹è¯•进度划分得很细。这些微ž®çš„æ­¥éª¤äº§ç”Ÿçš„æ”¶ç›Šå´å¾ˆå¤§ã€‚它们ä‹É我能够改˜q›æµ‹è¯•密度,æä¾›æ—‰™—´ä¾›æˆ‘æ€è€ƒæœŸæœ›çš„è¡ŒäØ“ä»¥åŠå®žçŽ°è¡ŒäØ“æ‰€éœ€çš?API。这些步骤还能ä‹Éæˆ‘åœ¨å¼€å‘æœŸé—´è·Ÿítªä»£ç è¦†ç›–情况,从而构建更加丰富的规范ã€?/p> <p>˜q™ç§é£Žæ ¼çš„æµ‹è¯•具有åŒé‡ä½œç”¨ï¼š‹¹‹è¯•实现òq¶åœ¨‹¹‹è¯•çš„åŒæ—¶æž„建需求设计文档。ç¨åŽï¼Œæˆ‘将通过‹¹‹è¯•用例构å¾ä¸€ä¸ªéœ€æ±‚列表ã€?/p> <p>我ä‹É用最½Ž€å•的方å¼ä¿®å¤äº†æµ‹è¯•,˜q”回 <code>:initial</code>åQŒå¦‚æ¸…å• 8 所½Cºï¼š</p> <br /> <a name="listing8"><strong>æ¸…å• 8. 指定åˆå§‹çжæ€?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">class Machine def state :initial end end </pre> </td> </tr> </tbody> </table> <br /> <p>当查看实现时åQŒæ‚¨å¯èƒ½ä¼šæ”¾å£°å¤§½W‘或感觉å—到了愚弄。对于测试驱动开å‘,您必™åȨ微改å˜ä¸€ä¸‹æ€è€ƒæ–¹å¼ã€‚æ‚¨çš„ç›®æ ‡åÆˆä¸æ˜¯¾~–写最¾lˆçš„生äñ”代ç åQŒè‡³ž®‘çŽ°åœ¨ä¸æ˜¯ã€‚您的目标是使测试通过。当掌æ¡ä»¥è¿™¿Uæ–¹å¼å·¥ä½œæ—¶åQŒæ‚¨å¯èƒ½ä¼šå‘现新的实玎ͼŒòq¶ä¸”¾~–写的代ç è¦˜qœè¿œž®‘于采用 TDD 时编写的代ç ã€?/p> <p>下一步是˜q行代ç åQŒæŸ¥çœ‹å®ƒæ˜¯å¦é€šè¿‡‹¹‹è¯•åQ?/p> <br /> <a name="listing9"><strong>æ¸…å• 9. ˜q行åˆå§‹çŠ¶æ€æµ‹è¯?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">~/rspec batate$ spec machine_spec.rb . Finished in 0.005364 seconds 1 example, 0 failures</pre> </td> </tr> </tbody> </table> <br /> <p>èŠ×ƒº›æ—‰™—´æ€è€ƒä¸€ä¸‹è¿™ä¸ªé€šè¿‡‹¹‹è¯•çš„è„P代。如果查看代ç çš„è¯ï¼Œæ‚¨å¯èƒ½ä¼šè§‰å¾—æ°”é¦ã€‚å› ä¸ºåÆˆæ²¡æœ‰å–得什么进展。如果查看整个è„P代,ž®†çœ‹åˆ°æ›´å¤šå†…容:您æ•获了一个é‡è¦éœ€æ±‚åÆˆ¾~–写‹¹‹è¯•用例实现需求。作ä¸ÞZ¸€å程åºå‘˜åQŒæˆ‘的第一个行为测试帮助我明确了开å‘过½E‹ã€‚因为实现细节éšç€‹¹‹è¯•的进行越æ¥è¶Šæ¸…æ™°ã€?/p> <p>现在åQŒæˆ‘å¯ä»¥å®žçŽ°ä¸€ä¸ªæ›´å¥å£®çš„状æ€å®žçŽ°ã€‚å…·ä½“æ¥è®ÔŒ¼Œæˆ‘需è¦å¤„ç†çŠ¶æ€æœºçš„多个状æ€ã€‚我需è¦åˆ›å»ÞZ¸€ä¸ªæ–°çš„è§„åˆ™èŽ·å–æœ‰æ•ˆçжæ€åˆ—表。åƒä»¥å‰ä¸€æ øP¼Œæˆ‘å°†˜q行‹¹‹è¯•òq¶æŸ¥çœ‹æ˜¯å¦é€šè¿‡ã€?/p> <br /> <a name="listing10"><strong>æ¸…å• 10. 实现有效状æ€è§„èŒ?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"> it "should remember a list of valid states" do @machine.states = [:shopping, :checking_out] @machine.states.should = [:shopping, :checking_out] end run test(note: failing first verifies test) ~/rspec batate$ spec machine_spec.rb .F 1) NoMethodError in 'Machine should remember a list of valid states' undefined method `states=' for #<Machine:0x10c7154> ./machine_spec.rb:13: Finished in 0.005923 seconds 2 examples, 1 failure</pre> </td> </tr> </tbody> </table> <br /> <p>在清å?10 中,出现了一ä¸?RSpec å½¢å¼çš„æ–­­a€ã€‚该断言ä»?<code>should</code> æ–ÒŽ³•å¼€å§‹ï¼Œç„¶åŽæ·ÕdŠ äº†ä¸€äº›æ¯”è¾ƒå…³¾p…R€?code>should</code> æ–ÒŽ³•对应用程åºè¿›è¡ŒæŸ¿U观察。工作中的应用程åºåº”该以æŸç§æ–¹å¼˜q行ã€?code>should</code> æ–ÒŽ³•很好地æ•获了˜q™ç§éœ€æ±‚ã€‚åœ¨æœ¬ä¾‹ä¸­ï¼Œæˆ‘çš„çŠ¶æ€æœºåº”该记忆两ç§ä¸åŒçš„状æ€ã€?/p> <p>现在åQŒåº”该添加一个实例å˜é‡æ¥å®žé™…记忆状æ€ã€‚åƒä»¥å¾€ä¸€æ øP¼Œæˆ‘在修改代ç åŽè¿è¡Œæµ‹è¯•用例,òq¶è§‚å¯Ÿæµ‹è¯•æ˜¯å¦æˆåŠŸã€?/p> <br /> <a name="listing11"><strong>æ¸…å• 11. 创å¾ä¸€ä¸ªå±žæ€§ä»¥è®°å¿†çжæ€?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">class Machine attr_accessor :states def state :initial end end ~/rspec batate$ spec machine_spec.rb .. Finished in 0.00606 seconds 2 examples, 0 failures</pre> </td> </tr> </tbody> </table> <br /> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <br /> <br /> <p><a name="N10199"><span id="wmqeeuq" class="atitle">é©±åŠ¨é‡æž„</span></a></p> <p>此时åQŒæˆ‘òq¶ä¸æƒ›_†³å®šå°† <code>:initial</code> 状æ€ç§°ä¸ºçŠ¶æ€æœºçš„第一个状æ€ã€‚相å,我更希望½W¬ä¸€ä¸ªçŠ¶æ€æ˜¯çŠ¶æ€æ•°¾l„ä¸­çš„ç¬¬ä¸€ä¸ªå…ƒç´ ã€‚æˆ‘å¯¹çŠ¶æ€æœºçš„ç†è§£åœ¨ä¸æ–­æ¼”å˜ã€‚è¿™¿UçŽ°è±¡åÆˆä¸å°‘è§ã€‚测试驱动开å‘ç»å¸¸è¿«ä½¿æˆ‘釿–°è€ƒè™‘之å‰çš„å‡è®¾ã€‚由于我已ç»é€šè¿‡‹¹‹è¯•用例æ•获了早期需求,我å¯ä»¥è½»æ‘Öœ°å¯¹ä»£ç è¿›è¡Œé‡æž„ã€‚åœ¨æœ¬ä¾‹ä¸­ï¼Œé‡æž„ž®±æ˜¯å¯¹ä»£ç è¿›è¡Œè°ƒæ•ß_¼Œä½¿å…¶æ›´å¥½åœ°å·¥ä½œã€?/p> <p>修改½W¬ä¸€ä¸ªæµ‹è¯•,使其如清å?12 所½Cºï¼Œòq¶è¿è¡Œæµ‹è¯•:</p> <br /> <a name="listing12"><strong>æ¸…å• 12. åˆå§‹çжæ€åº”è¯¥äØ“æŒ‡å®šçš„ç¬¬ä¸€ä¸ªçŠ¶æ€?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">it "should initially have a state of the first state" do @machine.states = [:shopping, :checking_out] @machine.state.should == :shopping end ~/rspec batate$ spec machine_spec.rb F. 1) 'Machine should initially have a state of the first state' FAILED expected :shopping, got :initial (using ==) ./machine_spec.rb:10: Finished in 0.005846 seconds 2 examples, 1 failure</pre> </td> </tr> </tbody> </table> <br /> <p>å¯ä»¥˜q™æ ·è¯ß_¼Œ‹¹‹è¯•ç”¨ä¾‹èµ·åˆ°ä½œç”¨äº†ï¼Œå› äØ“å®ƒè¿è¡Œå¤±è´¥ï¼Œå› æ­¤æˆ‘现在需è¦ä¿®æ”¹ä»£ç ä»¥ä½¿å…¶å·¥ä½œã€‚显而易è§ï¼Œæˆ‘çš„ä»ÕdŠ¡ž®±æ˜¯ä½¿æµ‹è¯•通过。我喜欢˜q™ç§‹¹‹è¯•目的åQŒå› ä¸ºæˆ‘的测试用例正在驱动我˜q›è¡Œè®¾è®¡ã€‚我ž®†æŠŠåˆå§‹çжæ€ä¼ é€’ç»™ <code>new</code> æ–ÒŽ³•。我ž®†å¯¹å®žçް½E作修改åQŒä»¥½W¦åˆä¿®æ”¹åŽçš„规范åQŒå¦‚æ¸…å• 13 所½Cºã€?/p> <br /> <a name="listing13"><strong>æ¸…å• 13. 指定åˆå§‹çжæ€?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">start to fix it class Machine attr_accessor :states attr_reader :state def initialize(states) @states = states @state = @states[0] end end ~/rspec batate$ spec machine_spec.rb 1) ArgumentError in 'Machine should initially have a state of the first state' wrong number of arguments (0 for 1) ./machine_spec.rb:5:in `initialize' ./machine_spec.rb:5:in `new' ./machine_spec.rb:5: 2) ArgumentError in 'Machine should remember a list of valid states' wrong number of arguments (0 for 1) ./machine_spec.rb:5:in `initialize' ./machine_spec.rb:5:in `new' ./machine_spec.rb:5: Finished in 0.006391 seconds 2 examples, 2 failures</pre> </td> </tr> </tbody> </table> <br /> <p>现在åQŒæµ‹è¯•出çŽîCº†ä¸€äº›é”™è¯¯ã€‚我扑ֈ°äº†å®žçŽîC¸­çš„一äº?bug。测试用例ä¸å†ä‹É用正¼‹®çš„æŽ¥å£åQŒå› ä¸ºæˆ‘没有把åˆå§‹çжæ€ä¼ é€’ç»™çŠ¶æ€æœºã€‚å¯ä»¥çœ‹åˆŽÍ¼Œ‹¹‹è¯•用例已ç»èµ·åˆ°äº†ä¿æŠ¤ä½œç”¨ã€‚我˜q›è¡Œäº†è¾ƒå¤§çš„æ›´æ”¹åQŒæµ‹è¯•å°±å‘现äº?bug。我们需è¦å¯¹‹¹‹è¯•˜q›è¡Œé‡æž„ä»¥åŒ¹é…æ–°çš„æŽ¥å£ï¼Œž®†åˆå§‹çжæ€åˆ—表传递给 <code>new</code> æ–ÒŽ³•。在˜q™é‡Œæˆ‘åÆˆæ²¡æœ‰é‡å¤åˆå§‹åŒ–代ç ï¼Œè€Œæ˜¯ž®†å…¶æ”„¡½®åœ?<code>before</code> æ–ÒŽ³•中,如清å?14 所½Cºï¼š</p> <br /> <a name="listing14"><strong>æ¸…å• 14. åœ?“before” 中åˆå§‹åŒ–çŠ¶æ€æœº </strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">require 'machine' describe Machine do before :each do @machine = Machine.new([:shopping, :checking_out]) end it "should initially have a state of the first state" do @machine.state.should == :shopping end it "should remember a list of valid states" do @machine.states.should == [:shopping, :checking_out] end end ~/rspec batate$ spec machine_spec.rb .. Finished in 0.005542 seconds 2 examples, 0 failures</pre> </td> </tr> </tbody> </table> <br /> <p>çŠ¶æ€æœºå¼€å§‹é€æ¸æˆåž‹ã€‚代ç ä»ç„¶æœ‰ä¸€äº›é—®é¢˜ï¼Œä½†æ˜¯æ­£åœ¨å‘è‰¯å¥½çš„æ–¹å‘æ¼”化。我ž®†å¼€å§‹å¯¹çŠ¶æ€æœº˜q›è¡Œä¸€äº›è{æ¢ã€‚这些è{æ¢å°†ä¿ƒä‹É代ç å®žé™…记忆当å‰çжæ€ã€?/p> <p>‹¹‹è¯•用例促ä‹É我全é¢åœ°æ€è€?API 的设计。我需è¦çŸ¥é“如何表½CÞZº‹ä»¶å’Œè½¬æ¢ã€‚首先,我将使用一个散列表表示转æ¢åQŒè€Œæ²¡æœ‰ä‹É用æˆç†Ÿçš„é¢å‘对象实现。éšåŽï¼Œ‹¹‹è¯•需求å¯èƒ½ä¼šè¦æ±‚我修改å‡è®¾æ¡ä»Óž¼Œä½†æ˜¯ç›®å‰åQŒæˆ‘ä»ç„¶ä¿æŒ˜q™ç§½Ž€å•性。清å?15 昄¡¤ºäº†ä¿®æ”¹åŽçš„代ç ï¼š</p> <br /> <a name="listing15"><strong>æ¸…å• 15. æ·ÕdŠ äº‹äšgå’Œè{æ?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">remember events... change before conditions require 'machine' describe Machine do before :each do @machine = Machine.new([:shopping, :checking_out]) @machine.events = {:checkout => {:from => :shopping, :to => :checking_out}} end it "should initially have a state of the first state" do @machine.state.should == :shopping end it "should remember a list of valid states" do @machine.states.should == [:shopping, :checking_out] end it "should remember a list of events with transitions" do @machine.events.should == {:checkout => {:from => :shopping, :to => :checking_out}} end end ~/rspec batate$ spec machine_spec.rb FFF 1) NoMethodError in 'Machine should initially have a state of the first state' undefined method `events=' for #<Machine:0x10c6f38> ./machine_spec.rb:6: 2) NoMethodError in 'Machine should remember a list of valid states' undefined method `events=' for #z7lt;Machine:0x10c5afc> ./machine_spec.rb:6: 3) NoMethodError in 'Machine should remember a list of events with transitions' undefined method `events=' for #<Machine:0x10c4a58> ./machine_spec.rb:6: Finished in 0.006597 seconds 3 examples, 3 failures</pre> </td> </tr> </tbody> </table> <br /> <p>ç”׃ºŽæ–°çš„‹¹‹è¯•代ç ä½äºŽ <code>before</code> 中,ž®†æˆ‘的三个测试分解开æ¥ã€‚å°½½Ž¡å¦‚æ­¤ï¼Œæ¸…å• 16 中展½Cºçš„‹¹‹è¯•éžå¸¸å®ÒŽ˜“ä¿®å¤ã€‚我ž®†æ·»åŠ å¦ä¸€ä¸ªè®¿é—®ç¨‹åºï¼š</p> <br /> <a name="listing16"><strong>æ¸…å• 16. 记忆事äšg</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">class Machine attr_accessor :states, :events attr_reader :state def initialize(states) @states = states @state = @states[0] end end ~/rspec batate$ spec machine_spec.rb ... Finished in 0.00652 seconds 3 examples, 0 failures test</pre> </td> </tr> </tbody> </table> <br /> <p>‹¹‹è¯•全部通过。我得到了一个能正常˜qè¡Œçš„çŠ¶æ€æœºã€‚接下æ¥çš„几个测试将使它更加完善ã€?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <br /> <br /> <p><a name="N101FD"><span id="wmqeeuq" class="atitle">接近真实的应用程åº?/span></a></p> <p>ç›®å‰ä¸ºæ­¢åQŒæˆ‘所åšçš„ä¸è¿‡æ˜¯è§¦å‘了一‹Æ¡çжæ€è{æ¢ï¼Œä½†æ˜¯æˆ‘å·²¾låšå¥½äº†æ‰€æœ‰åŸº¼‹€å·¥ä½œã€‚我得到了一¾l„需求。我˜q˜æž„å»ÞZº†ä¸€¾l„测试。我的代ç å¯ä»¥äØ“çŠ¶æ€æœºæä¾›ä½¿ç”¨çš„æ•°æ®ã€‚æ­¤æ—Óž¼Œ½Ž¡ç†å•ä¸ªçŠ¶æ€æœºè½¬æ¢ä»…表½CÞZ¸€‹Æ¡ç®€å•的转æ¢åQŒå› æ­¤æˆ‘ž®†æ·»åŠ å¦‚æ¸…å• 17 所½Cºçš„‹¹‹è¯•åQ?/p> <br /> <a name="listing17"><strong>æ¸…å• 17. æž„å¾çŠ¶æ€æœºçš„状æ€è{æ?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">it "should transition to :checking_out upon #trigger(:checkout) event " do @machine.trigger(:checkout) @machine.state.should == :checking_out end ~/rspec batate$ spec machine_spec.rb ...F 1) NoMethodError in 'Machine should transition to :checking_out upon #trigger(:checkout) event ' undefined method `trigger' for #<Machine:0x10c4d00> ./machine_spec.rb:24: Finished in 0.006153 seconds 4 examples, 1 failure</pre> </td> </tr> </tbody> </table> <br /> <p>æˆ‘éœ€è¦æŠµåˆ¶å¿«é€Ÿæž„å»ºå¤§é‡åŠŸèƒ½çš„è¯±æƒ‘ã€‚æˆ‘åº”è¯¥åªç¼–写少é‡ä»£ç ï¼Œåªè¦ä½¿æµ‹è¯•通过å›_¯ã€‚清å?18 展示的è„P代将表示 API 和需求。这ž®Þpƒö够了åQ?/p> <br /> <a name="listing18"><strong>æ¸…å• 18. 定义 trigger æ–ÒŽ³•</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">def trigger(event) @state = :checking_out end ~/rspec batate$ spec machine_spec.rb .... Finished in 0.005959 seconds 4 examples, 0 failures</pre> </td> </tr> </tbody> </table> <br /> <p>˜q™é‡Œå‡ºçŽ°äº†ä¸€ä¸ªæœ‰­‘£çš„è¾Ò޳¨ã€‚在¾~–å†™ä»£ç æ—Óž¼Œæˆ‘两‹Æ¡éƒ½å¼„错了这个简å•çš„æ–ÒŽ³•。第一‹Æ¡æˆ‘˜q”回äº?<code>:checkout</code>åQ›ç¬¬äºŒæ¬¡æˆ‘将状æ€è®¾¾|®äØ“ <code>:checkout</code> è€Œä¸æ˜?<code>:checking_out</code>。在‹¹‹è¯•中ä‹É用较ž®çš„æ­¥éª¤å¯ä»¥ä¸ºæˆ‘节çœå¤§é‡æ—‰™—´åQŒå› ä¸ºæµ‹è¯•ç”¨ä¾‹äØ“æˆ‘æ•èŽïLš„˜q™äº›é”™è¯¯åœ¨å°†æ¥çš„å¼€å‘中很难æ•获到。本文的最åŽä¸€ä¸ªæ­¥éª¤æ˜¯å®žé™…执行一‹Æ¡çŠ¶æ€æœºè½¬æ¢ã€‚在½W¬ä¸€ä¸ªç¤ºä¾‹ä¸­åQŒæˆ‘òq¶ä¸å…›_¿ƒå®žé™…çš„æœºå™¨çŠ¶æ€æ˜¯ä»€ä¹ˆæ ·å­çš„。我仅仅是根æ®äº‹ä»¶è¿›è¡Œç›²ç›®è{æ¢ï¼Œè€Œä¸è€ƒè™‘状æ€ã€?/p> <p>ä¸¤èŠ‚ç‚¹çš„çŠ¶æ€æœºæ— æ³•执行˜q™ä¸ªæ“作åQŒæˆ‘需è¦åœ¨½W¬ä¸‰ä¸ªèŠ‚ç‚¹ä¸­æž„å¾ã€‚我没有使用已有çš?<code>before</code> æ–ÒŽ³•åQŒåªæ˜¯åœ¨æ–°çжæ€ä¸­æ·ÕdŠ å¦å¤–的状æ€ã€‚我ž®†åœ¨‹¹‹è¯•用例中进行两‹Æ¡è{æ¢ï¼Œä»¥ç¡®ä¿çŠ¶æ€æœºèƒ½å¤Ÿæ­£ç¡®åœ°æ‰§è¡Œè{æ¢ï¼Œå¦‚清å?19 所½Cºï¼š</p> <br /> <a name="listing19"><strong>æ¸…å• 19. 实现½W¬ä¸€‹Æ¡è{æ?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">it "should transition to :success upon #trigger(:accept_card)" do @machine.events = { :checkout => {:from => :shopping, :to => :checking_out}, :accept_card => {:from => :checking_out, :to => :success} } @machine.trigger(:checkout) @machine.state.should == :checking_out @machine.trigger(:accept_card) @machine.state.should == :success end ~/rspec batate$ spec machine_spec.rb ....F 1) 'Machine should transition to :success upon #trigger(:accept_card)' FAILED expected :success, got :checking_out (using ==) ./machine_spec.rb:37: Finished in 0.007564 seconds 5 examples, 1 failure</pre> </td> </tr> </tbody> </table> <br /> <p>˜q™ä¸ª‹¹‹è¯•ž®†ä‹Éç”?<code>:checkout</code> å’?<code>:accept_card</code> 事äšgå»ºç«‹æ–°çš„çŠ¶æ€æœºã€‚在处熽{‘Ö‡ºæ—Óž¼Œæˆ‘选择使用两个事äšgè€Œä¸æ˜¯ä¸€ä¸ªï¼Œ˜q™æ ·å¯ä»¥é˜²æ­¢å‘生åŒå‘½ä»¤ã€‚ç­¾å‡ÞZ»£ç å¯ä»¥ç¡®ä¿çŠ¶æ€æœºåœ¨ç­¾å‡ÞZ¹‹å‰å¤„äº?<code>shopping</code> 状æ€ã€‚第一‹Æ¡ç­¾å‡ºé¦–å…ˆå°†çŠ¶æ€æœºä»?<code>shopping</code> 转æ¢ä¸?<code>checking_out</code>ã€‚æµ‹è¯•ç”¨ä¾‹é€šè¿‡è§¦å‘ <code>checkout</code> å’?<code>accept_card</code> 事äšg实现两个转æ¢åQŒåÆˆåœ¨è°ƒç”¨äº‹ä»¶ä¹‹åŽæ£€éªŒäº‹ä»¶çŠ¶æ€æ˜¯å¦æ­£¼‹®ã€‚ä¸Žé¢„æœŸä¸€æ øP¼Œ‹¹‹è¯•用例å¤ÞpÓ| â€?æˆ‘åÆˆæ²¡æœ‰¾~–写处ç†å¤šä¸ªè½¬æ¢çš„触å‘器æ–ÒŽ³•。代ç ä¿®æ­£åŒ…å«ä¸€è¡Œéžå¸”R‡è¦çš„代ç ã€‚清å?20 å±•ç¤ºäº†çŠ¶æ€æœºçš„æ ¸å¿ƒï¼š </p> <br /> <a name="listing20"><strong>æ¸…å• 20. çŠ¶æ€æœºçš„æ ¸å¿?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">def trigger(event) @state = events[event][:to] end ~/rspec batate$ spec machine_spec.rb ..... Finished in 0.006511 seconds 5 examples, 0 failures</pre> </td> </tr> </tbody> </table> <br /> <p>‹¹‹è¯•å¯ä»¥˜q行。这些粗¾p™çš„代砽W¬ä¸€‹Æ¡æ¼”å˜äؓ真正å¯ä»¥¿UîC¹‹ä¸ºçŠ¶æ€æœºçš„东è¥Ñ€‚但是这˜q˜è¿œ˜qœä¸å¤Ÿã€‚ç›®å‰ï¼ŒçŠ¶æ€æœº¾~ÞZ¹ä¸¥å¯†æ€§ã€‚ä¸½Ž¡çŠ¶æ€å¦‚ä½•ï¼ŒçŠ¶æ€æœºéƒ½ä¼šè§¦å‘事äšg。例如,当处äº?<code>shopping</code> çŠ¶æ€æ—¶åQŒè§¦å?<code>:accept_card</code> òq¶ä¸ä¼šè{æ¢äØ“ <code>:success</code> 状æ€ã€‚您åªèƒ½å¤Ÿä»Ž <code>:checking_out</code> 状æ€è§¦å?<code>:accept_card</code>。在¾~–程术语中,<code>trigger</code> æ–ÒŽ³•的范围应针对事äšg。我ž®†ç¼–写一个测试æ¥è§£å†³é—®é¢˜åQŒç„¶åŽä¿®å¤?bug。我ž®†ç¼–写一个负‹¹‹è¯•åQˆnegative teståQ‰ï¼ŒåÏx–­­a€ä¸€ä¸ªä¸åº”该出现的行为,如清å?21 所½Cºï¼š</p> <br /> <a name="listing21"><strong>æ¸…å• 21: 负测è¯?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">it "should not transition from :shopping to :success upon :accept_card" do @machine.events = { :checkout => {:from => :shopping, :to => :checking_out}, :accept_card => {:from => :checking_out, :to => :success} } @machine.trigger(:accept_card) @machine.state.should_not == :success end rspec batate$ spec machine_spec.rb .....F 1) 'Machine should not transition from :shopping to :success upon :accept_card' FAILED expected not == :success, got :success ./machine_spec.rb:47: Finished in 0.006582 seconds 6 examples, 1 failure</pre> </td> </tr> </tbody> </table> <br /> <p>现在å¯ä»¥å†æ¬¡˜q行‹¹‹è¯•åQŒå…¶ä¸­ä¸€ä¸ªæµ‹è¯•如预期一栯‚¿è¡Œå¤±è´¥ã€‚ä¿®å¤ä»£ç åŒæ ·åªæœ‰ä¸€è¡Œï¼Œå¦‚清å?22 所½Cºï¼š</p> <br /> <a name="listing22"><strong>æ¸…å• 22. ä¿®å¤ trigger 中的范围问题 </strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">def trigger(event) @state = events[event][:to] if state == events[event][:from] end rspec batate$ spec machine_spec.rb ...... Finished in 0.006873 seconds 6 examples, 0 failures</pre> </td> </tr> </tbody> </table> <br /> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <br /> <br /> <p><a name="N1029C"><span id="wmqeeuq" class="atitle">¾l„åˆä»£ç </span></a></p> <p>现在åQŒæˆ‘å…ähœ‰ä¸€ä¸ªå¯½Ž€å•è¿è¡Œçš„çŠ¶æ€æœºã€‚æ— è®ÞZ»Žå“ªæ–¹é¢æ¥è¯ß_¼Œå®ƒéƒ½ä¸æ˜¯ä¸€ä¸ªå®Œ¾ŸŽçš„½E‹åºã€‚它˜q˜å…·æœ‰ä¸‹é¢è¿™äº›é—®é¢˜ï¼š</p> <ul> <li>çŠ¶æ€æ•£åˆ—实际上ä¸å…·å¤‡ä“Q何功能。我应该æ ÒŽ®çŠ¶æ€å¯¹äº‹äšgåŠå…¶è½¬æ¢˜q›è¡ŒéªŒè¯åQŒæˆ–者将所有状æ€é›†ä¸­è“væ¥ã€‚厾l­éœ€æ±‚很å¯èƒ½ä¼šè¦æ±‚这样åšã€? <li>æŸä¸ªæ—¢å®šäº‹äšgåªèƒ½å­˜åœ¨äºŽä¸€ä¸ªçжæ€ä¸­ã€‚è¿™¿Ué™åˆ¶åƈä¸åˆç†ã€‚例如,<code>submit</code> å’?<code>cancel</code> 事äšgå¯èƒ½éœ€è¦å¤„于多个状æ€ã€? <li>代ç òq¶ä¸å…·å¤‡æ˜Žæ˜¾çš„é¢å‘对象特å¾ã€‚䨓佉K…¾|®ä¿æŒç®€å•ï¼Œæˆ‘å°†å¤§é‡æ•°æ®¾|®å…¥æ•£åˆ—中。厾l­çš„˜q­ä»£ä¼šè¿›ä¸€æ­¥é©±åŠ¨è®¾è®¡ï¼Œä½¿å…¶æœé¢å‘对象设计方å‘å‘展ã€?</li> </ul> <p>但是åQŒæ‚¨˜q˜å¯ä»¥çœ‹åˆŽÍ¼Œ˜q™ä¸ªçŠ¶æ€æœºå·²ç»èƒ½å¤Ÿæ»¡èƒö一些需求了。我˜q˜å…·å¤‡ä¸€ä¸ªæ˜q°ç³»¾lŸè¡Œä¸ºçš„æ–‡æ¡£åQŒè¿™æ˜¯è¿›è¡Œä¸€¾pÕdˆ—‹¹‹è¯•的好èµïL‚¹ã€‚æ¯ä¸ªæµ‹è¯•用例都支挾pÈ»Ÿçš„一个基本需求。事实上åQŒé€šè¿‡˜q行 <code>spec machine_spec.rb --format specdoc</code>åQŒæ‚¨å¯ä»¥æŸ¥çœ‹ç”Þq³»¾lŸè§„范组æˆçš„基本报告åQŒå¦‚æ¸…å• 23 所½Cºï¼š</p> <br /> <a name="listing23"><strong>æ¸…å• 23. 查看规范</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">spec machine_spec.rb --format specdoc Machine - should initially have a state of the first state - should remember a list of valid states - should remember a list of events with transitions - should transition to :checking_out upon #trigger(:checkout) event - should transition to :success upon #trigger(:accept_card) - should not transition from :shopping to :success upon :accept_card Finished in 0.006868 seconds</pre> </td> </tr> </tbody> </table> <br /> <p>‹¹‹è¯•驱动æ–ÒŽ³•òq¶ä¸é€‚åˆæ‰€æœ‰ähåQŒä½†æ˜¯è¶Šæ¥è¶Šå¤šçš„人开始ä‹É用这¿U技术,使用它构建具有絋zÀL€§å’Œé€‚应性的高质é‡ä»£ç ï¼Œòq¶ä¸”æ ÒŽ®‹¹‹è¯•从头构å¾ä»£ç ã€‚当ç„Óž¼Œæ‚¨ä¹Ÿå¯ä»¥é€šè¿‡å…¶ä»–框架åQˆå¦‚ test_unitåQ‰èŽ·å¾—ç›¸åŒçš„优点。RSpec ˜q˜æä¾›äº†ä¼˜ç§€çš„实现方法。这¿Uæ–°‹¹‹è¯•框架的一大亮点就是代ç çš„表示。新手尤其å¯ä»¥ä»Ž˜q™ç§è¡Œäؓ驱动的测试方法中å—益。请ž®è¯•ä½¿ç”¨è¯¥æ¡†æž¶åÆˆå‘Šè¯‰æˆ‘æ‚¨çš„æ„Ÿå—ã€?/p> <img src ="http://www.aygfsteel.com/lzj520/aggbug/155374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/lzj520/" target="_blank">lzj520</a> 2007-10-23 19:01 <a href="http://www.aygfsteel.com/lzj520/archive/2007/10/23/155374.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> Ö÷Õ¾Ö©Öë³ØÄ£°å£º <a href="http://" target="_blank">ÖÜÄþÏØ</a>| <a href="http://" target="_blank">ºþÖÝÊÐ</a>| <a href="http://" target="_blank">¸·ÑôÊÐ</a>| <a href="http://" target="_blank">ÏéÔÆÏØ</a>| <a href="http://" target="_blank">ÇßÔ´ÏØ</a>| <a href="http://" target="_blank">»ôÁÖ¹ùÀÕÊÐ</a>| <a href="http://" target="_blank">½­ÓÍÊÐ</a>| <a href="http://" target="_blank">ËìÏªÏØ</a>| <a href="http://" target="_blank">´óʯÇÅÊÐ</a>| <a href="http://" target="_blank">ÒÁ´ºÊÐ</a>| <a href="http://" target="_blank">ºÍ¾²ÏØ</a>| <a href="http://" target="_blank">Ìï¶«ÏØ</a>| <a href="http://" target="_blank">°×³ÇÊÐ</a>| <a href="http://" target="_blank">лÎ</a>| <a href="http://" target="_blank">ÏÌÄþÊÐ</a>| <a href="http://" target="_blank">³É°²ÏØ</a>| <a href="http://" target="_blank">ÎåָɽÊÐ</a>| <a href="http://" target="_blank">°²ÏªÏØ</a>| <a href="http://" target="_blank">°²Ë³ÊÐ</a>| <a href="http://" target="_blank">¶«ÀöÇø</a>| <a href="http://" target="_blank">¶¨ÄÏÏØ</a>| <a href="http://" target="_blank">¹ãÔªÊÐ</a>| <a href="http://" target="_blank">̨¶«ÏØ</a>| <a href="http://" target="_blank">ºâË®ÊÐ</a>| <a href="http://" target="_blank">ÁÖ¿ÚÏØ</a>| <a href="http://" target="_blank">ÓíÖÝÊÐ</a>| <a href="http://" target="_blank">á¶ÑÒ</a>| <a href="http://" target="_blank">ÌúÁëÊÐ</a>| <a href="http://" target="_blank">·î»¯ÊÐ</a>| <a href="http://" target="_blank">¸¡ÁºÏØ</a>| <a href="http://" target="_blank">ÃÏÖÝÊÐ</a>| <a href="http://" target="_blank">¸£¶¦ÊÐ</a>| <a href="http://" target="_blank">ÏÉÓÎÏØ</a>| <a href="http://" target="_blank">°¢À­ÉÆ×óÆì</a>| <a href="http://" target="_blank">Ìì×£</a>| <a href="http://" target="_blank">·À³Ç¸ÛÊÐ</a>| <a href="http://" target="_blank">»ªÈÝÏØ</a>| <a href="http://" target="_blank">ÁÙÈªÏØ</a>| <a href="http://" target="_blank">Í­´¨ÊÐ</a>| <a href="http://" target="_blank">×Ͳ©ÊÐ</a>| <a href="http://" target="_blank">Ð˳ÇÊÐ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>