IBM Korea Skip to main content
       IBM Ȩ    |  Á¦Ç° & ¼­ºñ½º  |  °í°´Áö¿ø & ´Ù¿î·Îµå  |  È¸¿ø°¡ÀÔ  

Extreme Programming : Test-driven ÇÁ·Î±×·¡¹Ö
Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇϱâ

Level: Intermediate

Roy W. Miller
¼ÒÇÁÆ®¿þ¾î °³¹ßÀÚ, RoleModel Software, Inc.
2003³â 4¿ù 22ÀÏ

Column iconTest-driven ÇÁ·Î±×·¡¹ÖÀº ÇÁ·Î±×·¡¸ÓµéÀ» ´çȲ½ÃÅ°´Â XPÀÇ ÇÑ Ãø¸éÀÌ´Ù. ¿ì¸®µéÀº Test-driven ÇÁ·Î±×·¡¹Ö¿¡ ´ëÇÑ ÀÇ¹Ì¿Í ÀÌ°ÍÀ» ´Ù·ç´Â ¹æ¹ý¿¡ ´ëÇØ ºÎÁ¤È®ÇÑ ÃßÃøÀ» ÇÏ°í ÀÖ´Ù. Roy Miller°¡ test-driven ÇÁ·Î±×·¡¹ÖÀ» ¼³¸íÇÑ´Ù.

Áö³­ 50³â µ¿¾È, Å×½ºÆ®¶õ °ÍÀº ÇÁ·ÎÁ§Æ®°¡ ³¡³¯ ÁîÀ½¿¡ ÇàÇØÁö´Â °ÍÀ¸·Î ÀνĵǾú´Ù. ¹°·Ð, ÇÁ·ÎÁ§Æ®°¡ ÁøÇàµÇ´Â µ¿¾È¿¡´Â ÅëÇÕ Å×½ºÆ®°¡ ÀÖ°í ¸ðµç ÄÚµå ÀÛ¾÷ÀÌ ¼öÇàµÈ ÈÄ¿¡µµ Åë»ó Å×½ºÆ®´Â ½ÃÀÛÇÏÁö ¾Ê´Â´Ù. ÇÏÁö¸¸ XPÀÇ ¿ËÈ£·ÐÀÚµéÀº ÀÌ ¸ðµ¨Àº ¿ÏÀüÈ÷ ½Ã´ëÂø¿ÀÀûÀ̶ó°í ¸»ÇÑ´Ù. ´ç½ÅÀÌ ÇÁ·Î±×·¡¸Ó¶ó¸é Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ Å×½ºÆ®¸¦ ¸¸µé¾î¾ßÇÏ°í ±×·±´ÙÀ½ Å×½ºÆ®°¡ Åë°ú ÇÒ Äڵ带 ÀÛ¼ºÇؾßÇÑ´Ù. ÀÌ·¸°Ô ÇÏ´Â °ÍÀº ½Ã½ºÅÛÀ» °¡´ÉÇÑ ´Ü¼øÇÏ°Ô ÇÏ´Â µ¥ µµ¿òÀÌ µÈ´Ù.

Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇϱâ
XP´Â µÎ Á¾·ùÀÇ Å×½ºÆ®-ÇÁ·Î±×·¡¸Ó Å×½ºÆ®(programmer tests)¿Í °í°´ Å×½ºÆ®(customer tests)-¿¡ ´ëÇؼ­ À̾߱âÇÏ°í ÀÖ´Ù. Test-driven ÇÁ·Î±×·¡¹ÖÀº ÇÁ·Î±×·¡¸Ó Å×½ºÆ®(programmer tests) ¶Ç´Â ´ÜÀ§ Å×½ºÆ®(unit tests)°¡ ´ç½ÅÀÌ ÀÛ¼ºÇÑ Äڵ带 °áÁ¤(drive) Çϵµ·Ï ÇÏ°íÀÖ´Ù. ÀÌ´Â Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ Å×½ºÆ®¸¦ °®°íÀÖ¾î¾ß ÇÑ´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù. ÀÌ Å×½ºÆ®´Â ¾î¶² Äڵ带 ÀÛ¼ºÇؾßÇÏ´ÂÁö¸¦ Áö½ÃÇÑ´Ù. ¿©·¯ºÐÀº ´õµµ ´úµµ ¸»°í Å×½ºÆ®°¡ Åë°ú½ÃŲ Äڵ常 ÀÛ¼ºÇÏ¸é µÈ´Ù. XP ±ÔÄ¢Àº °£´ÜÇÏ´Ù. ÇÁ·Î±×·¡¸Ó Å×½ºÆ®°¡ ¾ø´Ù¸é ¾î¶² Äڵ带 ÀÛ¼ºÇØ¾ß ÇÏ´ÂÁö ¾Ë ¼ö ¾ø°í µû¶ó¼­ ¾î¶² Äڵ嵵 ÀÛ¼ºÇÒ ¼ö ¾ø´Ù.

Å×½ºÆ®¸¦ ÀÛ¼ºÇÏ´Â ¹æ¹ý
ÀÌ ÀÌ·ÐÀº ÈǸ¢ÇÏ´Ù. ÇÏÁö¸¸ Å×½ºÆ®¸¦ Äڵ嵵 ÀÛ¼ºÇϱâ Àü¿¡ ¾î¶»°Ô ÀÛ¼ºÇÒ °ÍÀΰ¡? ¿ì¼± Kent BeckÀÇ Test-Driven Development: By Example (Âü°íÀÚ·á)À» Àб⠹ٶõ´Ù. Å×½ºÆ®¸¦ ÀÛ¼ºÇÏ´Â ¹æ¹ý°ú ±×°ÍÀ¸·Î Äڵ带 °áÁ¤ÇÏ´Â ¹æ¹ýÀ» ´Ù·ç¸é¼­ test-driven ÇÁ·Î±×·¡¹ÖÀÌ ÀåÁ¡À» ¼³¸íÇÏ°í ÀÖ´Ù.

