Whiteship's Note


[Spring Security] Method Security Test

모하니?/Coding : 2010.03.19 21:15


    @PreAuthorize("hasRole('ROLE_MEMBER')")
    public boolean write(String contents) {
        while (graffitiRepository.getTotalRowCount() >= GRAFFITI_LIMIT_COUNT) {
            graffitiRepository.deleteFirstGraffiti();
        }
        Graffiti graffiti = new Graffiti(contents, securityService.getCurrentMember());
        graffitiRepository.add(graffiti);
        return true;
    }

위 코드는 봄싹 낙서장 서비스의 코드이다. 봄싹 메인 화면에 있는 낙서장은 최대 100개를 유지하며 ROLE_MEMBER 권한을 가지고 있는 사용자(이메일 인증 절차를 거친 기본 회원)라면 누구나 낙서를 추가할 수 있다.

이 코드의 내용 대부분은 단위 테스트로 커버가 가능하다. 하지만 스프링 시큐리티 애노테이션이 제대로 동작하는지는 어떻게 테스트 할 것인가?

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/testContext.xml", "/testContext-security.xml"})
@Transactional
public class MethodSecurityTest extends DBUnitSupport{

    @Autowired GraffitiService graffitiService;
    @Autowired GraffitiRepository graffitiRepository;

    @Before
    public void login() throws Exception {
        insertXmlData("testData.xml");
        SecurityContext securityContext = new SecurityContextImpl();
        Authentication authentication = new UsernamePasswordAuthenticationToken("whiteship@email.com", "passwd");
        securityContext.setAuthentication(authentication);
        SecurityContextHolder.setContext(securityContext);
    }

    @Test
    public void methodAuth(){
        assertThat(graffitiRepository.getAll().size(), is(0));
        graffitiService.write("hi");
        assertThat(graffitiRepository.getAll().size(), is(1));
    }

    @After
    public void after(){
        SecurityContextHolder.clearContext();
    }

}


이런식으로 테스트 할 수 있다.

1. 시큐리티 설정 파일을 테스트에서 만들 AC(ApplicationContext)용 설정에 추가한다.
2. DB에 xml로 작성한 가짜 사용자, 권한 정보를 넣어야 하니까 DBUnit을 편하게 사용할 수 있게 해주는 클래스를 이용한다.
3. 테스트 실행하기 전에 로그인 한다. (SecurityContextHolder에 SecurityContext를 넣는다.)
4. 테스트 실행한 뒤에 로그오프 한다. (SecurityContextHolder를 비워버린다.)


top


[OSAF 테스트 가이드 초안] 서비스 통합 테스트

OSAF : 2009.09.01 19:40


서비스 통합 테스트

(테스트할 메서드 내에서 new를 이용하여 객체를 생성하는 등) 의존성을 목킹하기 까다로운 상황 또는,
사용하는 DAO의 기능을 충분히 테스트 했으며, DAO 실행 시간이 오래 걸리지 않을 경우
굳이 목킹하여 단위테스트를 작성할 필요 없이 통합 테스트를 작성 할 수 있습니다.

테스트 하지 않을 것

서비스 단위 테스트와 동일합니다.

테스트 할 것

  • 서비스 단위 테스트에서 하지 않은 테스트

테스트 코드 작성 방법

  • 스프링 @Test 설정 추가
  • 테스트 클래스 이름

서비스 단위 테스트와 겹치지 않도록 테스트할 클래스 이름 뒤에 Test를 붙여줍니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testApplicationContext.xml")
@Transactional
public class PurYearPlanServiceImplTest {

@Autowired PurYearPlanServiceImpl service;

...
}
  • 테스트 작성하기
	@Test
public void update() {
PurYearPlan entity = new PurYearPlan();
service.add(entity);
assertThat(entity.getAmount(), is(new BigDecimal(0)));

entity.addDetail(makeNewDetailWithPriceAndQty(10, 7));
service.update(entity);
checkPriceQtyAndAmount(entity, 10, 7, 70);

entity.addDetail(makeNewDetailWithPriceAndQty(20, 3));
service.update(entity);
checkPriceQtyAndAmount(entity, 15, 10, 150);
}

