Cucumber是Ruby世界的BDD框架åQŒå¼€å‘äh员主è¦ä¸Žä¸¤ç±»æ–‡äšg打交刎ͼŒFeatureæ–‡äšg和相应的Stepæ–‡äšg。Featureæ–‡äšg是以feature为厾~€å的文äšgåQŒä»¥Given-When-Thençš„æ–¹å¼æ˜qîCº†¾pÈ»Ÿçš„场æ™?scenarios)è¡ŒäØ“åQ›Stepæ–‡äšg为普通的Rubyæ–‡äšgåQŒFeatureæ–‡äšgä¸çš„æ¯ä¸ªGiven/When/Thenæ¥éª¤åœ¨Stepæ–‡äšgä¸éƒ½æœ‰å¯¹åº”çš„Ruby执行代ç åQŒä¸¤¾cÀL–‡ä»‰™€šè¿‡æ£åˆ™è¡¨è¾¾å¼ç›¸å…Œ™”。笔者在用Cucumber+Watiråšå›žå½’测试时对Cucumber工程的目录结构执行过½E‹è¿›è¡Œäº†ç ”ç©¶ã€?/p>
安装好CucumberåŽï¼Œå¦‚果在终端直接执行cucumber命ä×oåQŒå¾—åˆîC»¥ä¸‹è¾“出:
输出¾l“果表明åQšcucumber期待当å‰ç›®å½•下å˜åœ¨å为featuresçš„å目录。å¾å¥½featuresæ–‡äšg夹åŽåQŒé‡æ–°æ‰§è¡Œcucumber命ä×oåQŒè¾“出如下:
Cucumber˜q行æˆåŠŸåQŒä½†ç”׃ºŽfeaturesæ–‡äšg夹下没有ä»ÖM½•内容åQŒæ•…得到上述输出¾l“æžœã€?/p>
¾|‘上大多数关于Cucumber的教½E‹éƒ½å»ø™®®é‡‡ç”¨ä»¥ä¸‹ç›®å½•¾l“æž„åQŒæ‰€æœ‰çš„æ–‡äšgåQˆå¤¹åQ‰éƒ½ä½äºŽfeaturesæ–‡äšg夹下ã€?/p>
Featureæ–‡äšgåQˆå¦‚test.featureåQ‰ç›´æŽ¥ä½äºŽfeaturesæ–‡äšg夹下åQŒå¯ä»¥äØ“æ¯ä¸ªåº”用场景创å¾ä¸€ä¸ªFeatureæ–‡äšgåQ›ä¸ŽFeatureæ–‡äšg对应的Stepæ–‡äšgåQˆå¦‚test.rbåQ‰ä½äºŽstep_definitionsåæ–‡ä»¶å¤¹ä¸‹ï¼›åŒæ—¶åQŒå˜åœ¨supportåæ–‡ä»¶å¤¹åQŒå…¶ä¸‹çš„env.rbæ–‡äšg为环境酾|®æ–‡ä»¶ã€‚在˜q™æ ·çš„目录结构æ¡ä»¶ä¸‹æ‰§è¡Œcucumber命ä×oåQŒä¼šé¦–先执行env.rbåšå‰æœŸå‡†å¤‡å·¥ä½œï¼Œæ¯”如å¯ä»¥ç”¨Watir新律¹è§ˆå™¨çª—å£ï¼Œç„¶åŽCucumberž®†test.rbæ–‡äšgè¯Õd…¥å†…å˜åQŒæœ€åŽæ‰§è¡Œtest.featureæ–‡äšgåQŒå½“é‡åˆ°Given/When/Thenæ¥éª¤æ—Óž¼ŒCucumberž®†åœ¨test.rb䏿œç´¢æ˜¯å¦æœ‰ç›¸åº”çš„stepåQŒå¦‚果有åQŒåˆ™æ‰§è¡Œç›¸åº”çš„Ruby代ç ã€?/p>
˜q™æ ·çš„ç›®å½•ç»“æž„åªæ˜¯æŽ¨è的目录¾l“æž„åQŒç¬”者通过åå¤çš„试验得å‡ÞZº†ä»¥ä¸‹¾l“论åQšå¯¹äºŽCucumber而言åQŒé™¤äº†é¡¶å±‚çš„featuresæ–‡äšgå¤ÒŽ˜¯å¼ºåˆ¶æ€§çš„之外åQŒå…¶å®ƒç›®å½•ç»“æž„éƒ½ä¸æ˜¯å¼ºåˆ¶æ€§çš„åQŒCucumberž®†å¯¹featuresæ–‡äšg夹下的所有内容进行æ‰òq›_Œ–åQˆflattenåQ‰å¤„ç†å’Œé¦–å—æ¯æŽ’åºã€‚具体æ¥è¯ß_¼ŒCucumber在è¿è¡Œæ—¶åQŒé¦–先将递归的执行featuresæ–‡äšg夹下的所有Rubyæ–‡äšg(å…¶ä¸åˆ™åŒ…括Stepæ–‡äšg)åQŒç„¶åŽé€šè¿‡ç›¸åŒçš„æ–¹å¼æ‰§è¡ŒFeatureæ–‡äšg。但是,如果featuresæ–‡äšg夹下å˜åœ¨supportåæ–‡ä»¶å¤¹åQŒåƈ且support下有å䨓env.rb的文ä»Óž¼ŒCucumberž®†é¦–先执行该文äšgåQŒç„¶åŽæ‰§è¡Œsupport下的其它文äšgåQŒå†é€’归执行featues下的其它文äšgã€?/p>
比如有如下Cucumber目录¾l“æž„åQ?/p>
ä¸ÞZº†æ–¹ä¾¿è®°å½•Cucumber˜q行时的文äšg执行™åºåºåQŒåœ¨featuresæ–‡äšg夹下的所有Rubyæ–‡äšgä¸åŠ ä¸Šä»¥ä¸‹ä»£ç :
puts File.basename(__FILE__)
æ¤è¡Œä»£ç 的作用是在一个Rubyæ–‡äšgæ‰§è¡Œæ—¶è¾“å‡ø™¯¥æ–‡äšgçš„åå—ï¼Œæ¤æ—¶æ‰§è¡Œcucumber命ä×oåQŒå¾—åˆîC»¥ä¸‹è¾“出(部分åQ‰ç»“果:
上图å³äØ“Rubyæ–‡äšg的执行顺åºï¼Œå¯ä»¥çœ‹å‡ºåQŒsupportæ–‡äšg夹下env.rbæ–‡äšgé¦–å…ˆè¢«æ‰§è¡Œï¼Œå…¶æ¬¡æŒ‰ç…§å—æ¯æŽ’åºæ‰§è¡Œc.rbå’Œd.rbåQ›æŽ¥ä¸‹æ¥åQŒCucumberž®†featuresæ–‡äšg夹下的所用文ä»Óž¼ˆå¤¹ï¼‰æ‰åã^化,òq¶æŒ‰å—毙åºåºæŽ’åºåQŒä»Žè€Œå…ˆæ‰§è¡Œa.rbå’Œb.rbåQŒè€Œç”±äºŽotheræ–‡äšgå¤ÒŽŽ’在step_definitionsæ–‡äšg夹的å‰é¢åQŒæ‰€ä»¥å…ˆæ‰§è¡Œotheræ–‡äšg夹下的Rubyæ–‡äšgåQˆä¹Ÿæ˜¯æŒ‰å—毙åºåºæ‰§è¡ŒåQšå…ˆf.rbåQŒç„¶åŽg.rbåQ‰ï¼Œæœ€åŽæ‰§è¡Œstep_definitions下的e.rbã€?/p>
当执行完所有Rubyæ–‡äšgåŽï¼ŒCucumber开始例ơ读å–Featureæ–‡äšgåQŒæ‰§è¡Œé¡ºåºä¹Ÿå’Œå‰˜qîC¸€æ øP¼Œå? a.feature --> b.feature --> c.feature
½W”者还å‘现åQŒè¿™äº›Rubyæ–‡äšg甚至å¯ä»¥ä½äºŽfeaturesæ–‡äšg夹之外的ä»ÖM½•地方åQŒåªæ˜¯éœ€è¦åœ¨ä½äºŽfeaturesæ–‡äšg夹之内的Rubyæ–‡äšgä¸require一下,比如在env.rbä¸ã€?/p>
/** * Return an elements child given the key (context id), or uses the selector * to get the element. * * @param sel * @param key * Element id. * @return {@link AndroidElement} * @throws ElementNotFoundException */ public AndroidElement getElement(final UiSelector sel, final String key) throws ElementNotFoundException { AndroidElement baseEl; baseEl = elements.get(key); UiObject el; if (baseEl == null) { el = new UiObject(sel); } else { try { el = baseEl.getChild(sel); } catch (final UiObjectNotFoundException e) { throw new ElementNotFoundException(); } } if (el.exists()) { return addElement(el); } else { throw new ElementNotFoundException(); } } |