Test-driven vs test-first
³ª´Â "test-first" º¸´Ù "test-driven"À̶ó´Â ¿ë¾î°¡ ÁÁ´Ù. ¿Ö³ÄÇϸé test-first´Â Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ ÇÁ·Î±×·¡¸Ó Å×½ºÆ®(programmer tests)¸¦ ÀÛ¼ºÇÏ´Â ¹æ¹ý¿¡ ÃÊÁ¡À» ¸ÂÃ߱⠶§¹®ÀÌ´Ù. ±×·¯ÇÑ ¸ÞÄ¿´ÏÁòÀº Áß¿äÇÏÁö¸¸ ½ÇÁ¦ÀÇ ÈûÀº test-driven¿¡ ÇÔÃàµÇ¾î ÀÖ´Â »ç°í¿Í ÇÁ·Î±×·¡¹Ö ½À°üÀÇ º¯È­¿¡ ÀÖ´Ù. Á»´õ Æ÷°ýÀûÀÎ ¶æÀ» Áö´Ñ "test-driven ÇÁ·Î±×·¡¹Ö"Àº ÀÌ ¸ðµç Á¾·ù ¸ðµÎÀÇ Å×½ºÆ®¸¦ Æ÷°ýÇÏ°í, XP ÆÀÀÌ ÁöÇâÇÏ´Â test-drive ¹æ½ÄÀ» ¸»ÇÏ°íÀÖ´Ù.

Person °´Ã¼¸¦ °®°íÀÖ´Â ½Ã½ºÅÛÀ» ÀÛ¼ºÇÑ´Ù°í Çغ¸ÀÚ. ³ª´Â °¢ Person °´Ã¼µéÀÌ ³»°¡ ³ªÀ̸¦ ¹°À¸¸é ´ë´äÇϵµ·Ï ¸í·ÉÇÏ°í ½Í´Ù. ¾ÆÁ÷ Äڵ带 ÀÛ¼ºÇÏÁö ¾Ê¾ÒÁö¸¸ Áö±ÝÀº Å×½ºÆ®¸¦ ÀÛ¼ºÇؾßÇÑ´Ù. "³­ ³»°¡ ¹«¾ùÀ» Å×½ºÆ® ÇؾßÇÏ´ÂÁöµµ ¸ð¸£´Âµ¥¿ä? ¾î¶»°Ô Å×½ºÆ®¸¦ ÀÛ¼ºÇÒ ¼ö ÀÖ½À´Ï±î?" ¶ó´Â Áú¹®ÀÌ µé¸®´Â µí ÇÏ´Ù. :) ´ë´äÀº °£´ÜÇÏ´Ù. ´ç½ÅÀº ¹«¾ùÀ» Å×½ºÆ® ÇؾßÇÏ´ÂÁö¸¦ ¾Ë°í ÀÖÁö¸¸ ´ÜÁö ±×·¯ÇÑ ¹æ½ÄÀ¸·Î »ý°¢Çغ¸Áö ¾Ê¾Ò±â ¶§¹®¿¡ ¸ð¸£´Â °ÍÀÌ´Ù.

´ç½Å¿¡°Ô´Â Äڵ尡 ¾ÆÁ÷ ¾ø´Ù. ÇÏÁö¸¸ Person °´Ã¼°¡ ¾î¶°ÇØ¾ß ÇÏ´ÂÁö¿¡ ´ëÇؼ­´Â °³³äÀÌ ÀÖ´Ù. ¿©±â¿¡´Â ³ªÀ̸¦ Á¤¼ö·Î ¸®ÅÏÇÏ´Â ¸Þ¼Òµå°¡ ÀÖ¾î¾ßÇÑ´Ù. ³ª´Â ÁÖ·Î ÀÚ¹Ù¸¦ ´Ù·ç±â ¶§¹®¿¡ ÇÁ·Î±×·¡¸Ó Å×½ºÆ®(programmer tests)¸¦ ÀÛ¼ºÇϱâ À§ÇØ JUnitÀ» »ç¿ëÇÑ´Ù. Listing 1Àº Person °´Ã¼¸¦ À§ÇØ ÀÛ¼ºÇÏ°íÀÚ ÇÏ´Â JUnit Å×½ºÆ®ÀÌ´Ù:

Listing 1. Person °´Ã¼¿ë JUnit Å×½ºÆ®

package com.roywmiller.testexample;

import junit.framework.TestCase;

public class TC_Person extends TestCase {

  protected Person person;

  public TC_Person(String name) {
    super(name);
  }

  protected void setUp() throws Exception {
    person = new Person();
  }

  public void testGetAge() {
    int actual = person.getAge();
    assertEquals(0, actual);
  }

  protected void tearDown() throws Exception {
  }

}