private void checkPriceQtyAndAmount(PurYearPlan entity, int price, int qty, int amount) {
assertThat(entity.getPrice(), is(new BigDecimal(price)));
assertThat(entity.getQty(), is(new BigDecimal(qty)));
assertThat(entity.getAmount(), is(new BigDecimal(amount)));
}

private PurYearPlanDetail makeNewDetailWithPriceAndQty(int price, int qty) {
PurYearPlanDetail detail = new PurYearPlanDetail();
detail.setPrice(new BigDecimal(price));
detail.setQty(new BigDecimal(qty));
return detail;
}

생각해 볼 것

  • 서비스 단위 테스트와 통합 테스트 구분이 좀 애매 하다.

무조건 단위 테스트를 하기로 하고,
단위 테스트가 정 불편한 어떤 이유(그 이유를 정리해둬야겠다)를 가진 것들만 통합 테스트를 하는것이 좋치 않을까?

  • 서비스 단위 테스트와 통합 테스트의 성능 차이는 꽤 크다.

그런면에서도 통합테스트 보다는 단위 테스트가 더 좋아보인다.
쌓이고 쌓이고 쌓이다보면 빌드 하는데 엄청 오래 거릴 것이다.

  • 테스트 작성 및 이해가 비교적 쉽다

목킹을 하지 않기 때문인지, 목킹 코딩에 익숙치 않아서 인지,
목킹을 하면 역시 가독성도 떨어지고 테스트 작성이 완만하지 않다.
그럼 다시 반대로 통합 테스트를 기본으로 하고 복잡하고 오래 걸리는 DAO를 사용할 경우에만 단위 테스트로 옮길까?

top


[OSAF 테스트 가이드 초안] 서비스 단위 테스트

OSAF : 2009.09.01 19:34


서비스 단위 테스트

DAO를 사용하지 않는 부분을 테스트 하거나,
테스트 하려는 부분에서 사요하는 DAO 기능이 충분한 테스트를 거치지 않았거나,
테스트에서 사용하는 DAO가 아직 제대로 구현되지 않았거나,
실행이 오래 걸리는 DAO를 사용할 경우에
DAO를 목킹(mocking)하여 서비스 계층의 코드만 단위 테스트 할 수 있습니다.

테스트 하지 않을 것

DAO쪽으로 단순 위임하는 코드는 테스트하지 않습니다.

	public PurYearPlanDetail getPurYearPlanDetailById(int detailid) {
return dao.getPurYearPlanDetailById(detailid);
}

테스트 할 것

  • 서비스 인터페이스에 새로 추가하고 구현한 메서드
  • OSAF의 GenericService에서 상속받은 것을 재정의한 메서드

OSAF의 GenericService에서 상속 받은 것 중에서 재정의한 메서드를 테스트 합니다.

	public void update(PurYearPlan entity) {
super.update(entity);
entity.calcAll();
}
  • 비즈니스 로직

서비스에 포함되어 있는 복잡한 비즈니스 로직을 테스트 합니다.

	public void addPurYearPlanDetail(int yearplanid, PurYearPlanDetail detail) {
detail.calcAmount();
get(yearplanid).addDetail(detail);
}

public String getAutoGeneratedCode(Date year) {
String currentCode = null;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
String syear = formatter.format(year);

String previousCode = dao.getCurrentCode(year);
if (previousCode != null) {
Integer currentNo = Integer.valueOf(previousCode.substring(4)) + 1;
currentCode = (currentNo / 10) > 0 ? syear + currentNo.toString()
: syear + "0" + currentNo.toString();
} else {
currentCode = syear + "01";
}
return currentCode;
}

테스트 코드 작성 방법

  • Mockito 러너 추가

MockitoJUnitRunner를 추가합니다.

  • 테스트 클래스 이름

테스트 대상인 클래스 이름에 UnitTest를 붙여줍니다.

