µ¥Ôª²âÊÔUnit Test
ºÜÔç¾ÍÖªµÀµ¥Ôª²âÊÔÕâÑùÒ»¸ö¸ÅÄµ«Ö±µ½¼¸¸öÔÂǰ£¬ÎÒÕæÕý¿ªÊ¼½Ó´¥ºÍʹÓÃËü¡£¾¿¾¹Ê²Ã´Êǵ¥Ôª²âÊÔ£¿ÎÒÏëÒ²ÐíºÜ¶àʹÓÃÁ˺ܾõÄÈËÒ²²»Ò»¶¨ÄÜÃèÊöµÄÊ®·ÖÇå³þ£¬ËùÒÔдÁËÕâÆªÎÄÕÂÀ´³¢ÊÔÃèÊöËüµÄÌØÕ÷ºÍÔÔò£¬ÒÔ°ïÖú¸ü¶àÈË¡£
ʲôÊǵ¥Ôª²âÊÔ£¿
ÏÈÀ´¿´¿´µ¥Ôª²âÊԵ͍Ò壬ÔÚά»ù°Ù¿ÆÓ¢ÎİæÖпÉÒÔÕÒµ½Kolawa AdamÔÚ Automated Defect
Prevention: Best Practices in Software Management Ò»ÊéÖжԵ¥Ôª²âÊԵ͍Ò壺
In computer programming, unit testing is a method by
which individual units of source code, sets of one or
more computer program modules together with associated
control data, usage procedures, and operating procedures
are tested to determine if they are fit for use.
ÖØµãÔÚÓÚ×îºó£¬µ¥Ôª²âÊÔµÄÄ¿µÄÏÔ¶øÒ×¼û£¬ÓÃÀ´È·¶¨ÊÇ·ñÊʺÏʹÓ᣶ø²âÊԵķ½·¨Ôò°üÀ¨¿ØÖÆÊý¾Ý£¬Ê¹ÓúͲÙ×÷¹ý³Ì¡£ÄÇôÒÔÎÒµÄÀí½â£¬Ã¿¸öµ¥Ôª²âÊÔ¾ÍÊÇÒ»¶ÎÓÃÓÚ²âÊÔÒ»¸öÄ£¿é»ò½Ó¿ÚÊÇ·ñÄÜ´ïµ½Ô¤ÆÚ½á¹ûµÄ´úÂë¡£¿ª·¢ÈËÔ±ÐèҪʹÓôúÂëÀ´¶¨ÒåÒ»¸ö¿ÉÓõĺâÁ¿±ê×¼£¬²¢ÇÒ¿ÉÒÔ¿ìËÙ¼ìÑé¡£
ºÜ¿ìÎÒ·¢ÏÖÓÐÒ»¸öÎóÇø£¬Ðí¶àÈËÈÏΪµ¥Ôª²âÊÔ±ØÐëÊÇÒ»¸örunner¼¯ÖÐÔËÐÐËùÓе¥ÔªµÄ²âÊÔ£¬²¢Ò»Ä¿ÁËÈ»¡£²»£¬Õâ½ö½öÊÇÒ»ÖÖ×Ô¶¯»¯µ¥Ôª²âÊÔµÄ×î¼Ñʵ¼ù£¬ÔÚһЩСÐÍÏîÄ¿Öе¥Ôª²âÊÔ¿ÉÄܽö½öÊÇÒ»×éÈ¥³ýÆäËûÌØÐԵĽӿڵ÷Óá£ÉõÖÁÔÚһЩͼÐδ¦Àí»ò²¼¾ÖµÄÏîÄ¿Öе¥Ôª²âÊÔ¿ÉÒÔ½áºÏ×ÔÉíÌØÐÔ±äµÄÊ®·ÖÓÐȤ£¬±ÈÈçMasonry£¬Ò»¸öÍø¸ñ²¼¾Ö¿â£¬ÔÚËüµÄµ¥Ôª²âÊÔÖв»ÊÇÒ»¸öºì»òÂ̵ÄÌõÄ¿£¬¶øÊÇÒ»ÐÐÒ»ÐеÄС¸ñ²¼¾ÖÓÃÒÔ˵Ã÷²¼¾Ö±»Íê³ÉµÄÊÂʵ£¬ÕâÑù±È´úÂë¼ì²é²¼¾ÖÊÇ·ñÕýÈ·ÔÙÒÔÑÕÉ«ÏÔʾ½á¹ûÀ´µÃ¸üÖ±¹Û¸ßЧ£¬Ò²±ÜÃâÁ˲âÊÔ³ÌÐò±¾ÉíµÄbugµ¼ÖµÄʧÎó¡£
´ò¸ö±È·½£¬µ¥Ôª²âÊÔ¾ÍÏñÒ»°Ñ³ß×Ó£¬µ±²âÁ¿µÄ¶ÔÏóÊÇÒ»¸öÇúÃæÊ±£¬Ò²Ðí¿ÉÒÔ»¨·Ñ´óÁ¦ÆøÈ¥½«Ëü³éÏó³ÉÆ½Ãæ£¬µ«ÎÒ¸üÌᳫÁ¿Éí¶¨×öÒ»°ÑÍäÇúµÄ³ß×ÓÈ¥ÊÊÓ¦Õâ¸öÇúÃæ¡£ÎÞÂÛÔõÑù£¬µ¥Ôª²âÊÔÊÇΪÁËÉú²ú´úÂë¶øÐ´£¬ËüÓ¦µ±×ã¹»µÄ×ÔÓɱ¼·Å£¬È¥ÊÊÓ¦¸÷ÖÖ¸÷ÑùµÄÉú²ú´úÂë¡£
ΪʲôҪµ¥Ôª²âÊÔ£¿
Ò²Ðí¶¨ÒåÖÐÒѾºÜÇå³þµÄÖ¸Ã÷ÁËÆäÒâÒ壬ȷÈÏij¶Î´úÂë»òÄ£¿é»ò½Ó¿ÚÊÇ·ñÊʺÏʹÓ㬵«ÎÒÏë»áÓиü¶àµÄÈËÈÏΪ£¬Ö±½ÓÔÚ²âÊÔ»·¾³ÖÐʹÓÃÈí¼þ¿ÉÒÔ¸ü¼ÓÈ·±£Èí¼þÊÇ·ñ¿ÉÓᣲ»£¬ÔÚʵ¼ÊʹÓùý³ÌÖлá°éËæ×ÅÒ»´óÅúµÄ¸½´ø²Ù×÷´óÁ¿Ôö¼Ó²âÊÔʱ¼ä£¬²¢ÇÒÎÞ·¨±£Ö¤Æä²âÊÔ¸²¸ÇÂÊ¡£ËùÒÔÎÒÈÏΪµ¥Ôª²âÊÔµÄÄ¿µÄ²¢²»½ö½öÊÇÈ·ÈÏÊÇ·ñ¿ÉÓ㬶øÊǸü¸ßЧ¸üÎȶ¨µÄÈ·ÈÏÆäÊÇ·ñ¿ÉÓá£
Ëæ×ÅÏîÄ¿¹æÄ£µÄÔö¼Ó£¬º¯Êý¡¢·½·¨¡¢±äÁ¿¶¼ÔÚµÝÔö£¬ÓÈÆäÊǽø¶ÈµÄ²»×㣬À´×Ô²úÆ·¾ÀíµÄѹÁ¦£¬»¹ÓÐQAËù´øÀ´µÄ¸÷ÖÖBug±¨¸æ»áÈÃÔ±¾Õû½àµÄ´úÂë±äµÃһƬ»ìÂÒ¡£ÎÒÉõÖÁ¼û¹ýͬһ¸ö½Ó¿ÚÒÔ²»Í¬µÄÃû³Æ³öÏÖÔÚ8¸ö²»Í¬µÄ¿ØÖÆÆ÷ÖС£ÕâʱҲÐíÎÒÃÇÊ×ÏÈÏëµ½µÄÊÇÖØ¹¹£¬¿ÉÊǵȵȣ¬ÔÚÖØ¹¹½áÊøÊ±ÎÒÃÇÈçºÎÈ·¶¨ÏîÄ¿½ö½öÊDZ»Öع¹ÁË£¬¶ø²»ÊDZ»¸ÄдÁË£¿´Ëʱµ¥Ôª²âÊÔ½«ÊÇÒ»¸ù¾ÈÃüµ¾²Ý£¬ËüÊÇÒ»¸öºâÁ¿±ê×¼£¬¸æËß¿ª·¢ÈËÔ±Õâô×öÊÇ·ñ½«¸Ä±ä½á¹û¡£
²»½ö½öÊÇÕâÑù¡£Ðí¶àÈËÈÏΪµ¥Ôª²âÊÔ£¬ÉõÖÁÕû¸ö²âÊÔ¶¼ÊÇÔÚ±àÂë½áÊøºóµÄÒ»µÀ¹¤Ðò£¬¶øÐÞ¸´bugÒ²²»¹ýÊÇÔÚ×öÀ¬»øÑÚÂñÒ»ÀàµÄ¹¤×÷¡£µ«²âÊÔÓ¦¸Ã°éËæÕû¸ö±àÂë»òÈí¼þÖÜÆÚ½øÐУ¬»¹Óн«ÔÚºóÃæÌáµ½µÄTDDÕâÑùÓÐȤµÄ¶«Î÷£¬µ¥Ôª²âÊÔ½«³¬Ç°ÓÚ±àÂë¡£ÎÒµÄÒâ˼ÊÇ£¬µ¥Ôª²âÊÔÓ¦¸ÃÊÇÒ»¸ö¿ò¼Ü¡¢±ê×¼£¬¾³£±»ÐÎÈݱ»½ÅÊּܣ¬Ïñ½¨ÖþÒ»Ñù£¬½ÅÊּܵĸ߶ÈÖÁÉÙÓ¦¸ÃºÍ´óÂ¥¸ß¶È²»ÏàÉÏÏ£¬ÉõÖÁÒ»¿ªÊ¼¾Í´îºÃ½ÅÊּܡ£
ÈçºÎ×öµ¥Ôª²âÊÔ£¿
ŪÇåÁ˵¥Ôª²âÊÔµÄÄ¿µÄºÍÒâÒ壬µ«ÈçºÎ¿ªÊ¼£¿ºÜ¼òµ¥£¬Ê×ÏÈËüÊÇÒ»¸ö¼ìÑ飬ËùÒÔÓ¦¸ÃÖ»ÓÐpass»òfailÁ½ÖÖÇé¿ö¡£¶ø¼ìÑéµÄ¶ÔÏóÓ¦¸ÃÊÇij¸ö½Ó¿Ú»òÄ£¿é£¬ËùÒÔÓ¦¸Ãµ÷ÓÃËü»ñµÃÒ»¸ö½á¹û¡£¼ìÑéÕâ¸ö½á¹û¾ÍÊǵ¥Ôª²âÊԵĻù±¾¶¯×÷£¬¾ÍÄÃÒ»¸ö³ý·¨º¯ÊýÀ´×öÀý×Ó£º
function division (a, b) { return a / b; } var result = division(4, 2); if (result === 2) { alert('pass'); } else { alert('fail'); } |
ÏÔÈ»£¬½«»áÌáʾpassͨ¹ý¡£µ«ÊÇÎÊÌâÀ´ÁË£¬Õâ¸ö²âÊÔµÄÓÃÀýÌ«µ¥Ò»ºÍÆÕͨÁË£¬Èç¹ûʹÓÃ0×ö³ýÊýÄØ£¿ÊÇNaN£¿»¹ÊÇInfinity£¿»òÕßÔÚʵ¼ÊʹÓÃʱ£¬²úÆ·ÐèÒªÒ»¸ö0À´´úÌæÕâÑùÒ»¸ö²»·ûºÏÊýѧ¸ÅÄîµÄ½á¹ûÈ¥ÊÊÓ¦±ØÐëΪÊý×ÖÀàÐ͵ÄijÖÖ¼ÆË㣬ÓÚÊÇdivision³öÏÖÁËÒ»¸öbug¡£ÁíÍâµ±¸²¸ÇÂÊÔö¼Ó£¬Ò²Òâζ×ÅÓÃÀýµÄÔö¼Ó£¬ÎÒÃÇÐèÒª°ÑifÌõ¼þÓï¾äÌá³öÀ´×ö³ÉÒ»¸öº¯Êý¶à´Îµ÷Ó᣻¹ÓÐalert·½·¨£¬Èç¹ûÓÃÀýÌ«¶à£¬ÎÒÏàÐÅÄã»áµãÈ·Èϵ㵽ÊÖÈí£¬Ò²Ðí¿ÉÒÔÖ±½ÓÏÔʾÔÚÒ³ÃæÉÏ¡£
ËùÒÔÎÒÌí¼ÓÁËÒ»¸ö¹ØÓÚ³ýÊýΪ0µÄÓÃÀý£¬²¢Öع¹ÁË´úÂ룺
function division (a, b) { if (b === 0) { return 0; } else { return a / b; } } function matcher (name, result, expect) { if (result === expect) { _print(name + '- pass'); } else { _print(name + '- fail'); } function _print (str) { var _bar = document.createElement('p'); _bar.innerText = str; document.body.appendChild(_bar); } } matcher('normal', division(4, 2), 2); matcher('zero', division(5, 0), 0); |
ÏÖÔÚ¿ÉÒÔʹÓÃmatcher·½·¨Ìí¼ÓÐí¶à²âÊÔÓÃÀý£¬²¢ÇÒ»¹ÄÜΪ¸ÃÓÃÀýÃüÃû£¬ÔÚÒ³ÃæÖÐÖ±½ÓÏÔʾÿ¸öÓÃÀýÊÇ·ñͨ¹ý¡£ÕâÑùÒ»¸ö»ù±¾µÄµ¥Ôª²âÊÔ¾ÍÍê³ÉÁË£¬µ±È»ËüµÄ¸²¸ÇÂÊ»¹Ô¶Ô¶²»¹»£¬ÕâÀï½ö×÷Ϊһ¸öÀý×Ó¡£ÁíÍâΪÁËÌá¸ßЧÂÊ»¹Ó¦¸ÃʹÓÃÑÕÉ«À´±ê¼ÇÊÇ·ñͨ¹ý£¬¿ÉÒÔһĿÁËÈ»¡£
²âÊÔÇý¶¯¿ª·¢
TDDÊÇTest Driven Development µÄËõд£¬Ò²¾ÍÊDzâÊÔÇý¶¯¿ª·¢¡£
ͨ³£´«Í³Èí¼þ¹¤³Ì½«²âÊÔÃèÊöΪÈí¼þÉúÃüÖÜÆÚµÄÒ»¸ö»·½Ú£¬²¢ÇÒÊÇÔÚ±àÂëÖ®ºó¡£µ«Ãô½Ý¿ª·¢´óʦKent BeckÔÚ2003Äê³ö°æÁË
Test Driven Development By Example Ò»Ê飬´Ó¶øÈ·Á¢Á˲âÊÔÇý¶¯¿ª·¢Õâ¸öÁìÓò¡£
TDDÐèÒª×ñÑÈçϹæÔò£º
дһ¸öµ¥Ôª²âÊÔÈ¥ÃèÊö³ÌÐòµÄÒ»¸ö·½Ãæ¡£
ÔËÐÐËüÓ¦¸Ã»áʧ°Ü£¬ÒòΪ³ÌÐò»¹È±ÉÙÕâ¸öÌØÐÔ¡£
ΪÕâ¸ö³ÌÐòÌí¼ÓһЩ¾¡¿ÉÄܼòµ¥µÄ´úÂë±£Ö¤²âÊÔͨ¹ý¡£
ÖØ¹¹Õⲿ·Ö´úÂ룬ֱµ½´úÂëûÓÐÖØ¸´¡¢´úÂëÔðÈÎÇåÎú²¢Çҽṹ¼òµ¥¡£
³ÖÐøÖØ¸´ÕâÑù×ö£¬»ýÀÛ´úÂë¡£
ÁíÍ⣬ºâÁ¿ÊÇ·ñʹÓÃÁËTDDµÄÒ»¸öÖØÒª±ê×¼ÊDzâÊÔ¶Ô´úÂëµÄ¸²¸ÇÂÊ£¬¸²¸ÇÂÊÔÚ80%ÒÔÏÂ˵Ã÷Ò»¸öÍŶÓûÓгä·ÖÕÆÎÕTDD£¬µ±È»¸ß¸²¸ÇÂÊÒ²²»ÄÜ˵һ¶¨Ê¹ÓÃÁËTDD£¬Õâ½ö½öÊÇÒ»¸ö²Î¿¼Ö¸±ê¡£
ÔÚÎÒ¿´À´£¬TDDÊÇÒ»ÖÖ¿ª·¢¼¼Êõ£¬¶ø·Ç²âÊÔ¼¼Êõ£¬ËùÒÔËü¶ÔÓÚ´úÂë¹¹½¨µÄÒâÒåÔ¶´óÓÚ´úÂë²âÊÔ¡£Ò²Ðí×îÖյĴúÂëºÍÏÈ¿ª·¢ÔÙ²âÊÔдµÄ²âÊÔ´úÂë»ù±¾Ò»Ö£¬µ«ËüÃÇÈÔÈ»ÊÇÓкܴó²»Í¬µÄ¡£TDD¾ßÓкÜÇ¿µÄÄ¿µÄÐÔ£¬ÔÚÖ±½Ó½á¹ûµÄÖ¸µ¼Ï¿ª·¢Éú²ú´úÂ룬Ȼºó²»¶ÏÎ§ÈÆÕâ¸öÄ¿±êÈ¥¸Ä½ø´úÂ룬ÆäÓÅÊÆÊǸßЧºÍÈ¥ÈßÓàµÄ¡£ËùÒÔÆäÌØµãÓ¦¸ÃÊÇÓÉÐèÇóµÃ³ö²âÊÔ£¬ÓɲâÊÔ´úÂëµÃ³öÉú²ú´úÂë¡£´ò¸ö±È·½¾ÍÏñÊÇ×ÔÐгµµÄÁ½¸öÂÖ×Ó£¬ËäÈ»¶¼ÊÇÔÚÏòͬһ¸ö·½Ïòת¶¯£¬µ«ÊǺóÂÖÊÇÊ©Á¦µÄ£¬´ø¶¯³µ×ÓÏòǰ£¬¶øÇ°ÂÖÊÇÊÜÁ¦µÄ£¬±»ÏòǰµÄ³µ×Ó´ø¶¯¶ø×ª¡£
ÐÐΪÇý¶¯¿ª·¢
ËùνµÄBDDÐÐΪÇý¶¯¿ª·¢£¬¼´Behaviour Driven Development£¬ÊÇÒ»ÖÖеÄÃô½Ý¿ª·¢·½·¨¡£Ëü¸üÇ÷ÏòÓÚÐèÇó£¬ÐèÒª¹²Í¬ÀûÒæÕߵIJÎÓ룬ǿµ÷Óû§¹ÊÊ£¨User
Story£©ºÍÐÐΪ¡£2009Ä꣬ÔÚÂ×¶Ø·¢±íµÄ¡°Ãô½Ý¹æ¸ñ£¬BDDºÍ¼«ÏÞ²âÊÔ½»Á÷¡±[3]ÖУ¬Dan North¶ÔBDD¸ø³öÁËÈç϶¨Ò壺
BDDÊǵڶþ´úµÄ¡¢ÓÉÍâ¼°Äڵġ¢»ùÓÚÀ(pull)µÄ¡¢¶à·½ÀûÒæÏà¹ØÕßµÄ(stakeholder)¡¢¶àÖÖ¿ÉÀ©Õ¹µÄ¡¢¸ß×Ô¶¯»¯µÄÃô½Ý·½·¨¡£ËüÃèÊöÁËÒ»¸ö½»»¥Ñ»·£¬¿ÉÒÔ¾ßÓдøÓÐÁ¼ºÃ¶¨ÒåµÄÊä³ö£¨¼´¹¤×÷Öн»¸¶µÄ½á¹û£©£ºÒѲâÊÔ¹ýµÄÈí¼þ¡£
ÁíÍâ×îÖ÷¹ÛµÄÇø±ð¾ÍÊÇÓôʣ¬¡®example¡¯È¡´úÁË¡®test¡¯£¬¡®describe¡¯È¡´úÁË¡®class¡¯£¬¡®behaviour¡¯È¡´úÁË¡®method¡¯µÈµÈ¡£ÕâÕýÊÇÆäÌØÕ÷Ö®Ò»£¬×ÔÈ»ÓïÑԵļÓÈ룬ʹµÃ·Ç³ÌÐòÈËÔ±Ò²ÄܲÎÓëµ½²âÊÔÓÃÀýµÄ±àдÖÐÀ´£¬Ò²´ó´ó½µµÍÁ˿ͻ§¡¢Óû§¡¢ÏîÄ¿¹ÜÀíÕßÓ뿪·¢ÕßÖ®¼äÀ´»Ø·ÒëµÄ³É±¾¡£
¼òµ¥À´Ëµ£¬ÎÒÈÏΪBDD¸ü¼Ó×¢ÖØÒµÎñÐèÇó¶ø²»ÊǼ¼Êõ£¬ËäÈ»¿´ÆðÀ´BDDȷʵÊDZÈATDD×öµÄ¸üºÃ£¬µ«ÕâÊÇÒ»ÖÖÎóµ¼£¬Õâ½ö½öÊǾÍijÖÖ»·¾³Ï¶øÑԵġ£¶øÇÒÒÔ¹úÄÚµÄÏÖ×´À´¿´TDDÒª±ÈBDD¸üÊʺϣ¬ÒòΪËü²»ÐèÒªËùÓÐÈËÔ±µÄÀí½âºÍ¼ÓÈë¡£
µ¥Ôª²âÊÔ¿ò¼Ü
ÎÞÂÛÈçºÎ£¬µ¥Ôª²âÊÔÓÀÔ¶ÊÇÉÙ²»Á˵ġ£ÆäʵÔÚµ¥Ôª²âÊÔÖвâÊÔ´úÂëºÍÉú²ú´úÂëÓ¦¸ÃÊǵÈÁ¿µÄ£¬ÕýÈçRobert C.
MartinÔÚÆä Clean Code: A Handbook of Agile Software Craftsmanship
Ò»ÊéÖÐËùд£º
²âÊÔ±ØÐëËæÉú²ú´úÂëµÄÑݽø¶øÐ޸쬲âÊÔÔ½Ôà¾ÍÔ½ÄÑÐÞ¸Ä
ÓÚÊÇеIJâÊÔºÜÄѱ»¼ÓÈëÆäÖУ¬²âÊÔ´úÂëµÄά»¤±äµÃÒì³£À§ÄÑ£¬×îÖÕÔÚ¸÷ÖÖѹÁ¦Ö®ÖÐÖ»ÓÐÈÓµô²âÊÔ´úÂë×é¡£µ«ÊÇûÓÐÁ˲âÊÔ´úÂ룬¾ÍʧȥÁËÈ·±£¶Ô´úÂëµÄ¸Ä¶¯ÄÜÈçÔ¸ÒÔ³¥µÄÄÜÁ¦£¬¸÷ÖÖÎÊÌâËæÖ®¶øÀ´¡£Òò´Ë£¬µ¥Ôª²âÊÔÒ²ÐèÒªÒ»ÖÖÐÐÖ®ÓÐЧµÄʵ¼ùÀ´È·±£ÆäÖÊÁ¿ºÍ¿Éά»¤ÐÔ¡£
ËùÒÔÕýÈçÉú²ú´úÂëÒ»Ñù£¬²âÊÔ´úÂëÒ²Óпò¼Ü£¬ÏÂÃæ½éÉܼ¸ÖÖÖ÷Á÷µÄJavascriptµÄµ¥Ôª²âÊÔ¿ò¼Ü¡£
Jasmine
ÓÐÒ»Àà¿ò¼Ü½Ð×öxUnit£¬À´Ô´ÓÚÖøÃûµÄJAVA²âÊÔ¿ò¼ÜJUnit£¬xUnitÔò´ú±íÁËÒ»ÖÖģʽ£¬²¢ÇÒʹÓÃÕâÑùµÄÃüÃû¡£ÔÚJavascriptÖÐÒ²ÓÐÕâÑùµÄÒ»¸öÀÏÅÆ¿ò¼ÜJsUnit£¬ËûµÄ×÷ÕßÊÇEdward
HieattÀ´×ÔPivotal Labs£¬µ«ÔÚ¼¸ÄêǰJsUnit¾ÍÒѾֹͣά»¤ÁË£¬ËûÃÇ´øÀ´ÁËеÄBDD¿ò¼ÜJasmine¡£
Jasmine²»ÒÀÀµÓÚÈκοò¼Ü£¬ËùÒÔÊÊÓÃÓÚËùÓеÄJavascript´úÂ롣ʹÓÃÒ»¸öÈ«¾Öº¯Êý describe
À´ÃèÊöÿ¸ö²âÊÔ£¬²¢ÇÒ¿ÉÒÔǶÌס£describeº¯ÊýÓÐ2¸ö²ÎÊý£¬Ò»¸öÊÇ×Ö·û´®ÓÃÓÚÃèÊö£¬Ò»¸öÊǺ¯ÊýÓÃÓÚ²âÊÔ¡£Ôڸú¯ÊýÖпÉÒÔʹÓÃÈ«¾Öº¯Êý
it À´¶¨ÒåSpecs£¬Ò²¾ÍÊǵ¥Ôª²âÊÔµÄÖ÷ÒªÄÚÈÝ£¬ ʹÓà expect º¯ÊýÀ´²âÊÔ£º
describe('A suite', function () { it('is a spec', function () { var a = true; expect(a).toBe(true); }); }); |
ÁíÍâÈç¹ûÏëÈ¥µôij¸ödescribe£¬ÎÞÐë×¢Ê͵ôÕû¶Î´úÂ룬ֻÐèÒªÔÚdescribeÇ°Ãæ¼ÓÉÏx¼´¿ÉºöÂÔ¸Ãdescribe¡£
Matcher
toBe·½·¨ÊÇÒ»¸ö»ù±¾µÄ matcher ÓÃÀ´¶¨ÒåÅжϹæÔò£¬¿ÉÒÔ¿´µÃ³öÀ´JasmineµÄ·½·¨ÊǷdz£ÓïÒ廯µÄ£¬¡°expect
¡®a¡¯ to be true¡±£¬Èç¹ûÏëÅжϷñ¶¨Ìõ¼þ£¬ÔòÖ»ÐèÒªÔÚtoBeǰµ÷Óà not ·½·¨£º
expect(a).not().toBe(false); |
³ýÁËtoBeÕâÑù»ù±¾µÄ»¹ÓÐÐí¶àÆäËûµÄMatcher£¬±ÈÈç toEqual ¡£ºÜ¶à³õѧJasmine»áŪ²»ÇåºÍtoBeµÄÇø±ð£¬Ò»¸ö¼òµ¥µÄÀý×Ó¾ÍÄÜÃ÷°×ËüÃǵÄÇø±ð£º
expect({}).not().toBe({}); expect({}).toEqual({}); |
Ò»¸öн¨µÄObject²»ÊÇ£¨not to be£©ÁíÒ»¸öн¨µÄObject£¬µ«ÊÇËüÃÇÊÇÏàµÈ£¨to equal£©µÄ¡£»¹ÓÐ
toMatch ¿ÉÒÔʹÓÃ×Ö·û´®»òÕßÕýÔò±í´ïʽÀ´ÑéÖ¤£¬ÒÔ¼°ÆäËûÒ»Ð©ÌØÊâÑéÖ¤£¬±ÈÈçundefined»òÕßbooleanµÄÅжϣ¬
toThrow ¿ÉÒÔ¼ì²éº¯ÊýËùÅ׳öµÄÒì³£¡£ÁíÍâJasmine»¹Ö§³Ö×Ô¶¨ÒåMatcher£¬ÒÔNaNµÄ¼ì²éΪÀý£¬ÏñÕâÑùʹÓÃbeforeEach·½·¨ÔÚÿ¸ö²âÊÔÖ´ÐÐǰÌí¼ÓÒ»¸ömatcher£º
beforeEach(function () { this.addMatchers({ toBeNaN: function (expected) { return isNaN(expected); } }); }); |
¿ÉÒÔÏëµ½£¬Æä²ÎÊýexpectedÊÇ´«ÈëµÄÒ»¸öÆÚÍûµÄ×ÖÃæÁ¿£¬¶øÔÚexpect·½·¨Öд«ÈëµÄ²ÎÊý£¬¿ÉÒÔͨ¹ý
this.acturl »ñÈ¡£¬ÊÇ·ñµ÷ÓÃÁË not ·½·¨Ôò¿ÉÒÔͨ¹ý this.isNot »ñÈ¡£¬ÕâÊÇÒ»¸öbooleanÖµ¡£×îºó²âÊÔÊä³öµÄʧ°ÜÐÅÏ¢Ó¦¸ÃʹÓÃ
this.message À´¶¨Ò壬²»¹ýËüÊÇÒ»¸öfunction£¬È»ºóÔÚÆäÖзµ»ØÒ»¸öÐÅÏ¢¡£ËùÒÔ¼ÌÐøÔö½øtoBeNaN£º
beforeEach(function () { this.addMatchers({ toBeNaN: function (expected) { var actual = this.actual; var not = this.isNot ? ' not' : ''; this.message = function () { return 'Expected ' + actual + not + ' to be NaN ' + expected; }; return isNaN(expected); } }); }); |
ÕâÑùÒ»¸öÍêÕûµÄmatcher¾Í´´½¨³ÉÁË¡£
ÁíÍâÐèҪ˵Ã÷µÄÊǶÔÓ¦beforeEachÊÇÔÚÿ¸öspec֮ǰִÐУ¬ afterEach ·½·¨ÔòÊÇÔÚÿ¸öspecÖ®ºóÖ´ÐС£ÕâÊÇÒ»ÖÖAOP£¬¼´ÃæÏò·½ÃæµÄ±à³Ì£¨Aspect
Oriented Programming£©¡£±ÈÈçÓÐʱºòΪÁ˲âÊÔÒ»¸ö¶ÔÏ󣬿ÉÄÜÐèÒª¶à´Î´´½¨ºÍÏú»ÙËü£¬ËùÒÔΪÁ˱ÜÃâÈßÓà´úÂ룬ʹÓÃËüÃÇÊÇ×î¼ÑÑ¡Ôñ¡£
»¹¿ÉÒÔʹÓà jasmine.any ·½·¨À´´ú±íÒ»ÀàÊý¾Ý´«ÈëmatcherÖУ¬±ÈÈç
expect(123).toEqual(jasmine.any(Number)); expect(function () {}).toEqual(jasmine.any(Function)); |
Spy·½·¨
Ò»¸öSpyÄܼà²âÈκÎfunctionµÄµ÷ÓúͻñÈ¡Æä²ÎÊý¡£ÕâÀïÓÐ2¸öÌØÊâµÄMatcher£¬ toHaveBeenCalled
¿ÉÒÔ¼ì²éfunctionÊÇ·ñ±»µ÷Óùý£¬»¹ÓÐ toHaveBeenCalledWith ¿ÉÒÔ´«Èë²ÎÊý¼ì²éÊÇ·ñºÍÕâЩ²ÎÊýÒ»Æð±»µ÷Óùý£¬ÏñÕâÑùʹÓÃ
spyOn À´×¢²áÒ»¸ö¶ÔÏóÖеķ½·¨£º
var foo, a = null; beforeEach(function () { var foo = { set: function (str) { a = str; } } spyOn(foo, 'set'); foo.set(123); }); it('tracks calls', function () { expect(foo.set).toHaveBeenCalled(); expect(foo.set).toHaveBeenCalled(123); expect(foo.set.calls[0].args[0]).toEqual(123); expect(foo.set.mostRecentCall.args[0]).toEqual(123); expect(a).toBeNull(); }); |
ÔÚ²âÊÔʱ¸Ãfunction½«´øÓÐÒ»¸ö±»µ÷ÓõÄÊý×é calls £¬¶ø args Êý×é¾ÍÊǵ÷ÓÃʱ´«ÈëµÄ²ÎÊý£¬ÁíÍâÌØÊâÊôÐÔ
mostRencentCall Ôò´ú±í×îºóÒ»´Îµ÷Ó㬺Ícalls[calls.length]Ò»Ö¡£ÐèÒªÌØ±ð×¢ÒâµÄÊÇ£¬ÕâЩµ÷Óý«²»»á¶Ô±äÁ¿²úÉú×÷Óã¬ËùÒÔ
a ÈÔΪnull¡£
Èç¹ûÐèÒªµ÷ÓòúÉúʵ¼ÊµÄ×÷Ó㬿ÉÒÔÔÚspyOn·½·¨ºóµ÷Óà andCallThrough ·½·¨¡£»¹¿ÉÒÔͨ¹ýµ÷ÓÃ
andReturn ·½·¨É趨һ¸ö·µ»ØÖµ¸øfunction¡£ andCallFake Ôò¿ÉÒÔ´«ÈëÒ»¸öfunction×÷Ϊ²ÎÊýÈ¥´úÌæÔ±¾µÄfunction¡£
spyOn(foo, 'set').andCallThrough(); |
ÉõÖÁÔÚûÓÐfunctionµÄʱºò¿ÉÒÔʹÓÃJasmineµÄ createSpy ºÍ createSpyObj
´´½¨Ò»¸öspy£º
foo = jasmine.createSpy('foo'); obj = jasmine.createSpyObj('obj', [set, do]);
foo(123);
obj.set(123);
obj.do(); |
ÆäЧ¹ûÏ൱ÓÚspyOnʹÓÃÔÚÁËÒÑ´æÔÚµÄfunctionÉÏ¡£
ʱ¼ä¿ØÖÆ
ÉÏÃæµÄ·½·¨¶¼ÔÚ³ÌÐò˳ÐòÖ´ÐеÄǰÌáÏÂÖ´ÐУ¬µ« setTimeout ÒÔ¼° setInterval Á½¸ö·½·¨»áʹ´úÂë·ÖÀëÔÚʱ¼äÖáÉÏ¡£ËùÒÔJasmineÌṩÁË
Clock ·½·¨À´Ä£Äâʱ¼ä£¬ÒÔ»ñÈ¡setTimeoutµÄ²»Í¬×´Ì¬¡£
beforeEach(function () { jasmine.Clock.useMock(); }); it('set time', function () { var str = 0; setTimeout(function () { str++; }, 100); expect(str).toEqual(0); jasmine.Click.tick(101); expect(str).toEqual(1); jasmine.Click.tick(200); expect(str).toEqual(3); }); |
ʹÓÃClockµÄ·½·¨ useMock À´¿ªÊ¼Ê±¼ä¿ØÖÆ£¬È»ºóÔÚitÖÐʹÓà tick ·½·¨À´ÍƽøÊ±¼ä¡£
Òì²½
Javascript×î´óµÄÌØÉ«Ö®Ò»¾ÍÊÇÒì²½£¬Ö®Ç°½éÉܵķ½·¨Èç¹û´æÔÚÒì²½µ÷Ó㬴󲿷ֲâÊÔʱ¿ÉÄܻ᲻ͨ¹ý¡£Òò´Ë£¬ÐèÒªµÈÒì²½»Øµ÷Ö®ºóÔÙ½øÐвâÊÔ¡£
JasmineÌṩÁË runs ºÍ waitsFor Á½¸ö·½·¨À´Íê³ÉÕâ¸öÒì²½µÄµÈ´ý¡£ÐèÒª½«waitsFor·½·¨¼ÐÔÚ¶à¸öruns·½·¨ÖУ¬runs·½·¨ÖеÄÓï¾ä»á°´Ë³ÐòÖ±½ÓÖ´ÐУ¬È»ºó½øÈëwaitsFor·½·¨£¬Èç¹ûwaitsFor·µ»Øfalse£¬Ôò¼ÌÐøÖ´ÐÐwaitsFor£¬Ö±µ½·µ»Øtrue²ÅÖ´ÐкóÃæµÄruns·½·¨¡£
var cb = false; var ajax = { success: function () { cb = true; } }; spyOn(ajax, 'success'); it('async callback', function () { runs(function () { _toAjax(ajax); }); waitsFor(function () { return ajax.success.callCount > 0; }); runs(function () { expect(cb).toBeTruthy(); }); }); |
Èç´Ë£¬Ö»ÒªÔÚwaitsForÖÐÅжϻص÷º¯ÊýÊÇ·ñ±»µ÷ÓÃÁ˼´¿ÉÍê³ÉÒì²½²âÊÔ¡£ÉÏÃæ´úÂëÖÐÎÒʹÓÃÒ»¸ö·½·¨ÃûÖ±½Ó´úÌæÁËajaxÇëÇó·½·¨À´Ëõ¼õ²»±ØÒªµÄ´úÂë¡£ÔÚµÚÒ»¸öruns·½·¨Öз¢³öÁËÒ»¸öajaxÇëÇó£¬È»ºóÔÚwaitsForÖеȴýÆä±»µ÷Ó㬵±µÚ¶þ¸örunsÖ´ÐÐʱ˵Ã÷»Øµ÷º¯ÊýÒѾ±»µ÷ÓÃÁË£¬½øÐвâÊÔ¡£
Qunit
ËüÊÇÓÉjQueryÍŶӿª·¢µÄÒ»¿î²âÊÔÌ×¼þ£¬×î³õÒÀÀµÓÚjQuery¿â£¬ÔÚ2009ÄêʱÍÑÀëjQueryµÄÒÀÀµ£¬±ä³ÉÁËÒ»¸öÕæÕýµÄ²âÊÔ¿ò¼Ü£¬ÊÊÓÃÓÚËùÓÐJavascript´úÂë¡£
Qunit²ÉÓöÏÑÔ£¨Assert£©À´½øÐвâÊÔ£¬Ïà±ÈÓÚJasmineµÄmatcher¸ü¼Ó¶àµÄÀàÐÍ£¬Qunit¸ü¼¯ÖÐÔÚ²âÊԵĶÈÉÏ¡£
deepEqual ÓÃÓڱȽÏһЩ×ÝÏòÊý¾Ý£¬±ÈÈçObject»òÕßFunctionµÈ¡£¶ø×î³£ÓÃµÄ ok ÔòÖ±½ÓÅжÏÊÇ·ñΪtrue¡£Òì²½·½ÃæQunitÒ²ºÜÓÐȤ£¬Í¨¹ý
stop À´Í£Ö¹²âÊԵȴýÒì²½·µ»Ø£¬È»ºóʹÓà start ¼ÌÐø²âÊÔ£¬ÕâÒª±ÈJasmineµÄ¹ý³Ì»¯µÄµÈ´ý¸ü×ÔÓÉһЩ£¬²»¹ýÓÐʱҲÐí»á¸üÄÑдһЩ¡£Qunit»¹ÓµÓÐ3×éAOPµÄ·½·¨(
done ºÍ 'begin' )À´¶ÔÓ¦ÓÚÕû¸ö²âÊÔ£¬²âÊÔºÍÄ£¿é¡£
¶ÔÓÚFunctionµÄ¸ú×Ù²âÊÔ£¬QunitËÆºõÍêȫûÓп¼ÂÇ¡£²»¹ý¿ÉÒÔʹÓÃÁíÍâÒ»¸ö²âÊÔ¿ò¼ÜΪQunit´øÀ´µÄ²å¼þ
sinon-qunit¡£ÕâÑù¾Í¿ÉÒÔÔÚtestÖÐʹÓà spy ·½·¨ÁË¡£
Sinon
Sinon²¢²»ÊÇÒ»¸öµäÐ͵ĵ¥Ôª²âÊÔ¿ò¼Ü£¬¸üÏñÒ»¸ö¿â£¬×îÖ÷ÒªµÄÊǶÔFunctionµÄ²âÊÔ£¬°üÀ¨ Spy
ºÍ Stub Á½¸ö²¿·Ö£¬SpyÓÃÓÚÕì²âFunction£¬¶øStub¸üÏñÊÇÒ»¸öSpyµÄ²å¼þ»òÕßÖúÊÖ£¬ÔÚFunctionµ÷ÓÃǰºó×öÒ»Ð©ÌØÊâµÄ´¦Àí£¬±ÈÈçÐÞ¸ÄÅäÖûòÕ߻ص÷¡£ËüÕýºÃ¼«´óµÄÃÖ²¹ÁËQunitµÄ²»×㣬ËùÒÔͨ³£»áʹÓÃQunit+SinonÀ´½øÐе¥Ôª²âÊÔ¡£
ÖµµÃÒ»ÌáµÄÊÇ£¬SinonµÄ×÷ÕßChristian Johansen¾ÍÊÇ Test-Driven JavaScript
Development Ò»ÊéµÄ×÷Õߣ¬Õâ±¾ÊéÕë¶ÔJavascriptºÜÏêϸµÄÃèÊöÁ˵¥Ôª²âÊÔµÄÿ¸ö»·½Ú¡£
Mocha
ËüµÄ×÷Õß¾ÍÊÇÔÚGithubÉÏ·ÛË¿6KµÄ³¬¼¶Jser TJ Holowaychuk£¬¿ÉÒÔÔÚËûµÄÒ³ÃæÉÏ¿´µ½¹ýÈ¥Ò»ÄêµÄÌá½»Á¿ÊÇ5700¶à£¬ÓµÓÐ300¶à¸öÏîÄ¿£¬ÎÞÂÛÊÇ˶¼ÄÑÒÔÏëÏóËûÊÇÈçºÎ½øÐÐcodingµÄ¡£
ÀíËùµ±È»µÄ£¬Mocha³äÂúÁËGeek¸Ð£¬²»µ«¿ÉÒÔÔÚbashÖнøÐвâÊÔ£¬¶øÇÒ»¹ÓµÓÐÒ»ÕûÌ×ÃüÁî¶Ô²âÊÔ½øÐвÙ×÷¡£ÉõÖÁʹÓÃ
diff ¿ÉÒԲ鿴µ±Ç°²âÊÔÓëÉÏÒ»´Î³É¹¦²âÊԵĴúÂë²»Ò»Ö¡£
²»½ö½öÊÇÕâÑù£¬Mocha·Ç³£µÃ×ÔÓÉ¡£Mocha½«¸ü¶àµÄ·½·¨¼¯ÖÐÔÚÁËdescribeºÍitÖУ¬±ÈÈçÒì²½µÄ²âÊԾͷdz£°ô£¬ÔÚitµÄ»Øµ÷º¯ÊýÖлá»ñȡһ¸ö²ÎÊý
done £¬ÀàÐÍÊÇfunction£¬ÓÃÓÚÒì²½»Øµ÷£¬µ±Ö´ÐÐÕâ¸öº¯Êýʱ¾Í»á¼ÌÐø²âÊÔ¡£»¹¿ÉÒÔʹÓà only ºÍ
skip ȥѡÔñ²âÊÔʱÐèÒªµÄ²¿·Ö¡£MochaµÄ½Ó¿ÚÒ²Ò»Ñù×ÔÓÉ£¬³ýÁË BDD ·ç¸ñºÍJasmineÀàËÆµÄ½Ó¿Ú£¬»¹ÓÐ
TDD ·ç¸ñµÄ £¨suite test setup teardown suiteSetup suiteTeardown£©£¬»¹ÓÐAMD·ç¸ñµÄ
exports£¬Qunit·ç¸ñµÈ¡£Í¬Ê±²âÊÔ±¨¸æÒ²¿ÉÒÔÈÎÒâ×éÖ¯£¬ÎÞÂÛÊÇÁÐ±í¡¢½ø¶ÈÌõ¡¢»¹ÊÇ·É»úÅܵÀÕâÑùÆæÌØµÄÑùʽ¶¼¿ÉÒÔÔÚbashÖÐÏÔʾ¡£
ǰ¶Ë²âÊÔ¹¤¾ß
Client/Server ²âÊÔ
Ïà±ÈÓÚ·þÎñ¶Ë¿ª·¢£¬Ç°¶Ë¿ª·¢ÔÚ²âÊÔ·½ÃæÊ¼ÖÕÃæÁÙ×ÅÒ»¸öÑϾþµÄÎÊÌ⣬ÄǾÍÊÇä¯ÀÀÆ÷¼æÈÝÐÔ¡£Paul IrishÔø·¢±íÎÄÕÂBrowser
Market Pollution: IE[x] Is the New IE6²ûÊöÁËÒ»¸öÆæ¹ÖµÄÉèÏ룬δÀ´Äã¿ÉÄÜÐèÒªÔÚ76¸öä¯ÀÀÆ÷ÉÏ¿ª·¢£¬ÒòΪÿ´ÎIEµÄа汾¶¼ÊÇÒ»¸öÌØ±ðµÄä¯ÀÀÆ÷£¬¶øÇÒ»¹ÓÐËü¶Ô֮ǰËùÓа汾µÄ¼æÈÝģʽҲÊÇÒ»Ñù¡£ËäȻûÈËÈÏΪ΢Èí»á¼ÌÐøÈç´ËÓÞ´À£¬²»¹ýÕâҲ˵Ã÷ÁËÒ»¸öÎÊÌ⣬ǰ¶Ë¿ª·¢ÖÐä¯ÀÀÆ÷¼æÈÝÐÔÊÇÒ»¸öÓÀÔ¶µÄÎÊÌ⣬¶øÇÒÎÒÈÏΪ¼´Ê¹½â¾öÁËä¯ÀÀÆ÷µÄ¼æÈÝÐÔÎÊÌ⣬δÀ´ÔÚÒÆ¶¯¿ª·¢·½Ã棬É豸¼æÈÝÐÔÒ²ÊÇÒ»¸öÎÊÌâ¡£
ËùÒÔÔÚ×Ô¶¯»¯²âÊÔ·½ÃæÒ²ÊÇÈç´Ë£¬¼´Ê¹ËùÓеĵ¥Ôª²âÊÔ¼¯ÖÐÔÚÁËÒ»¸örunnerÖУ¬Ç°¶Ë²âÊÔÈÔÈ»ÒªÃæ¶ÔÖÁÉÙ4¸öä¯ÀÀÆ÷ÄÚºËÒÔ¼°3¸öµçÄÔ²Ù×÷ϵͳ¼Ó2¸ö»ò¸ü¶àÒÆ¶¯²Ù×÷ϵͳ£¬ºÎ¿ö»¹ÓÐÁîÒÆ¶¯¿ª·¢ÈËԱͷÌÛµÄAndroidµÄË鯬»¯ÎÊÌâ¡£²»¹ý¿ÉÒÔ°²ÐĵÄÊÇ£¬ÔçÒÑ´æÔÚÕâÑùµÄ¹¤¾ß¿ÉÒÔ²¶»ñ²»Í¬É豸ÉϵIJ»Í¬ä¯ÀÀÆ÷£¬²¢Ê¹Ö®ËæÊ±¸üвâÊÔ½á¹û£¬ÉõÖÁ¿ÉÒÔÔÚÒ»¸öÖÕ¶ËÉÏ¿´µ½ËùÓнá¹û¡£
¹¤¾ß½éÉÜ
JSTD£¨Javascript Test Driver£©ÊÇÒ»¸ö×îÔçµÄC/S²âÊÔ¹¤¾ß£¬À´×ÔGoogle£¬»ùÓÚJAVA±àд£¬¿çƽ̨£¬Ê¹ÓÃÃüÁîÐпØÖÆ£¬»¹ÓÐºÜºÃµÄ±à¼Æ÷Ö§³Ö£¬×î³£ÓÃÓÚeclipse¡£²»¹ýËüÎÞ·¨ÏÔʾ²âÊÔ¶ÔÏóµÄÉ豸¼°ä¯ÀÀÆ÷°æ±¾£¬Ö»ÓÐä¯ÀÀÆ÷ÃûÊDz»¹»µÄ¡£ÁíÍâJSTDÒѾÂýÂý²»ÔÙ»îÔ¾£¬ËüµÄÔçÕýÈçËüµÄÀÏ¡£
GoogleµÄйóKarma³öÏÖÁË£¬ËüʹÓÃNodejs¹¹½¨£¬Òò´Ë¿çƽ̨£¬»¹Ö§³ÖPhantomJSä¯ÀÀÆ÷£¬»¹Ö§³Ö¶àÖÖ¿ò¼Ü£¬°üÀ¨ÒÔÉϽéÉܵÄJasmine¡¢QunitºÍMocha¡£Ò»´Î¿ÉÒÔÔÚ¶à¸öä¯ÀÀÆ÷¼°É豸ÖнøÐвâÊÔ£¬²¢¿ØÖÆä¯ÀÀÆ÷ÐÐΪºÍ²âÊÔ±¨¸æ¡£ËäÈ»Ëü²»Ö§³ÖNodejsµÄ²âÊÔ£¬²»¹ýûʲôӰÏ죬ÒòΪNodejs²¢²»ÒÀÀµÓÚä¯ÀÀÆ÷¡£
»¹ÓÐTestSwarm£¬³ö×ÔjQueryÖ®¸¸John ResigÖ®ÊÖ£¬¿´À´jQueryµÄÇ¿´ó¹ûÈ»²»ÊÇżȻµÄ£¬ÔÚ²âÊÔ·½Ãæ·Ç³£µ½Î»£¬¸÷ÖÖ¹¤¾ßÆëÈ«¡£Ëü×îÌØ±ðµÄµØ·½ÔÚÓÚËùÓвâÊÔ»·¾³ÓÉ·þÎñÆ÷Ìṩ£¬°üÀ¨¸÷ÖÖ°æ±¾µÄÖ÷Á÷ä¯ÀÀÆ÷ÒÔ¼°iOS5µÄiphoneÉ豸£¬²»¹ýĿǰ¼ÓÈëÒѾÊÜÏÞ¡£
×îÊÜÖõÄ¿µÄµ±ÊôBuster£¬Æä×÷ÕßÖ®Ò»¾ÍÊÇChristian Johansen¡£ºÍKarmaºÜÏñ£¬Ò²Ê¹ÓÃNodejs±àд¿çƽ̨²¢ÇÒÖ§³ÖPhantomJS£¬Ò»´Î²âÊÔËùÓпͻ§¶Ë¡£¸üÖØÒªµÄÊÇÖ§³ÖNodejsµÄ²âÊÔ£¬Í¬ÑùÖ§³Ö¸÷ÖÖÖ÷Á÷²âÊÔ¿ò¼Ü¡£²»¹ýĿǰ»¹ÔÚBeta²âÊÔÖУ¬ºÜ¶àbug¶øÇÒ²»ÄܺܺõļæÈÝWindowsϵͳ¡£ËüµÄÄ¿±ê»¹°üÀ¨ÕûºÏBrowser
Stack¡£
»ùÓÚÍøÒ³µÄ²âÊÔ
µ½Ä¿Ç°ÎªÖ¹ÎÒÃǵIJâÊÔ¿´ÆðÀ´Ê®·ÖµÄÍêÃÀÁË£¬µ«ÊDZðÍüÁË£¬ÔÚǰ¶Ë¿ª·¢ÖдæÔÚ½»»¥ÎÊÌ⣬²»ÄÜÆÚ´ýQAÍæÁËÃüµÄµã»÷ij¸ö°´Å¥»òÕßË¢ÐÂÒ»¸öÒ³Ãæ²¢ÊäÈëÒ»¾äÂÒÂëÖ®ÀàµÄ¶«Î÷À´²âÊÔ´úÂë¡£¼´Ê¹ÊÇ¿ª·¢Õß±¾ÉíÒ²»áÊܲ»ÁË£¬Èç¹û²úÆ·±¾ÉíÓµÓÐÒ»¶Ñ¸´ÔÓµÄ±íµ¥ºÍÂß¼µÄ»°¡£
SeleniumÊÇÒ»¸ö²âÊÔ¹¤¾ß¼¯£¬ÓÉThoughtworks¿ª·¢£¬·ÖΪÁ½²¿·Ö¡£Selenium IDEÊÇÒ»¸öFirefoxä¯ÀÀÆ÷µÄ²å¼þ£¬¿ÉÒÔÂ¼ÖÆÓû§ÐÐΪ£¬²¢¿ìËÙ²âÊÔ¡£
¶øSelenium WebDriverÊÇÒ»¸ö¶àÓïÑÔµÄÇý¶¯ä¯ÀÀÆ÷µÄ¹¤¾ß£¬Ö§³ÖPython¡¢Java¡¢Ruby¡¢Perl¡¢PHP»ò.Net¡£²¢ÇÒ¿ÉÒÔ²Ù×÷IE¡¢Firefox¡¢SafariºÍChromeµÈÖ÷Á÷ä¯ÀÀÆ÷¡£Í¨¹ý
open , type , click , waitForxxx µÈÖ¸ÁîÀ´Ä£ÄâÓû§ÐÐΪ£¬±ÈÈçÓÃJava²âÊÔ£º
public void testNew() throws Exception { selenium.open("/"); selenium.type("q", "selenium rc"); selenium.click("btnG"); selenium.waitForPageToLoad("30000"); assertTrue(selenium.isTextPresent("Results * for selenium rc")); } |
Ê×ÏÈÌø×ªµ½¸úĿ¼£¬È»ºóÑ¡ÔñÀàÐÍ£¬µã»÷°´Å¥G£¬²¢µÈ´ýÒ³ÃæÔØÈë30Ã룬ȻºóʹÓöÏÑÔ²âÊÔ¡£ÕâÑù¾ÍÍê³ÉÁËÒ»´ÎÓû§»ù±¾ÐÐΪµÄÄ£Ä⣬²»¹ý¸´ÔÓµÄÄ£ÄâÒÔ¼°ÔÚһЩ·ÇÁ´½ÓµÄ²Ù×÷»¹ÐèÒª¸ñÍâ×¢Ò⣬±ÈÈçAjaxÇëÇó»òÕßPjaxµÄÎÞˢеȵȡ£
ÁíÍ⻹ÓÐÒ»¿î¿ÉÒÔÄ£ÄâÓû§ÐÐΪµÄÍøÒ³²âÊÔ¹¤¾ßWATIR£¬ÊÇWeb Application Testing
in RubyµÄËõд£¬ÏÔÈ»ËüÖ»Ö§³ÖRubyÓïÑÔÀ´²Ù×÷ä¯ÀÀÆ÷Ä£ÄâÓû§ÐÐΪ¡£¹Ù·½Éù³ÆËüÊÇÒ»¸ö¼òµ¥¶øÁé»îµÄ¹¤¾ß£¬ÎÞÂÛÔõÑùÖÁÉپ͹ٷ½ÍøÕ¾µÄÉè¼ÆÀ´¿´Òª±ÈSelenium¼òÔ¼¶àÁË¡£Í¬ÑùÖ§³ÖÄ£ÄâÁ´½Óµã»÷£¬°´Å¥µã»÷£¬»¹ÓÐ±íµ¥µÄÌîдµÈÐÐΪ¡£²»¹ýWATIR²»Ö§³ÖAjaxµÄ²âÊÔ¡£ºÍÆäËûRuby¿âÒ»ÑùÐèÒªgemÀ´°²×°Ëü£º
gem install watir --no-rdoc --no-ri |
È»ºóʹÓÃËü
require 'rubygems' require 'watir' require 'watir-webdriver' browser = Watir::Browser.new browser.goto 'http://www.example.com/form' browser.test_field(:name => 'entry.0.single').set 'Watir' browser.radio(:value => 'Watir').set browser.radio(:value => 'Watir').clear browser.checkbox(:value => 'Ruby').set browser.checkbox(:value => 'Javascript').clear browser.button(:name => 'submit').click |
ÕâÑù¾ÍʹÓÃwatirÍê³ÉÁËÒ»´Î±íµ¥Ìîд¡£
³ÖÐø¼¯³É²âÊÔ
³ÖÐø¼¯³É¾ÍÊÇͨ³£ËùνµÄCI(Continuous integration)£¬³ÖÐø²»¶ÏµÄ×Ô¶¯»¯²âÊÔмÓÈë´úÂëºóµÄÏîÄ¿¡£Ëü²¢²»ÊôÓÚµ¥Ôª²âÊÔ£¬¶øÊÇÁíÍâµÄ·¶³ë£¬²»¹ýͨ¹ýʹÓÃCI·þÎñ¿ÉÒÔºÜÈÝÒ×µÄÔÚGithubÉϲâÊÔÏîÄ¿£¬¶øÕâÒ²¾ÍÊdzÖÐø¼¯³ÉµÄÒâÒå¡£
ÏÂÃæÒÔÎÒµÄjQС²å¼þDialogΪÀý½éÉÜÒ»ÏÂTravis-CIµÄʹÓ÷½·¨£¬×¢²áTravis£¬È»ºóÁ´½Ó×Ô¼ºµÄGithub£¬Ñ¡ÔñÒª½øÐгÖÐø¼¯³ÉµÄÏîÄ¿¡£´Ëʱ»áÏÔʾbuild
failing£¬ÄÇÊÇÒòΪ»¹Ã»ÓÐÔÚÏîÄ¿ÖнøÐÐÏà¹ØÅäÖá£
Ê×ÏÈÐèҪʹÓÃGruntµÈ¹¤¾ßÅäÖúòâÊÔ¿ò¼ÜµÄ×Ô¶¯»¯²âÊÔ£¬Ï¸½Ú¿ÉÒԲο¼ÎÒ֮ǰµÄÎÄÕ¸ĽøÎÒµÄWorkflow¡£È»ºóÔÚ
package.json ÖÐÌí¼ÓһϴúÂëÀ´Ö¸¶¨Ö´ÐеĽű¾£º
"scripts": { "test": "grunt jasmine:test" } |
½Ó×ÅÌí¼ÓÒ»¸öÎļþ .travis.yml À´ÅäÖÃtravis£º
language: node_js node_js: - "0.8" before_script: - npm install -g grunt-cli |
language ÊǼ¯³É²âÊÔËùʹÓõÄÓïÑÔ£¬ÕâÀïǰ¶Ë¿ª·¢µ±È»ÊÇʹÓÃNodejs£¬ÔÚ node_js ÖÐÖ¸¶¨°æ±¾¼´¿É¡£µ±È»Travis»¹Ö§³ÖÆäËû¶àÖÖÓïÑÔ£¬ÒÔ¼°ºó¶ËÊý¾Ý¿âµÈ¡£
before_script ÔòÊÇÔÚ²âÊÔǰִÐеĽű¾³ÌÐò£¬ÕâÀïÔÚÈ«¾Ö°²×°Grunt-cli¼´¿É£¬ÒòΪĬÈϵÄTravis»áÖ´ÐÐ
npm install ½«package.jsonÖÐÖ¸¶¨µÄNode°ü°²×°µ½ÏîÄ¿¡£
×îºóÔÚGithubÖл¹ÐèÒªÔÚÏîÄ¿µÄSettingÖеÄService HooksÖÐÅäÖÃTravis£¬ÊäÈëToken²¢±£´æ¡£»òÕßÖ±½ÓÔÚTravisÖеã»÷¸ÃÏîÄ¿ÌõÄ¿ÖеİâÊÖͼ±ê½øÈëGithub£¬»á×Ô¶¯ÅäÖúá£
ÁíÍ⣬Èç¹ûÔÚGithubÉÏΪREADMEÎļþÌí¼ÓÒ»ÐÐ
[](https://travis-ci.org/tychio/dialog) |
¾Í¿ÉÒÔ³ÖÐøÖ±¹ÛµÄÏÔʾÆä²âÊÔ½á¹û¡£
|