¿ì¼± JUnit¿¡ Àͼ÷ÇÏÁö ¾ÊÀº »ç¶÷µéÀ» À§ÇØ ¹æ¹ý°ú ±¸Á¶¸¦ »ìÆ캸µµ·Ï ÇÏÀÚ. TestCase Ŭ·¡½º´Â °¡Àå ¸¹ÀÌ »ç¿ëÇÏ°Ô µÉ Ŭ·¡½ºÀÌ´Ù. ¿©·¯ºÐÀº TestCase¸¦ ÇÏÀ§ºÐ·ùÇÏ´Â Å×½ºÆ® Ŭ·¡½º¸¦ ÀÛ¼ºÇϱ⸸ ÇÏ¸é µÈ´Ù. ÀÏ´Ü Å×½ºÆ® Ŭ·¡½º¸¦ °®°íÀÖÀ¸¸é Å×½ºÆ® ¸Þ¼Òµå¿¡ ½ÇÁ¦ ¾×¼ÇÀÌ ¹ß»ýÇÑ´Ù. À̵éÀº test Á¢µÎ»ç·Î ½ÃÀÛÇÑ´Ù. Å×½ºÆ®¸¦ ½ÇÇàÇÒ ¶§, JUnitÀº:

  • Å×½ºÆ® Ŭ·¡½º¸¦ °Ë»çÇÏ°í "test"·Î ½ÃÀÛÇÏ´Â °¢°¢ÀÇ ¸Þ¼Òµå¸¦ ½ÇÇàÇÑ´Ù.
  • °¢ Å×½ºÆ® ¸Þ¼Òµå Àü¿¡ setUp() ¸Þ¼Òµå¸¦ ½ÇÇàÇÑ´Ù.
  • °¢ Å×½ºÆ® ¸Þ¼Òµå ÈÄ¿¡ tearDown() ¸Þ¼Òµå¸¦ ½ÇÇàÇÑ´Ù.

ÀÌ ¿¹Á¦¿¡¼­ setUp() ¸Þ¼Òµå´Â PersonÀ» ÀνºÅϽºÈ­ ÇÑ´Ù. ´Ù½Ã¸»ÇÏ¸é ³»°¡ 20°³ÀÇ Å×½ºÆ® ¸Þ¼Òµå¸¦ °¡Áö°í ÀÖ´Ù¸é °¢°¢Àº »õ·Î¿î Person ÀνºÅϽº·Î ½ÃÀÛÇÑ´Ù´Â ÀǹÌÀÌ´Ù. tearDown()¿¡¼­´Â ÇÒ ÀÏÀÌ ¾ø´Ù. µû¶ó¼­ Áö±ÝÀº ºñ¿öµÐ´Ù. setUp()À̳ª setUp()ÀÌ ÇÊ¿äÇÏÁö ¾Ê´Ù´Â °ÍÀº °­Á¶ÇÒ °¡Ä¡°¡ ÀÖ´Ù. ³ª´Â µÎ ¹ø° ¶Ç´Â ¼¼ ¹ø° Å×½ºÆ® ¸Þ¼Òµå¸¦ ÀÛ¼ºÇÏ°í ¸ðµÎ°¡ °øÀ¯ÇÏ´Â ¼Â¾÷À̳ª tear down ¾×ƼºñƼ°¡ ÀÖ´Ù°í °áÁ¤Çϱâ Àü±îÁö´Â ±×µéÀ» ¸¸µéÁö ¾Ê´Â´Ù.

³ª´Â Å×½ºÆ® ¸Þ¼Òµå¿¡ ¸î °³ÀÇ µðÀÚÀÎ °áÁ¤À» ³»·È´Ù. ³ª´Â ³»°¡ personÀ» ¼öÇàÇÒ ¼ö ÀÖ°í "µðÆúÆ®" Person ÀÌ ³ª¿¡°Ô 0À̶õ ³ªÀ̸¦ µÇµ¹·Á ÁÙ°ÍÀ̶ó°í »ý°¢Çß´Ù. ¶ÇÇÑ Person °´Ã¼°¡ getAge() ¸Þ¼Òµå¸¦ °®°Ô µÉ °ÍÀ̶ó°í »ý°¢Çß´Ù. ±×·¯ÇÑ »ó»óÀº Áö±Ý±îÁö´Â ³ª»ÚÁö ¾Ê´Ù. ºñ·Ï ±×µéÀÌ ¿µ¿øÈ÷ Áö¼ÓµÉ °ÍÀº ¾Æ´ÏÁö¸¸ ¸»ÀÌ´Ù. ±×·¯ÇÑ »ý°¢À» ±â¹ÝÀ¸·Î PersonÀ» ÀνºÅϽºÈ­ÇÏ¿© Å×½ºÆ® ¸Þ¼Òµå¿¡¼­ Å×½ºÆ®ÇÒ ¸Þ¼Òµå¸¦ È£ÃâÇÏ°í "assert" ¸Þ¼Òµå ´Ù¹ß Áß¿¡¼­ Çϳª¸¦ È£ÃâÇß´Ù. ¼±¾ð ¸Þ¼Òµå´Â ¾î¶² °ÍÀÌ true ÀÎÁö Å×½ºÆ®ÇÑ´Ù. ´Ù½Ã¸»Çؼ­ ±×µéÀº JUnitÀÌ true °ªÀ» °®°í ÀÖ´Ù´Â °ÍÀ» ¼±¾ðÇÑ´Ù. Ç¥ 1Àº ¼±¾ð Ä«Å×°í¸® ¸®½ºÆ®ÀÌ´Ù:

Ç¥1. ¼±¾ð Ä«Å×°í¸®
¼±¾ð ¸Þ¼Òµå ¼³¸í
assertEquals µÎ °³ÀÇ µ¿ÀϼºÀ» ºñ±³ÇÑ´Ù(ÇÁ¸®¸ÓƼºê ¶Ç´Â °´Ã¼).
assertTrue booleanÀ» true·Î ¼±¾ðÇÑ´Ù.
assertFalse booleanÀ» false·Î ¼±¾ðÇÑ´Ù.
assertNull °´Ã¼°¡ nullÀ̶ó´Â ¼±¾ðÇÑ´Ù.
assertNotNull °´Ã¼°¡ nullÀÌ ¾Æ´Ï¶ó´Â °ÍÀ» ¼±¾ðÇÑ´Ù.
assertSame µÎ °´Ã¼°¡ °°Àº ÀνºÅϽºÀÓÀ» ¼±¾ðÇÑ´Ù.
assertNotSame µÎ °´Ã¼°¡ °°Àº ÀνºÅϽº°¡ ¾Æ´Ï¶ó´Â °ÍÀ» ¼±¾ðÇÑ´Ù.