@RunWith(MockitoJUnitRunner.class)
public class PurYearPlanServiceImplUnitTest {

}
  • 의존성 Mocking

@Mock을 사용해서 의존하는 인터페이스에 대한 목 객체를 만들고, @Before를 붙인 setUp 메서드에서 테스트 객체에 주입해 줍니다.
@Mock을 이용하면 mock(PurYearPlanDao.class); 같은 코드를 호출하지 않아도 MockitoJUnitRunner에 의해 자동으로 목 객체가 생성됩니다.

@RunWith(MockitoJUnitRunner.class)
public class PurYearPlanServiceImplUnitTest {

PurYearPlanServiceImpl service;
@Mock PurYearPlanDao mockDao;

@Before
public void setUp() {
service = new PurYearPlanServiceImpl();
service.setDao(mockDao);
}
...
}
  • 테스트 작성

테스테에 필요한 객체들을 정의하고 테스트 이후에 변경되는 값의 현재 상태를 확인합니다.
Mockito의 stub()을 사용하여 목 객체가 어떻게 동작해야 하는지 정의해 줍니다.
그런 다음 테스트 하려는 메서드를 실행합니다.
마지막으로 비즈니스 로직이 제대로 수행되었는지 여러 객체의 상태들을 확입합니다.

	@Test
public void addPurYearPlanDetail() throws Exception {
PurYearPlan yearPlan = new PurYearPlan();
int yearplanid = 1;
yearPlan.setId(yearplanid);
PurYearPlanDetail detail = new PurYearPlanDetail();

when(mockDao.get(yearplanid)).thenReturn(yearPlan);

service.addPurYearPlanDetail(yearplanid, detail);
assertThat(yearPlan.getDetails().size(), is(1));
}

생각해 볼 것

  • 목킹을 사용하는 여러 가지 경우를 좀 더 구체적으로 작성해야겠다.
top


[OSAF 테스트 가이드 초안] DAO 통합 테스트

OSAF : 2009.09.01 18:32


어렴풋이 생각은 해봤었는데, 이번 기회에 정리해 보네요. 매우 주관적이며 OSAF 프레임워크를 사용하는 경우에 해당하는 가이드이기 때문에 통용될리는 없다고 생각합니다. 하지만 적어도 저한테는 이렇게 하는 것이 타당해 보이며, 조금만 응용하면, 다른 프레임워크 또는 별도의 프레임워크가 없는 경우에도 어느정도 적절할 것으로 보입니다. 그럼.. 차근차근 정리해 보겠습니다.

DAO 통합 테스트

DAO 테스트는 항상 데이터베이스를 필요로 하기 때문에 통합 테스트로 볼 수 있습니다.

테스트하지 않을 것

  • 프레임워크 코드

OSAF의 GenericDao로부터 상속받은 코드와 하이버네이트 코드는 테스트하지 않습니다.

테스트 할 것

  • 하이버네이트 도메인 모델 검증

도메인 모델에 맵핑 정보가 제대로 설정되었는지 확인합니다.
OSAF GenericDao가 제공하는 save로 도메인 모델을 저장해보는 것으로 확인합니다.

	@Test
public void crud() throws Exception {
Code code = new Code();
code.setCodeCate(CodeCate.CAR_TYPE);
code.setName("BLK");

cd.save(code);
}
  • DAO에서 재정의하는(overriding)하는 addRestrictions 메서드

해당 메서드에서 정의하는 검색 조건과 정렬 옵션에 따른 쿼리가 제대로 동작하는지 테스트 합니다.

	protected Criteria addRestrictions(Criteria c, CodeParams params) {
CriteriaUtils.ilike(c, "name", params.getName(), MatchMode.ANYWHERE);
CriteriaUtils.conditionalEq(c, "codeCate", params.getCodeCate());
c.addOrder(Order.asc("codeCate"));
return c;
}
  • DAO 인터페이스에 별도로 추가한 메서드의 구현체