ÀÌ °æ¿ì Person ÀνºÅϽº°¡ Á¦°øÇÑ ³ªÀÌ´Â 0 ÀÓÀ» È®ÀÎÇß´Ù. 0Àº »õ·Î¿î Person °´Ã¼ µðÆúÆ®ÀÌ´Ù.

¹°·Ð, ÀÌ Å×½ºÆ®´Â ÄÄÆÄÀÏ ÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù. ±×¸² 1Àº ÀÌ°ÍÀ» Eclipse¿¡¼­ ½ÇÇàÇÒ ¶§ JUnit Fast View¸¦ ³ªÅ¸³»´Â ¸ð½ÀÀÌ´Ù.

±×¸²1. JUnit ÄÄÆÄÀÏ ¿À·ù
JUnit compile failure

ºÐ¸íÈ÷ Person Ŭ·¡½º¸¦ °®°íÀÖÁö ¾Ê¾Æ ³ªÀÇ Å×½ºÆ®´Â ¹®Á¦ÀÇ ½ÇÇàÀ» ÇÏ°Ô µÇ¾ú´Ù. »¡°£ÁÙÀÌ »ý°å´Ù. ¸¸¾à ¸ðµç°ÍÀÌ ½ÇÇàµÇ°í Å×½ºÆ®°¡ Åë°úµÇ¾ú´Ù¸é ÀÌ ¹Ù(bar)´Â ³ì»öÀÌ µÉ °ÍÀÌ´Ù.

¹®Á¦µÉ °Í ¾ø´Ù. ³ª´Â Person Ŭ·¡½º¸¦ ¸¸µé°ÍÀÌ´Ù:

Listing 2. Person Ŭ·¡½º

package com.roywmiller.testexample;

public class Person {
  
  public int getAge() {
    return 0;
  }

}

Å×½ºÆ®¸¦ ½ÇÇàÇÒ ¶§ ÀÌ°ÍÀº Åë°úµÇ¾î ³ì»öÁÙÀÌ µÉ °ÍÀÌ´Ù. getAge()¿¡¼­ ¾î¶² °ÍÀ» ¸®ÅÏÇؾßÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é ÀÌ°ÍÀº ÄÄÆÄÀÏ ÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù. »õ·Î¿î Person ÀνºÅϽº¿ë µðÆúÆ®ÀÎ 0ÀÌ ÈçÈ÷ »ç¿ëµÇ°í ÀÌ°ÍÀº Àß ½ÇÇàµÈ´Ù. ´Ù½Ã Å×½ºÆ®¸¦ Åë°úÇÒ Äڵ带 ÀÛ¼ºÇß´Ù.

Person¿¡ µðÆúÆ® ³ªÀ̸¦ ºÎ°úÇÏ´Â °ÍÀº ÁÁ´Ù. ÇÏÁö¸¸ ±×°ÍÀÌ ½Ã½ºÅÛÀ» ¸¹ÀÌ µ½´Â °ÍÀº ¾Æ´Ï´Ù. PersonÀº ±× º¸´Ù ´õ Çö¸íÇØ¾ß ÇÑ´Ù. ³ª¿¡°Ô Á¤¸»·Î ÇÊ¿äÇÑ °ÍÀº »ý³â ¿ùÀÏÀ» º¸À¯ÇÏ°í ÀÖ°í ¿À´ÃÀ» ±âÁ¡À¸·Î ³ªÀ̸¦ ÀÀ´äÇÏ´Â PersonÀÌ´Ù. ³ªÀÇ Person °´Ã¼°¡ ¼ºÀåÇؾßÇÒ ÇÊ¿ä°¡ ÀÖ´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù. ÄÚµå ÀÛ¾÷¿¡ µé¾î°¡±â¿¡ ¾Õ¼­ testGetAge¸¦ testGetDefaultAge·Î À̸§À» ¹Ù²Ù°í ³ªÀÇ Å×½ºÆ® ÄÉÀ̽º¸¦ À§ÇÑ ¶Ç ´Ù¸¥ Å×½ºÆ®¸¦ ÀÛ¼ºÇß´Ù:

Listing 3. »õ·Î¿î Å×½ºÆ® ¸Þ¼Òµå

public void testGetAge() {
  GregorianCalendar calendar = new GregorianCalendar(1971, 3, 23);
  person.setBirthDate(calendar.getTime());
  int actual = person.getAge();
  assertEquals(31, actual);
}

Person¿¡´Â setBirthDate() ¸Þ¼Òµå°¡ ¾ø±â ¶§¹®¿¡ ÀÌ Å×½ºÆ®´Â ÄÄÆÄÀÏ ÇÏÁö ¾Ê´Â´Ù. ³»°¡ ÇÑ °³¸¦ ¸¸µç ÈÄ¿¡, PersonÀº Listing 4¿Í °°´Ù:

Listing 4. ¾÷µ¥ÀÌÆ® µÈ Person Ŭ·¡½º

package com.roywmiller.testexample;

import java.util.Date;

public class Person {
  
  protected Date birthdate;
  
  public int getAge() {
    return 0;
  }
  
  public void setBirthDate(Date aBirthDate) {
    this.birthdate = aBirthDate;
  }

}

PersonÀº getAge()¿¡ ´ëÇØ ´Ù¸¥ ¾î¶² °Íµµ ¼öÇàÇÏÁö ¾Ê´Â´Ù. µû¶ó¼­ Å×½ºÆ®´Â ½ÇÆÐÇß´Ù. ±×¸² 2´Â JUnit Fast View ÀÌ´Ù:

±×¸²2. JUnit ¼±¾ð ¿À·ù
JUnit assertion failure

AssertionFailedError´Â °á°ú °ªÀÌ 31 ´ë½Å 0À» ³ªÅ¸³»°í ÀÖ´Ù. ´Ù¸¥ ¾î¶² °ÍÀ» ¼öÇàÇϵµ·Ï ¸Þ¼Òµå¸¦ º¯°æÇÏÁö ¾Ê¾Ò±â ¶§¹®¿¡ ÀÌ ¿À·ù´Â ¿¹»óµÈ °á°úÀÌ´Ù. ÀÌÁ¦ ³ª´Â Å×½ºÆ®¸¦ Åë°úÇÒ Äڵ带 ¸¸µé ¼ö ÀÖ´Ù. µðÆúÆ® ³ªÀÌÀÎ 0À» µû¶ó¾ß ÇÏÁö¸¸ 1971³â 3¿ù 23ÀÏ¿¡ ž ´©±º°¡ÀÇ ³ªÀ̸¦ °è»êÇؾßÇÑ´Ù. ¾î¶² ÇÁ·Î±×·¡¸ÓµéÀº (Kent Beck Æ÷ÇÔ) birthdate°¡ null ÀÎÁö¸¦ °Ë»çÇÏ°í ±×·±´ÙÀ½ °è»êÀ» Á»´õ Àß ÇÏ´Â ¶Ç ´Ù¸¥ Å×½ºÆ®¸¦ ÀÛ¼ºÇÏ´Â °Í °°ÀÌ °£´ÜÇÑ °ÍÀ» ¼öÇàÇÒ °ÍÀ» ±ÇÇÑ´Ù. ÇÏÁö¸¸ ÀÌ °æ¿ì ¿¹Á¦¸¦ °£´ÜÇÏ°Ô ¸¸µé°ÍÀ̱⠶§¹®¿¡ ³»°¡ ¿øÇÏ´Â ¹æ½ÄÀ¸·Î ³ªÀ̸¦ °è»êÇÔÀ¸·Î¼­ Å×½ºÆ® Åë°ú¸¦ ½ÃµµÇÒ °ÍÀÌ´Ù. Calendar¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù:

Listing 5. getAge() ±¸Çö

package com.roywmiller.testexample;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class Person {
  
  protected Date birthdate;
  
  public int getAge() {
    if (birthdate == null)
      return 0;
    else {
      int yearToday = 
        Calendar.getInstance().get(Calendar.YEAR);
      
      Calendar calendar = new GregorianCalendar();
      calendar.setTime(birthdate);
      int birthYear =calendar.get(Calendar.YEAR);
      
      return yearToday - birthYear; 
    }
  }
  
  public void setBirthDate(Date aBirthDate) {
    this.birthdate = aBirthDate;
  }

}

Å×½ºÆ®¸¦ ½ÇÇàÇϸ鼭 31ÀÌ ³ª¿Ã°ÍÀ» ±â´ëÇÏ¿´À¸³ª °á°ú´Â 32°¡ µÇ¾ú´Ù. ¿À·ùÀÌ´Ù. ¹«¾ùÀÌ À߸øµÇ¾ú´Â°¡? ¹®Á¦´Â ³»°¡ ÀÛ¼ºÇÑ Äڵ忡 ÀÖ´Ù´Â °ÍÀ» ¾È´Ù. else ÀýÀ» º¸¸é ¿¬µµ¸¸À» ±âÁØÀ¸·ÎÇÑ ³ªÀ̸¦ °è»êÇß´Ù. ÀÌ°ÍÀº Ʋ·È´Ù. ³ª´Â ÇöÀç 31»ì ÀÌÁö¸¸ ´ÙÀ½´Þ¿£ 32»ìÀÌ µÈ´Ù. ¾Ë°í¸®ÁòÀÌ Æ²¸° °á°ú¸¦ ³Â´Ù. ÀÌ ¹®Á¦¸¦ ÇØ°áÇϱâ À§Çؼ­ Listing 6¸¦ »ç¿ëÇß´Ù:

Listing 6. ¼öÁ¤µÈ getAge()

else {
  int yearToday = Calendar.getInstance().get(Calendar.YEAR);
  
  Calendar calendar = new GregorianCalendar();
  calendar.setTime(birthdate);
  int birthYear = calendar.get(Calendar.YEAR);
  
  if (yearToday == birthYear)
    return yearToday - birthYear;
  else
    return yearToday - birthYear - 1;
}

³ì»öÁÙÀÌ´Ù. Person Ŭ·¡½º¿¡´Â ÄÚµå Áߺ¹ÀÌ ¾à°£ ÀÖ´Ù. ÇÏÁö¸¸ ³ªÁß¿¡ ¸®ÆÑÅ丵À» À§ÇØ ³²°ÜµÎ°Ú´Ù.