OSAF에서 상속받지 않은 코드로, DAO 인터페이스에 추가하고, DaoImpl 클래스에서 구현한 메서드도 테스트가 필요합니다.

//DAO 인터페이스
public interface CodeDao extends GenericDao<Code, CodeParams> {
public List<Code> findByCodeCate(CodeCate codeCate);
}

//DAO 인터페이스 구현체
@Repository
public class CodeDaoImpl extends GenericDaoImpl<Code, CodeParams> implements CodeDao{

...

@SuppressWarnings("unchecked")
public List<Code> findByCodeCate(CodeCate codeCate){
return super.getSession().createCriteria(Code.class).add(
Restrictions.eq("codeCate", codeCate)).list();
}

}

테스트 코드 작성 방법

  • 스프링 @Test 선언

애노테이션 추가: DAO 테스트에 스프링 테스트 러너, 설정 파일 위치, 트랜잭션을 설정합니다.

테스트 설정 파일 위치: 테스트용 스프링 설정파일은 test 폴터 밑에 위치한 testApplicationContext.xml을 사용합니다.

트랜잭션 설정: OSAF의 DAO는 트랜잭션 당 세션을 유지하기 위해 getCurrentSession()을 사용하고 있기 때문에 @Transactional을 반드시 추가해야 합니다.

테스트 클래스 이름: 테스트할 DAO 구현체 이름뒤에 Test를 붙여서 작명합니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/testApplicationContext.xml")
@Transactional()
public class CodeDaoImplTest {

}
  • DBUnitSupport 클래스 상속.

DBUnit을 편하게 사용할 수 있도록 DBUbnitSupport 클래스를 상속 받습니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/testApplicationContext.xml")
@Transactional()
public class CodeDaoImplTest extends DBUnitSupport{

}
  • 테스트 데이터를 적성합니다.

XML 테스트 데이터가 필요한 경우 테스트 클래스와 동일한 패키지에 두어 접근성을 높여줍니다.
XML 테스트 데이터는 다음과 같이 작성합니다.

<dataset>
<code id="1" name="test" codeCate="10" />
<code id="2" name="test" codeCate="10" />
<code id="3" name="test" codeCate="20" />
<code id="4" name="test" codeCate="20" />
</dataset>
  • 테스트를 작성합니다.

테스트 데이터가 필요한 테스트는 DBUnitSupport에서 상속받은 insertXmlData();
또는 inserXlsData(); 메서드를 이용하여 테스트 데이터를 넣어줍니다.

	@Test
public void search() throws Exception {
insertXmlData("testData.xml");
CodeParams params = new CodeParams();
OrderPage orderPage = new OrderPage();

params.setName("te");
assertThat(cd.search(params, orderPage).size(), is(4));

params.setName("");
params.setCodeCate(PersistentEnumUtil.valueOf(CodeCate.class, 20));
assertEquals(2, cd.search(params, orderPage).size());
}

생각해볼 것

  • 테스트 데이터베이스와 실제 데이터페이스가 다르다

배포용으로는 MySQL을 사용하면서 테스트할 때는 HSQL을 사용한다. 과연 제대로 테스트 했다고 볼 수 있을까?



top


스프링의 이메일 기능 지원과 테스트를 살펴보자

Spring/etc : 2009.07.27 12:20


스프링이 지원하는 이메일은 JavaMail과 JAF라는 것이 있습니다. 사용법은 간단하니.. 다음에 심심할 때 살펴보기로 하고, 지금은 사부님이 올리신 글과 관련 된 부분을 찾아보는게 급선무입니다.

스프링 이메일 기능은 context.support 모듈에 들어있습니다. 주요 클래스는 o.s.mail.javamail에 들어있는 JavaMailSender 인터페이스와 그 구현체인 JavaMailSenderImpl 클래스입니다. 인터페이스의 API를 읽어보면 다음과 같은 내용이 있습니다.

...

Clients should talk to the mail sender through this interface if they need mail functionality beyond SimpleMailMessage. The production implementation is JavaMailSenderImpl; for testing, mocks can be created based on this interface. Clients will typically receive the JavaMailSender reference through dependency injection.