ÀÌ ¿¹Á¦´Â test-driven ÇÁ·Î±×·¡¹ÖÀÇ Á¤¼ö¸¦ º¸¿©ÁØ´Ù. ³ª´Â ¸Å ´Ü°è ¸¶´Ù Å×½ºÆ®¸¦ Åë°úÇÒ Äڵ带 ÀÛ¼ºÇß´Ù. ¿©·¯ºÐµµ Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ Å×½ºÆ®¸¦ ÀÛ¼ºÇØ¾ß ÇÑ´Ù´Â »ç°í¿¡ Àͼ÷ÇØÁ®¾ß ÇÑ´Ù .

Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇØ¾ß ÇÏ´Â ÀÌÀ¯
¾Æ¸¶µµ Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇÏ´Â °ÍÀº ´ë´ÜÇÑ »ý°¢ÀÌ ¾Æ´Ï¶ó°í »ý°¢ÇÒÁöµµ ¸ð¸£°Ú´Ù. ³Ê¹« ³¸¼³°Å³ª ºÒÇÊ¿äÇÏ°Ô º¸ÀÏ ¼öµµ ÀÖ´Ù. ³ª´Â µÎ ¹ø° ÀÌÀ¯¸¦ ÀÚÁÖ µé¾ú´Ù. ´ëºÎºÐ ¼÷·ÃµÈ ÇÁ·Î±×·¡¸Ó¿¡°Ô¼­ ±×·± ¼Ò¸®¸¦ µé¾ú´Ù. À̵éÀº ¿µ¸®ÇÏ°í ¸¹Àº °æÇèÀÌ ÀÖ°í ¹«¾ùÀ» ÇÏ°íÀÖ´ÂÁö ¾Ë±â ¶§¹®¿¡ Å×½ºÆ®¸¦ ÀÛ¼ºÇÒ ÇÊ¿ä°¡ ¾ø´Ù°í ¸»ÇÑ´Ù. Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇؾßÇÏ´Â ¼¼ °¡Áö ÀÌÀ¯°¡ ÀÖ´Ù:

  • ÇнÀ(Learning)
  • º¯¼ö ¹ß»ý(Emergence)
  • È®½Å(Confidence)

Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇÏ´Â °ÍÀº ÇнÀ¿¡ ÀÖ¾î ÁÁÀº ¹æ¹ýÀÌ´Ù. ÀÌ°ÍÀº ÀÛ¼ºÇÏ°í ÀÖ´Â °Í¿¡ ´ëÇÑ ÀÎÅÍÆäÀ̽º¿¡ ÃÊÁ¡À» ¸ÂÃßµµ·Ï µµ¿ÍÁØ´Ù. Å×½ºÆ®¸¦ ÀÛ¼ºÇÒ ¶§ »ç¿ëÇÏ°í Àִ Ŭ·¡½º°¡ ÀÌ¹Ì Á¸ÀçÇÏ°í ÀÖ´Â °Íó·³ °¡ÀåÇÒ ¼ö ÀÖ´Ù. ±×·±´ÙÀ½ ³ª¸ÓÁö ½Ã½ºÅÛ¿¡¼­ ¿øÇÏ´Â ¹æ½ÄÀ¸·Î ±× Ŭ·¡½º¸¦ »ç¿ëÇÏ´Â °ÍÀÌ´Ù. ³ªÁß¿¡ ÀÌ Å¬·¡½º¸¦ »ç¿ëÇÏ´Â ¹æ¹ýÀ» ÀØÀ¸¸é Å×½ºÆ®¸¦ º¸°í ±¸Ã¼ÀûÀÎ ¿¹Á¦¸¦ º¼ ¼ö ÀÖ´Ù.

Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇϱâÀÇ °¡Àå Èï¹Ì·Î¿î Á¡Àº º¯¼ö ¹ß»ýÀÌ °¡´ÉÇϵµ·Ï ÇѴٴµ¥ ÀÖ´Ù. ¸¸µé°í ÀÖ´Â ½Ã½ºÅÛÀº ¼ºÀåÇØ¾ß ÇÑ´Ù. XP´Â Àüü ÀÛ¾÷À» ¼³°èÇÏÁö ¾Ê´Â´Ù. Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇÏ°í ±×µéÀ» Åë°ú½Ãų ¶§ ¿©·¯ºÐÀº Äڵ尡 ¿øÇÏ´Â °ÍÀ» ¼öÇàÇϵµ·Ï ÇÒ ¼ö ÀÖ´Ù. ´ÜÁö ÄÚµù¸¸À» ½ÃÀÛÇÑ´Ù¸é ´Ü¼øÈ÷ »ý°¢À» ±¸ÇöÇÏ°Ô µÉ °ÍÀÌ´Ù. ±×·¯ÇÑ °áÁ¤À» ¹Ì·ç¸é ¹Ì·ê¼ö·Ï ½Ã½ºÅÛÀ» º¸´Ù ÁÁ°Ô ¸¸µé ¼öÀÖ´Â »õ·Î¿î ¹æÇâÀ» ¹ß°ßÇÒ ±âȸ´Â ¸¹¾ÆÁø´Ù.

Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇÒ ¶§ ȯ»óÀûÀÎ ·ÎÁ÷ ¹üÀ§¸¦ °®°ÔµÈ´Ù. ³ª´Â Äڵ带 ÅëÇؼ­´Â ¸ðµç °æ·Î¸¦ ´Ù·ê ¼ö ¾ø´Ù. ÇÏÁö¸¸ Å×½ºÆ®¸¦ ÅëÇØ ¸¹Àº °ÍÀ» ´Ù·ç°Ô µÉ °ÍÀÌ´Ù. ´ëºÎºÐÀÇ »çÀü XP ÇÁ·ÎÁ§Æ®º¸´Ù ³ªÀº Å×½ºÆ® ½´Æ®¸¦ °®°í ÀÖ´Ù. ³ª´Â ±×·¯ÇÑ Å×½ºÆ®¸¦ ½ÇÇàÇÒ ¼ö ÀÖ´Ù. ´ÜÁö ÇϳªÀÇ ¹öÆ°À» ´©¸§À¸·Î¼­. ¸î ÃÊ ÈÄ¿¡ ³»°¡ ¸í·ÉÇÑ ´ë·Î Äڵ尡 ½ÇÇàµÇ´Â Áö¸¦ ¾Ë¼öÀÖ´Ù. ÆÀÀÇ ¸ðµç »ç¶÷µéÀº ¾ðÁ¦³ª Äڵ带 º¯°æÇÒ ¼ö ÀÖ´Ù. ½ÉÁö¾î ¹èÆ÷ÀÏ Àü±îÁöµµ. ÀÌ´Â ³ª¿¡°Ô ÇÁ·Î±×·¡¸Ó·Î¼­ È®½ÅÀ» ÁØ´Ù.