...

The entire JavaMail Session management is abstracted by the JavaMailSender. Client code should not deal with a Session in any way, rather leave the entire JavaMail configuration and resource handling to the JavaMailSender implementation. This also increases testability.

A JavaMailSender client is not as easy to test as a plain MailSender client, but still straightforward compared to traditional JavaMail code: Just let createMimeMessage() return a plain MimeMessage created with a Session.getInstance(new Properties()) call, and check the passed-in messages in your mock implementations of the various send methods.

즉, 이 API를 만든 의도에 사용성 편의 뿐만 아니라, 테스트 편의성도 포함되어 있다는 암시를 읽어낼 수 있습니다. JavaMail의 Session API를 사용하지 않고 스프링의 JavaMailSender를 목킹해서 테스트 하라는 것인데, 왜 그렇게 했는지는 맨 마지막 부분의 JavaMail의 Session API 사용법(Session.getInstance(new Properties())에서 볼 수 있습니다. 바로 static 메서드입니다.

JavaMail 레퍼런스에서 그 사용법을 보면, 다음과 같은 코드로 JavaMail을 이용하는 모습을 볼 수 있습니다.

//메시지를 만들고,,
     Properties props = new Properties();
     props.load(new FileInputStream(propfile));

     Session session = Session.getInstance(props, null);
     MimeMessage msg = new MimeMessage(session);

...

//전송합니다.
    // Set the content for the message and transmit
    msg.setContent(mp);
    Transport.send(msg);

코드 대부분을 생략했습니다. 중요한 부분은 위에 다 나와있습니다. 바로 static 메서드를 사용한다는 것이 중요한 부분입니다.

이런 API 사용을 클래스를 단위 테스트 하려면 막막합니다. 도무지 static 메서드를 호출하는 부분을 mock으로 바꿀 수가 없습니다. 그렇다고 테스트를 하는데 실제로 메일을 매번 보내기도 뭐하고 말이죠. 그래서 테스트 하려면 static 메서드 호출을 사용한 클래스를 거의 다시 만들다시피 구현한 stub을 만들어서 테스트 해야 하는데 이건 엄청난 수고가 필요합니다. JavaMail 예를 들면 거의 Transport를 테스트용으로 다시 구현해서.. sendMessage에서 실제로 메일을 보내지 않고 그냥 보내는 메시지 목록에 메시지만 모아두는 식의 작업이 필요해집니다. 그리고 테스트 할 떄는 그런 스텁 Transport를 사용하는 또 다른 스텁 MailSender가 필요해지겠죠.(실제로 이 작업들은 스프링의 JavaMailSenderTests에서 수행하고 있습니다.)

하지만, 테스트를 편하게 하는 방법이 아주 없는 건 아니었습니다. 오늘 톱님께서 올리신 글을 보면 static 메서드를 호출하는 코드를 비교적 편하게 테스트하는 방법 세 가지를 알 수 있습니다.

하나는 JavaMailSender처럼 static 메서드 호출 부분을 랩핑한 클래스를 만들고, 그 클래스를 목킹한 다음 해당 메서드가 호출되는지 테스트하는 것입니다. 그렇게 만들어 두면, 테스트 하려는 대상이 JavaMail의 Transport.send 같은 static 메서드를 호출하지 않고, 그것을 사용한 JavaMailSender를 사용하기 때문에 JavaMailSender의 mock을 만들고 그 객체의 send가 호출될 때 어떤걸 하라고 mocking 한다던지 해서 호출이 제대로 됐는지, 어떤 메시지가 넘어갔는지 등을 확인할 수 있겠습니다.

두 번째 방법은 로드존슨이 만들었다는 AspectJ를 이용하는 방법이고, 세 번째 방법은 PowerMock을 이용하는 방법인데, 둘 다 결국 바이트코드를 조작해서 static 호출 부분을 mock으로 호출로 교체하는 기술 인듯합니다. 이 두 가지는 일단 논외로 치

결론은.. 스프링의 JavaMailSender를 사용하면 JavaMail의 static 메서드 호출과 관련하여 테스트를 어떻게 작성할까 고민할 필요없이, JavaMailSender를 목킹해서 테스트를 만들면 된다는 것입니다.

덤으로 JavaMail의 static 메서드 호출을 사용한 JavaMailSender의 테스트 클래스를 보면, static 메서드 호출을 하는 클래스에 대한 테스트 실마리를 얻을 수 있습니다. static 메서드를 호출해서 가져오는 객체를 가져오는 부분을 별도의 메서드로 분리하고 그 부분을 테스트 용으로 재구현하고 그것을 테스트에서 사용하는 방법인데.. 이거 이거.. 귀찮아서 원... @_@..  그래서 static은 테스트의 적인가 봅니다. 그래도 이길 수 있는 적이라는거..
top


Cargo 메이븐 플러그인 설정하기

Good Tools : 2009.05.11 00:36


참조: http://cargo.codehaus.org/Maven2+plugin

상당히 간단하지만, 그 결과는 그다지 간단하지 않은 것 같습니다. 일단 설정은 이렇게 했습니다.

            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
                <configuration>
                    <container>
                        <containerId>tomcat6x</containerId>
                        <home>/apps/apache-tomcat-6.0.18</home>
                    </container>
                </configuration>
            </plugin>

이렇게 하고, cargo:start 골을 실행하면 톰캣 서버를 메이븐에서 실행할 수 있습니다. mvn cargo:start 이런식으로요.

테스트 진행은 다음 순서대로 할 겁니다.

WAR 파일 패키징 -> cargo를 사용하여 톰캣 서버 실행 -> 웹 (통합) 테스트 -> cargo를 사용한 톰캣 서버 정지

이 것을 그대로 메이븐 골로 옮겨 적으면 다음과 같습니다.

mvn package cargo:start test cargo:stop

그러나 이건 예상대로 동작하지 않습니다. 일단, 단위 테스트와 통합 테스트가 분리되어야 합니다. 단위 테스트를 실행하는데 굳이 카고를 이용하여 테스트 서버를 실행할 필요는 없기 때문이죠.

두 번째로 cargo:start를 실행하는 순간, 해당 커맨드 창은 이용할 수가 없습니다. 서버 로그가 뜨고 Ctrl+C를 눌러 서버 실행을 멈추기 전까지는 해당 커맨드 창이 먹통이나 다릅없습니다. 또 다른 콘솔을 띄우고 그 곳에서 테스트를 진행 한 다음 cargo:stop으로 서버 실행을 멈출 수 있습니다.

이 두 가지를 생각해 봤을 때 빌드가 2단으로 구성되어야 할 것 같습니다.

1단에서 할 일은 clean package(이 안에 complie, test 포함) cargo:start
2단에서 할 일은 integration-test, cargo:stop

궁금한 건 이러한 2단 빌드를 제공하는 CI 툴이 있느냐 하는 것과 메이븐으로 이런 구성을 하는 방법입니다. 후자는 금방 찾을 것 같은데 전자는 잘 모르겠네요. 기존 CI 툴의 plan을 잘 짜서 여러 plan끼리 의존성을 주며 실행하도록 할 수 있다면 가능할지도 모르겠고, 아예 하나의 plan으로 이러한 2단 빌드를 구성할 수 있게 해준다면 편리할 것 같습니다.
top


테스트는 진짜로 잘 만들어야 함

모하니?/Coding : 2008.04.25 22:51


오늘 테스트를 "제대로" 만들어야 함을 배웠습니다. 개발하고 배우고 느끼고 공부하고 혼나고 가끔 이렇게 공유도 하고 재밌습니다.

제가 만든 클래스는 제네릭 프로퍼티 에디터로, 특정 객체 타입이 오면 해당 객체가 가지고 있는 id 값을 화면에 보여주기 위한 클래스입니다. 즉 ${member} 라고 JSP에 적어두면 member 객체의 id를 사용합니다.

구현도 잘 했고, 테스트도 잘 했다고 생각해서 기분이 좋았었습니다. 그런데 이게 왠걸.. 실제로 돌아가는걸 보니까 잘 안 되는 것입니다. 제가 만든건 GenericPropertyEditor 입니다. 코드는 공개 안 하려고 했지만 어쩔 수 없네요.ㅋㅋ

아래가 구현한 코드입니다.
    public String getAsText() {
        T entity = (T) this.getValue();
        logger.info("entity = " + entity);
        if (entity == null)
            return "";
        else
            return String.valueOf(SimpleReflectionUtils.getValue(entityClass, entity, "id"));
    }

저걸 테스트 해보려고 다음과 같은 코드를 작성했습니다.
    @Test
    public void getAsText() throws Exception {
        Supp supp = new Supp();
        int id = 10;
        supp.setId(id);
       
        suppPropertyEditor.setValue(supp);
       
        assertEquals(String.valueOf(id), suppPropertyEditor.getAsText());
    }

잘 돌아갑니다.

그런데 분명 위의 코드에는 문제가 있습니다. 무슨 문제인지는 비밀입니다. 스프링, 하이버, @ManyToOne,Lazy Initialization, Proxy, id, getter, field 등을 조합해서 생각하면 문제를 발견하실 수도 있으실 테지만, 전 상상도 못했었습니다.

테스트를 기계적으로 만들지 말고 해당 클래스가 어떤 상황에서 어떤 역할을 하는지 고려해서 작성해야 한다는 걸 느꼈습니다.
top

TAG 테스트

9. Testing Techniques

View/JSP : 2007.06.26 12:41


책에서 다루고 있는 테스트 종류
    Regression Test :: Unit Test를 묶어 둔 것으로 새로운 기능을 개발하기 전에 실행. 즉 테스트는 다른 테스트에 독립적이어야 함.
    Unit Test :: 단일 메소드 또는 기능을 테스트 하는 것
    Load Test :: 병목현상이나 성능 측정을 위한 테스트

테스트가 왜 중요한가?
    제목하고 어울리는 내용은 아닌것 같은데 시나리오를 들어 설명하고 있었습니다. 갑이라는 사람이 a, b, c 메소드를 구현하고 테스트 합니다. 병이라는 사람이 해당 클래스에 d, e 메소드를 개발하고 테스트 합니다. 그리고 QA팀에 넘겨줬는데 에러가 납니다. 원인은 regression test를 하지 않았기 때문에...

JUnit 테스팅 프레임워크 소개
    역시나 이 프레임워크도 다들 알고 있을 법한 내용인지라...

JMeter 를 사용한 성능 테스트
    오.. 첨보는 거라 한번 해봐야겠습니다.

생각해볼 것
    1. 테스트가 중요함에도 테스트를 잘 작성하지 않는 이유?
    2. 개발하는 모든 메소드를 빠짐없이 테스트 해야 하는가?
    3. p192쪽의 제목 "애플리케이션에 단위 테스트 추가하기"의 코드는 정말 단위 테스트인가?
    4. JMeter 외에 성능 테스트를 위한 오픈소스는 없을까?
    5. 책에서 다루지 않고 있는 테스트의 종류에는 어떤 것이 있을까?

'View > JSP' 카테고리의 다른 글

태그 파일 배포하기  (0) 2008.09.14
태그 파일 활용 예제  (0) 2008.02.18
태그 파일  (2) 2008.02.18
JavaServer Pages Standard Tag Library  (5) 2008.02.18
JMeter 다운로드 & 사용해보기  (0) 2007.06.29
9. Testing Techniques  (2) 2007.06.26
6. The Decorating Filter Pattern  (0) 2007.06.20
5. Development Using Patterns  (0) 2007.06.06
4. Role Separation with Custom Tags  (0) 2007.06.01
3. Role Separation with JavaBeans  (0) 2007.05.29
Foundation of JSP Design Patterns 소스코드  (0) 2007.05.28
top