Extreme Programming Ä®·³ Çǵå¹é!
ÀÌ Ä®·³¿¡ ´ëÇÑ ¿©·¯ºÐÀÇ Çǵå¹éÀ» ±â´Ù¸³´Ï´Ù. XP°¡ ¹«¾ùÀΰ¡ ¶ó´Â Å« ¹®Á¦ ºÎÅÍ ¾î¸®¼®°Å³ª, ºÒ°¡´ÉÇÑ Áú¹®±îÁöµµ ȯ¿µÇÕ´Ï´Ù.

Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇÏÁö ¾Ê´Â ÀÌÀ¯

Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇÏ·Á¸é ÈÆ·ÃÀÌ ÇÊ¿äÇÏ´Ù. Å×½ºÆ®¸¦ ÀÛ¼ºÇÏ´Â °ÍÀÌ ½¬¿îÀÏÀÌ ¾Æ´Ï´Ù. ±×·¸´Ù°í Çؼ­ Å×½ºÆ®¸¦ ÀÛ¼ºÇÏÁö ¾Ê´Â´Ù¸é °á±¹ Å×½ºÆ®¸¦ °ÅÄ¡Áö ¾ÊÀº Äڵ带 °®°Ô µÈ´Ù. ´ÙÀ½ ½Ã½ºÅÛ ±â´ÉÀ» ÄÚµùÇÒ ¶§ ¾î¶² ºÎºÐÀÌ ¿Ã¹Ù¸£°Ô ÀÛµ¿ÇÏÁö ¾Ê´Â´Ù¸é ¾îµð¼­ ¹®Á¦¸¦ ãÀ» °ÍÀΰ¡? Å×½ºÆ® ¾øÀÌ ±× Áú¹®¿¡ ´ëÇÑ ´äÀ» È®½ÇÇÏ°Ô ¸»ÇØ ÁÙ ¼ö ¾ø´Ù. ¸ðµç °ÍÀÌ Àß µ¹¾Æ°¡´Â °Íó·³ º¸ÀÏÁö¶óµµ Áö±Ý ´çÀåÀº ³ªÅ¸³ªÁö ¾ÊÁö¸¸ ½Ã½ºÅÛ »óÀÇ ¾î¶² °ÍÀÌ À߸øµÇ ÀÖÀ» °ÍÀÌ ºÐ¸íÇÏ´Ù. Å×½ºÆ® ¾ø´Â µð¹ö±ëµµ ¸¶Âù°¡ÁöÀÌ´Ù.

Å×½ºÆà Åø°ú ±â¼ú
°ÅÀÇ ¸ðµç ¾ð¾î¿¡´Â xUnit ¶óÀ̺귯¸®°¡ ÀÖ´Ù. JUnitÀº ÀÚ¹Ù Ç÷§Æû¿ë ÀÛ¾÷À» Àß ¼öÇàÇÑ´Ù. ³ª´Â °³ÀÎÀûÀ¸·Î Eclipse IDE (Âü°íÀÚ·á)¸¦ »ç¿ëÇÏ°í ÀÖ´Ù. Eclipse´Â ¿ÀÇ ¼Ò½ºÀÌ°í ½ÇÇàÀÌ °¡´ÉÇÑ Å×½ºÆ® ½´Æ®°¡ ÀÖ´Ù. À̸¦ Åä´ë·Î ¸¹Àº Å×½ºÆ®¸¦ ¸¸µé ¼ö ÀÖ´Ù. »ç¿ëÇÒ ¼ö ÀÖ´Â ±â¼ú·Î´Â ObjectMother ÆÐÅÏ, Mock °´Ã¼, Sham °´Ã¼ µîÀÌ ÀÖ´Ù.

ObjectMother ÆÐÅÏ
ObjectMother ÆÐÅÏÀº Gang of Four Abstract Factory ÆÐÅÏÀÇ ½ÇÁ¦ ±¸ÇöÀÌ´Ù. (Âü°íÀÚ·á). ÀÌ°ÍÀº Å×½ºÆÿ¡ ÇÊ¿äÇÑ ÀνºÅϽº¸¦ ÁÖ±âÀ§ÇØ ÆÑÅ丮 °´Ã¼¸¦ ¸¸µéµµ·Ï ¸í·ÉÇÑ´Ù:

Listing 7. ObjectMother ¿¹Á¦

Seminar seminar = TF_Seminar.newFullyLoaded;
seminar.doSomething();
assertEquals("expectedValue", seminar.getValue());

Mock °´Ã¼
Mock °´Ã¼´Â Å×½ºÆà ¿ë °´Ã¼¸¦ ¹èÄ¡ÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù (Âü°íÀÚ·á). Mock °´Ã¼¿¡°Ô ½ÇÁ¦ ÄÄÆ÷³ÍÆ®°¡ °®±â ¿øÇÏ´Â ÀÎÅÍÆäÀ̽º¸¦ ÁØ´Ù. ±×·±´ÙÀ½ ½ÇÁ¦ ÄÄÆ÷³ÍÆ®°¡ Çü¼ºµÉ ¶§ ±îÁö mockÀ» »ç¿ëÇÑ´Ù. mockÀº Á¸ÀçÇÏÁö ¾Ê´Â ÄÄÆ÷³ÍÆ®¿¡°Ô´Â stub ±× ÀÌ»óÀÌ´Ù. Äڵ尡 mock¿Í ¾î¶»°Ô ÀÎÅÍ·¢ÆÃÇÏ´ÂÁö¸¦ Æò°¡ÇÒ ¼ö ÀÖ´Ù. Mock °´Ã¼´Â ¸¹ÀÌ ¾Ë·ÁÁ®ÀÖÁö¸¸ °ú¿ëµÇ°í ÀÖ´Â °Í °°´Ù.

Sham °´Ã¼
°¡²û¾¿Àº °°Àº ÀÎÅÍÆäÀ̽º¸¦ ±¸ÇöÇÏ°í Å×½ºÆ®¿¡¼­ ÀÌ°Í°ú ¾î¶»°Ô ÀÎÅÍ·¢ÆÃÇÏ´Â Áö¿¡ ´ëÇÑ Æ¯Á¤ ¹®Á¦¿¡ ´ëÇØ ´ë´äÇÒ ¼ö ÀÖ´Â fake °´Ã¼°¡ ÇÊ¿äÇÒ ¶§°¡ ÀÖ´Ù. sham °´Ã¼°¡ ±×·¸´Ù. sham °´Ã¼´Â ´ç½ÅÀÌ ÇÊ¿ä·ÎÇÏ´Â °ÍÀÌ ¹«¾ùÀÌµç µÉ ¼ö ÀÖ´Ù:

Listing 8. Person¿ë sham

protected class ShamPerson extends Person {
  protected boolean getAgeWasCalled;
  
  public int getAge() {
    getAgeWasCalled = true;
    return 25;
  }
}

ÇÁ·Î±×·¡¹Ö Çõ¸í
Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ Å×½ºÆ®¸¦ ÀÛ¼ºÇÏ´Â °ÍÀº ÇÁ·Î±×·¡¸Ó·Î¼­ÀÇ ³» »îÀ» Çõ½Å½ÃÄ×´Ù. ´ç½Å¿¡°Ôµµ ¸¶Âù°¡Áö·Î Àû¿ëµÉ °ÍÀÌ´Ù. ³» ÄÚµå´Â ¾ðÁ¦³ª ´Ü¼øÇÏ°í ±ú²ýÇÏ°í °­·ÂÇÏ´Ù. Äڵ带 ÀÛ¼ºÇϱâ Àü¿¡ Äڵ带 Å×½ºÆ®ÇÏ´Â ¹æ¹ýÀ» »ý°¢ÇÏ´Â ÈƷø¸À¸·Îµµ »óȲÀÌ ´õ ³ª¾ÆÁø´Ù. ¸ðµç ¼ÒÇÁÆ®¿þ¾î °³¹ßÆÀÀÌ XPÀÇ ¸¹Àº °ü½ÀÀ» °ÅÀýÇÏ°í Å×½ºÆ® ¿ì¼± ÀÛ¼ºÇÑ´Ù¸é ¼ÒÇÁÆ®¿þ¾î °³¹ß ¼¼°è´Â ¾öû ³ª¾ÆÁú °ÍÀÌ´Ù.

Âü°íÀÚ·á

¸ñ Â÷:
Å×½ºÆ® ¸ÕÀú ÀÛ¼ºÇϱâ
Å×½ºÆ®¸¦ ÀÛ¼ºÇÏ´Â ¹æ¹ý
Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇØ¾ß ÇÏ´Â ÀÌÀ¯
Å×½ºÆ®¸¦ ¸ÕÀú ÀÛ¼ºÇÏÁö ¾Ê´Â ÀÌÀ¯
Å×½ºÆà Åø°ú ±â¼ú
ÇÁ·Î±×·¡¹Ö Çõ¸í
Âü°í ÀÚ·á
ÇÊÀÚ ¼Ò°³
±â»ç¿¡ ´ëÇÑ Æò°¡
°ü·Ã dW ¸µÅ©:
Demystifying Extreme Programming series
Incremental development with Ant and JUnit
AspectJ¿Í mock °´Ã¼¸¦ ÀÌ¿ëÇÑ À¯¿¬ÇÑ Å×½ºÆÃ
Subscribe to the developerWorks newsletter
US ¿ø¹® Àбâ
Also in the Java zone:
Tutorials
Tools and products
Code and components
Articles
ÇÊÀÚ¼Ò°³
Roy W. Miller´Â ¼ÒÇÁÆ®¿þ¾î °³¹ßÀÚÀÌÀÚ ±â¼ú ÄÁ¼³ÅÏÆ®ÀÌ´Ù.
ÀÌ ±â»ç¿¡ ´ëÇÏ¿© ¾î¶»°Ô »ý°¢ÇϽʴϱî?

Á¤¸» ÁÁ´Ù (5) ÁÁ´Ù (4) ±×Àú±×·¸´Ù (3) ¼öÁ¤º¸¿ÏÀÌ ÇÊ¿äÇÏ´Ù(2) ÇüÆí¾ø´Ù (1)

  È¸»ç¼Ò°³  |  °³ÀÎÁ¤º¸ º¸È£Á¤Ã¥  |  ¹ý·ü  |  ¹®ÀÇ