[펌] log4j 설정법

프로그래밍/Library 2007. 11. 28. 09:37 Posted by galad
[펌]log4j 설정법
참고파일



=============================================

본문서는 자유롭게 배포/복사 할수 있지만

이문서의 저자에 대한 언급을 삭제하시면 안됩니다

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

=============================================


LOG4J

I. 들어가면서.. 그리고 log4j


log4j는 자바 어플리케이션에서 빠르고 효과적으로 로깅 할 수 있도록 도와주는 오픈 소스 프로젝트입니다.


로깅(logging)은 코드의 가독성을 떨어뜨리는 단점이 있지만 애플리케이션에 문제가 있을 때 개발자가 자세한 상황을 파악할 수 있도록 해 주며 테스팅시 빠질 수 없는 요소입니다.


아마도 여러분들은 여러 어플리케이션이 추가되면서 각 개발자들만의 독특한 로깅방식이 서로 썩이고 얽혀서 화면에 나타나는것을 많이 봤을겁니다 -_-;
즉 로깅방법을 통일할 필요가 있는것이죠. 모든 개발자가 특정 포맷에 맞추어서 로깅 한다면 한결 로깅하기도 편하겠지요


오픈 소스 프로젝트인 Log4j는 개발자들이 매우 손쉽고 다양한 형태로 로깅을 할 수 있도록 도와줍니다. 성능또한 우수해 더이상 System.out.println을 사용할 필요가 없습니다.



II. 다운로드


다운로드 http://logging.apache.org/log4j/docs/download.html

매뉴얼 http://logging.apache.org/log4j/docs/documentation.html

API spec http://logging.apache.org/log4j/docs/api/index.html



III. LOG4J 구조


일단 log4j를 잘 모르지만 그 구조만 살짝 살펴보고 넘어갑시다

log4j는 크게 3가지 요소로 구성되며 그 구조는 다음과 같습니다

① Logger(Category) : 로깅 메세지를 Appender에 전달합니다.

② Appender : 전달된 로깅 메세지를 파일에다 기록할 것인지, 콘솔에 출력할 것인지

                   아니면 DB에 저장할 것인지 매개체 역활을 합니다.

③ Layout : Appender가 어디에 출력할 것인지 결정했다면 어떤 형식으로 출력할 것이지

                출력 layout을 결졍합니다.

쉽죠?



IV. LOG4J 로깅 레벨


log4j는 다양한 로깅레벨을 지원합니다.


① FATAL : 가장 크리티컬한 에러가 일어 났을 때 사용합니다.

② ERROR : 일반 에러가 일어 났을 때 사용합니다.

③ WARN : 에러는 아니지만 주의할 필요가 있을 때 사용합니다.

④ INFO : 일반 정보를 나타낼 때 사용합니다.

⑤ DEBUG : 일반 정보를 상세히 나타낼 때 사용합니다.


만약 로깅 레벨을 WARN 으로 설정하였다면 그 이상 레벨만 로깅하게 됩니다.

즉 WARN, ERROR, FATAL 의 로깅이 됩니다.



V. 샘플코드 1


jsp에서 사용하는 예제가 없어 만들어 봤습니다.


test.jsp


<%@ page contentType="text/html;charset=MS949"
 import="org.apache.log4j.Logger" %>

<%!
 static Logger logger = Logger.getLogger("test.jsp");
%>

<%
logger.fatal("fatal!!");

logger.fatal("fatal2!!", new NullPointerException("널입니다요"));

logger.error("error!", new NumberFormatException());

logger.error("error!2");

logger.warn("warn");

logger.info("info");

logger.debug("debug");
%>


결과 콘솔화면








static Logger logger = Logger.getLogger("test.jsp");

static 메소드 getLogger를 통해 logger 인스턴스를 가져옵니다.
getLogger에는 파라미터로 스트링 혹은 클래스를 사용하는데 jsp에서는 클래스를 파라미터로 주기에는 좀 애매합니다. 그냥 스트링으로 주도록 하지요


logger.fatal("fatal!!");
logger.fatal("fatal2!!", new NullPointerException("널입니다요"));
  
logger에 fatal 레벨의 메세지를 전달합니다. 다음 두가지 메소드를 지원하는군요

fatal(Object message)

fatal(Object message, Throwable t)

각 레벨마다 위처럼 두가지 메소드를 지원합니다.


지원 메쏘드
logger.fatal(Object message) logger.fatal(Object message, Throwable t)
logger.error(Object message) logger.error(Object message, Throwable t)
logger.warn(Object message) logger.warn(Object message, Throwable t)
logger.info(Object message) logger.info(Object message, Throwable t)
logger.debug(Object message) logger.debug(Object message, Throwable t)


VI. 샘플코드 2


서블릿의 경우 다음과 같이 코딩하면 되겠군요

TestServlet.java


import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestServlet extends HttpServlet {


    static Logger logger = Logger.getLogger(TestServlet.class);


    public void init(ServletConfig config) throws ServletException {
         super.init(config);
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

         try {
              ...
   
              logger.info("Hellow World~");

              ...

          } catch (Exception e) {
              logger.error("Error at TestServlet", e);
          }
     }
}



VII. LOG4J 설정


log4j 설정은 프로그램 내에서 할 수 있지만 설정파일을 사용함으로서 좀더 유연하게 log4j환경을 만들 수 있습니다.


프로그램에서 설정

<%@ page contentType="text/html;charset=MS949"
 import="org.apache.log4j.*,java.io.* "
%>

<%!
 static Logger logger = Logger.getLogger("log4j.jsp");
%>

<%
String layout = "%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n";
String logfilename = "DailyLog.log";
String datePattern = ".yyyy-MM-dd ";

PatternLayout patternlayout = new PatternLayout(layout);
DailyRollingFileAppender appender = new DailyRollingFileAppender(patternlayout, logfilename, datePattern);
logger.addAppender(appender);
logger.setLevel(Level.INFO);
logger.fatal("fatal!!");
%>


property 파일에 설정
log4j.properties를 만들어 /WEB-INF/classes 밑에 놓으세요



log4j.rootLogger=INFO, stdout, rolling

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender

log4j.appender.rolling.File=output.log

log4j.appender.rolling.Append=true

log4j.appender.rolling.MaxFileSize=500KB

log4j.appender.rolling.DatePattern='.'yyyy-MM-dd

log4j.appender.rolling.layout=org.apache.log4j.PatternLayout

log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n


#최상위 카테고리에 INFO로 레벨 설정 및 appender로 stdout, rolling을 정의

log4j.rootLogger=INFO, stdout, rolling

#stdout 어펜더는 콘솔에 뿌리겠다는 정의

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

#stdout 어펜더는 patternlayout을 사용하겠다는 정의

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

#페턴은 다음과 같이 포맷팅 하겠다는 것을 정의

log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n


#역시나 rolling 어펜더는 파일로 처리한다라고 정의

log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender

#로그 파일 이름은 output.log

log4j.appender.rolling.File=output.log

#true면 톰캣을 내렸다 올려도 파일이 리셋되지 않습니다.

log4j.appender.rolling.Append=true

#파일 최대 사이즈는 500KB로 설정

log4j.appender.rolling.MaxFileSize=500KB

#파일 포맷은 output.log.2005-03-10 으로 관리하겠다고 정의

log4j.appender.rolling.DatePattern='.'yyyy-MM-dd

#역시나 rolling 어펜더는 패턴 레이아웃을 사용하겠다고 정의

log4j.appender.rolling.layout=org.apache.log4j.PatternLayout

#rolling 어펜더는 패턴 레이아웃 포맷

log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n



VIII. 설정 포맷


로그파일명 포맷 (DatePattern)
로그파일명 포맷입니다. 날짜, 시간 및 분단위로까지 로그 파일을 분리할 수 있습니다.

형식 설명
'.'yyyy-MM 매달 첫번째날에 로그파일을 변경합니다
'.'yyyy-ww 매주의 시작시 로그파일을 변경합니다.
'.'yyyy-MM-dd 매일 자정에 로그파일을 변경합니다.
'.'yyyy-MM-dd-a 자정과 정오에 로그파일을 변경합니다.
'.'yyyy-MM-dd-HH 매 시간의 시작마다 로그파일을 변경합니다.
'.'yyyy-MM-dd-HH-mm 매분마다 로그파일을 변경합니다.



PatternLayout 포맷
로그자체를 어떤 포맷으로 남길지 결정합니다.
layout에는 HTMLLayout, PatternLayout, SimpleLayout, XMLLayout등이 있으며 PatternLayout이 일반적으로 가장 많이 쓰입니다.


형식 설명
%p debug, info, warn, error, fatal 등의 priority 가 출력된다.
%m 로그내용이 출력됩니다
%d 로깅 이벤트가 발생한 시간을 기록합니다.
포맷은 %d{HH:mm:ss, SSS}, %d{yyyy MMM dd HH:mm:ss, SSS}같은 형태로 사용하며 SimpleDateFormat에 따른 포맷팅을 하면 된다
%t 로그이벤트가 발생된 쓰레드의 이름을 출력합니다.
%% % 표시를 출력하기 위해 사용한다.
%n 플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다.
%c 카테고리를 표시합니다
예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다.
%C 클래스명을 포시합니다.
예) 클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다
%F 로깅이 발생한 프로그램 파일명을 나타냅니다.
%l 로깅이 발생한 caller의 정보를 나타냅니다
%L 로깅이 발생한 caller의 라인수를 나타냅니다
%M 로깅이 발생한 method 이름을 나타냅니다.
%r 어플리케이션 시작 이후 부터 로깅이 발생한 시점의 시간(milliseconds)
%x 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다.
%X 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다.

예시) (같은 색끼리 보시면 됩니다)

위의 test.jsp를 다음 포맷으로 출력해본다면

[%c] [%C] [%d] [%F] [%l] [%L] [%m] [%M] [%n] [%p] [%r] [%t] [%x] [%X]는 다음과 같다

[test.jsp] [org.apache.jsp.test_jsp] [2005-03-10 12:37:23,561] [test_jsp.java] [org.apache.jsp.test_jsp._jspService(test_jsp.java:64)] [64] [fatal!!] [_jspService] [개행] [FATAL] [765567] [http-8080-Processor25] [] []

'프로그래밍 > Library' 카테고리의 다른 글

[펌] Log4J...  (0) 2007.11.28
[펌] Log4j를 사용하여 Tomcat 5.x로깅 설정하기  (0) 2007.11.28
[펌] Log4J Configuration  (0) 2007.11.28
[펌] Log4J 사용하기  (0) 2007.11.28
[펌] Tomcat의 Logger(로거)가 이상해요..  (0) 2007.11.28

[펌] Log4J Configuration

프로그래밍/Library 2007. 11. 28. 09:37 Posted by galad
#####################################
#  Log4J Configuration                       #
#####################################

작성자 : 장형화(hhjang97@venus.uos.ac.kr)
작성일 : 2005. 08. 11
수정일 :

원본 :
설명 :


################################# ################################# #################################

LOG4J !!

디버그나 에러 확인을 위해 항상 사용하는 API입니다.

다양한 Level로 나눠서 설정 가능하며, System.out.println을 난발(?) 하지 않도록 도와주고 있죠 ^^;



설정 부분에서 필요한 부분을 그때그때 웹사이트 돌아다니며 찾았는데,

여기에 포스트 해놓고 필요할때 찾아 쓰려고요 ^^;



!-----------------------------------------------------------------------------!
! category(logger) 설정                                                                                    !
!-----------------------------------------------------------------------------!
log4j.debug=true
#log4j.disable=INFO
log4j.rootLogger=DEBUG, CONSOL, SYSTEM





!-----------------------------------------------------------------------------!
! appender(log destinations/targets) 와 옵션들을 설정                                         !
!-----------------------------------------------------------------------------!

! FILE에 로그 쓰기, 지정한 크기를 넘어서면 파일을 교체
log4j.appender.CONSOL=org.apache.log4j.ConsoleAppender


! 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.
log4j.appender.CONSOL.ImmediateFlush=true


! 이 appender 는 여기 명시된 priority 와 같거나 높은 메세지만 로깅한다
log4j.appender.CONSOL.Threshold=DEBUG


! Layout 형식 : TTCCLayout, HTMLLayout,  XMLLayout, PatternLayout, SimpleLayout
! PatternLayout, SimpleLayout - 자바의 Throwable 에러들과 예외를 무시한다
log4j.appender.CONSOL.layout=org.apache.log4j.PatternLayout


! %l - 소스코드의 위치정보를 출력한다. %C. %M(%F:%L) 의 축약형이다
log4j.appender.CONSOL.layout.ConversionPattern=%-5p %l %x =>%m%n







log4j.appender.SYSTEM=org.apache.log4j.DailyRollingFileAppender
log4j.appender.SYSTEM.File=C:/logs/system.html


! 매일 자정에 로그파일을 교체하며 기존파일은 xx.log_2004.07.12
log4j.appender.SYSTEM.DatePattern='.'yyyy-MM-dd
log4j.appender.SYSTEM.Threshold=DEBUG


! 자바의 Throwable 에러들과 예외를 포함하기 위해 HTMLLayout을 사용한다.
log4j.appender.SYSTEM.layout=org.apache.log4j.HTMLLayout


! [%d{yyyy-MM-dd}형식은 프로그램의 실행속도를 느리게 함으로 SimpleDateFormat 형식지정한다.
log4j.appender.SYSTEM.layout.DateFormat=ISO8601
! [YYYY-MM-DD HH:MM:SS, mm] 형식을 뜻한다.
log4j.appender.SYSTEM.layout.TimeZoneID=GMT-8:00


! %l - 소스코드의 위치정보를 출력한다. %C. %M(%F:%L) 의 축약형이다
log4j.appender.SYSTEM.layout.ConversionPattern=[%d] %-5p %l - %m%n







! 각 업무 상위패키지를 지정하여 logging 셋팅한다.


log4j.logger.rkhwang.biz.protoss=DEBUG, PROTOSS
log4j.logger.rkhwang.biz.teran=DEBUG, TERAN
log4j.logger.rkhwang.biz.zerg=DEBUG, ZERG





log4j.appender.PROTOSS=org.apache.log4j.DailyRollingFileAppender
log4j.appender.PROTOSS.File=C:/logs/protoss.log
log4j.appender.PROTOSS.DatePattern='.'yyyy-MM-dd
log4j.appender.PROTOSS.Threshold=DEBUG
log4j.appender.PROTOSS.layout=org.apache.log4j.PatternLayout
log4j.appender.PROTOSS.layout.DateFormat=ISO8601
log4j.appender.PROTOSS.layout.TimeZoneID=GMT-8:00
log4j.appender.PROTOSS.layout.ConversionPattern=[%d] %-5p %l - %m%n





log4j.appender.TERAN=org.apache.log4j.DailyRollingFileAppender
log4j.appender.TERAN.File=C:/logs/teran.log
log4j.appender.TERAN.DatePattern='.'yyyy-MM-dd
log4j.appender.TERAN.Threshold=DEBUG
log4j.appender.TERAN.layout=org.apache.log4j.PatternLayout
log4j.appender.TERAN.layout.DateFormat=ISO8601
log4j.appender.TERAN.layout.TimeZoneID=GMT-8:00
log4j.appender.TERAN.layout.ConversionPattern=[%d] %-5p %l - %m%n



log4j.appender.ZERG=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ZERG.File=C:/logs/zerg.log
log4j.appender.ZERG.DatePattern='.'yyyy-MM-dd
log4j.appender.ZERG.Threshold=DEBUG
log4j.appender.ZERG.layout=org.apache.log4j.PatternLayout
log4j.appender.ZERG.layout.DateFormat=ISO8601
log4j.appender.ZERG.layout.TimeZoneID=GMT-8:00
log4j.appender.ZERG.layout.ConversionPattern=[%d] %-5p %l - %m%n


#################################
#  참고 log4j.properties 파일
#################################

log4j.rootCategory=, dest2, C

log4j.appender.C=org.apache.log4j.DailyRollingFileAppender
log4j.appender.C.File= error.log
log4j.appender.C.layout=org.apache.log4j.PatternLayout
#log4j.appender.C.layout.ConversionPattern=[%d{yyyy-MM-dd hh:mm:ss}] %-5p [%-10t] %c{2} - %m%n
log4j.appender.C.layout.ConversionPattern=[%d{yyyy-MM-dd hh:mm:ss}] - %m%n
log4j.appender.C.Append=true
log4j.appender.C.DatePattern='.'yyyyMMdd
log4j.appender.C.Threshold=ERROR
log4j.appender.C.ImmediateFlush=true


log4j.appender.dest2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dest2.File=debug.log
log4j.appender.dest2.layout=org.apache.log4j.PatternLayout
#log4j.appender.dest2.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %-5p [%-10t] %c{2} - %m%n
log4j.appender.dest2.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] - %m%n
log4j.appender.dest2.Append=true
log4j.appender.dest2.DatePattern='.'yyyyMMdd
log4j.appender.dest2.Threshold=DEBUG
log4j.appender.dest2.ImmediateFlush=true



#---------------------------------------------------------------------
# %n - newline                                                               
# %m - your log message                                               
# %p - message priority (FATAL, ERROR, WARN, INFO, DEBUG or custom)          
# %r - millisecs since program started running                               
# %% - percent sign in output                                                
#                                                                            
#-----------------------SOME MORE CLUTTER IN YOUR LOG-------------------------
# %c - name of your category (logger), %c{2} will outputs last two components
# %t - name of current thread                                                
# %x - Nested Diagnostic Context (NDC) (you supply it)        
#                                                                            
#-------------------------SLOW PERFORMANCE FORMATS----------------------------
# %d - date and time, also %d{ISO8601}, %d{DATE}, %d{ABSOLUTE},              
#        %d{HH:mm:ss,SSS}, %d{dd MMM yyyy HH:mm:ss,SSS} and so on       
# %l - Shortcut for %F%L%C%M                                                 
# %F - Java source file name                                                 
# %L - Java source line number                                             
# %C - Java class name, %C{1} will output the last one component             
# %M - Java method name    
#-----------------------------------------------------------------------




#################################
#
#################################

[펌] Log4J 사용하기

프로그래밍/Library 2007. 11. 28. 09:36 Posted by galad
1. 서언
이 문서는 GPL을 따릅니다. 편의상 경어는 생략합니다. 이 문서에서 다루고 있는 범위는 Log4J의 설치 및 환경설정, 그리고 간단한 예제 프로그램의 구동까지입니다. 추가의 내용을 원하시는 분은 Log4J의 홈페이지에 가셔서 보면 Log4J에 대한 책을 소개하고 있으니 참고하시기 바랍니다.

2. Context
Log4J는 Jakarta 프로젝트의 Sub Project로 자바에서 손쉽게 로그를 만들 수 있도록 해 준다. 일반적으로 디버깅을 위해서는 System.out.println을 사용하게 된다. 아니면 자체적으로 로그 기능을 담당하는 간단한 로그 클래스를 작성하기도 한다. 하지만 오픈소스로 만들어진 다양한 기능을 제공하고 퍼포먼스도 빠른 로그 시스템인 Log4J를 사용한다면 개발자들은 로그 보다는 좀 더 비즈니스 로직에 충실할 수 있게된다.
이에 Log4J를 설치하고 사용해 보고 그 설정 및 샘플을 남겨 보았다.

Log4J에 대한 소개는 http://jakarta.apache-korea.org/log4j/index.html에 있으니 자세한 내용을 보길 원한다면 위 페이지를 참고한다. 위 페이지는 한글로 번역된 페이지라 읽기에 부담없으리라 생각한다.

3. Install & Configuration
먼저 Log4J를 다운 받는다. Log4J는 http://jakarta.apache.org/log4j/docs/download.html에서 최신 버전을 다운로드 받을 수 있다. 이 글을 쓰는 시점에서 최신 버전은 1.2.7이다.
파일을 다운로드 받은 다음에 적절한 디렉토리에 압축을 푼다. 여기서는 압축을 푼 디렉토리를 $LOG4J_HOME이라 하겠다. $LOG4J_HOME에 보면 INSTALL 이라는 파일이 존재한다. 반드시 이 파일을 먼저 읽어 보길 권한다.
이 파일에는 Log4J를 어떻게 설치하고 테스트하는지 잘 설명이 되어 있다. 또한 이 글에서는 언급하고 있지 않는 Dependency부분들을 설명하고 있으니 JDK버전이 다른 사람들은 반드시 읽고 Dependency를 체크해 보길 바란다.
$LOG4J_HOMEdistlib에 보면 log4j-1.2.7.jar 파일이 존재한다. 이 파일을 CLASSPATH에 추가를 한다.

자바로 개발을 하다 보면 이것저것 툴도 설치하는 것도 많고 여러 Jar파일들도 CLASSPATH에 추가해야 하는 경우가 많다. 이러한 모든 Jar파일들을 시스템 환경변수나 사용자 환경변수의 CLASSPATH에 추가하게 되면 나중에 CLASSPATH때문에 고생하는 경우가 발생된다. 따라서 이런 방법보다는 cmd파일 또는 sh파일에 환경 변수를 셋팅하는 Script를 만들어 두고 사용하는 것을 추천한다.

이제 클래스패스에 log4j-1.2.7.jar를 추가했으면 다음의 프로그램을 통해서 제대로 셋팅이 되었는지 체크해
보도록 하자.
############################## Test Program ##############################
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;

public class Hello {

  static Logger logger = Logger.getLogger(Hello.class);

  public
  static
  void main(String argv[]) {
  BasicConfigurator.configure();
  logger.debug("Hello world.");
  logger.info("What a beatiful day.");
  }
}
##############################  End of Program ##############################
위의 Hello.java를 컴파일을 하고 실행을 시켜본다.
만일 Exception in thread "main" java.lang.NoClassDefFoundError: Hello 이라는 메시지가 나온다면 클래스 패스에 현재 디렉토리(.)를 추가한다. 실행을 시켰을때,

10 [main] DEBUG Hello  - Hello world.
20 [main] INFO Hello  - What a beatiful day.

이런 Output이 나온다면 제대로 셋팅이 된 것이다.

4. Sample Program
이제 Log4J를 이용한 간단한 로그를 남기는 예제를 만들어보자. 이 예제는 3가지 종류의 로그를 남기는 아주 간단한 프로그램이다.
첫번째 로그는 파일로 로그를 남기면서 그 파일의 크기가 10KB 이상이면 백업으로 보관하고
새로운 파일에 로그를 작성하게 된다.
두번째 로그는 파일로 로그를 남기지만 날짜별로 백업을 남기게 된다.
세번째는 Project 전체에 대한 로그를 파일로 남기게 된다.

먼저 프로그램 코드를 보도록 하자.

############################## Sample Program ############################## import org.apache.log4j.*;

public class TestLogging {
  static Logger esoLogger = Logger.getLogger("posdata.log.esourcing");
  static Logger bidLogger = Logger.getLogger("posdata.log.ebidding");
  public static void main(String[] args) {

    esoLogger.debug("ESO Debug");
    bidLogger.debug("BID Debug");
    esoLogger.info("ESO INFO");
    bidLogger.info("BID info");
    esoLogger.warn("ESO WARN");
    bidLogger.warn("BID WARN");
    esoLogger.error("ESO ERROR");
    bidLogger.error("BID ERROR");
    init();
    property();
  }

  public static void init() {
    Logger hr = Logger.getLogger("posdata.log.hr");
    hr.debug("HR debug");
    hr.info("HR Info");
    hr.warn("HR Warn");
    hr.error("HR Error");
  }

  private static void property() {
    java.util.Properties props = System.getProperties();
    java.util.Enumeration enum = props.propertyNames();
    String key = null;
    while(enum.hasMoreElements()) {
      key = (String)enum.nextElement();
      bidLogger.info(key + " : " + props.getProperty(key));
    }
  }
}
############################## End of Program ##############################

다음은 위 프로그램의 로그설정을 가지고 있는 log4j.properties 파일이다. '#'표시는 주석문이 된다. ESO_Appender의 설정은 로그 파일의 크기가 10KB이상이 되면 백업으로 남기게 하는 설정이고, BIS_Appender의 설정은 날짜별로 백업을 남기게 되는 설정이다. 만일 여기에 설정된 Appener이외에 다른 것을 Logger를 사용 했다면 ROOT_Appender를 통해서 로그를 남기게 된다. 이 Properties 파일은 반드시 Classpath에 포함되어 있어야 한다.

############################## log4j.properties ##############################
log4j.rootCategory=DEBUG, ROOT_Appender
log4j.category.posdata.log.esourcing=INFO, ESO_Appender
log4j.category.posdata.log.ebidding=INFO, BID_Appender
log4j.additivity.posdata.log.ebidding=false
log4j.additivity.posdata.log.esourcing=false

# Set ESO_Appender specific options.
# log4j.appender.ESO_Appender=org.apache.log4j.ConsoleAppender
log4j.appender.ESO_Appender=org.apache.log4j.RollingFileAppender
log4j.appender.ESO_Appender.File=./eso.log
log4j.appender.ESO_Appender.Append=true
log4j.appender.ESO_Appender.MaxFileSize=10KB
log4j.appender.ESO_Appender.MaxBackupIndex=12
log4j.appender.ESO_Appender.layout=org.apache.log4j.PatternLayout
log4j.appender.ESO_Appender.layout.ConversionPattern=%d{<yyyy-MM-dd HH:mm:ss>} <%-5p> <%l>: %m%n

# Set BID_Appender specific options.
log4j.appender.BID_Appender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.BID_Appender.ImmediateFlush=true
log4j.appender.BID_Appender.File=./bid.log
log4j.appender.BID_Appender.Append=true
log4j.appender.BID_Appneder.DatePattern='.'yyyy-MM-dd
# log4j.appender.BID_Appender.MaxFileSize=10KB
# log4j.appender.BID_Appender.MaxBackupIndex=9
log4j.appender.BID_Appender.layout=org.apache.log4j.PatternLayout
log4j.appender.BID_Appender.layout.ConversionPattern=%d{<yyyy-MM-dd HH:mm:ss>} <%-5p> <%-l>: %m%n
# log4j.appender.BID_Appender.layout.ConversionPattern=%d{<yyyy-MM-dd HH:mm:ss>} %-15.15t %-8.8p %-30.30c %x: %m%n

# Set ROOT_Appender specific options.
log4j.appender.ROOT_Appender=org.apache.log4j.RollingFileAppender
log4j.appender.ROOT_Appender.File=./project.log
log4j.appender.ROOT_Appender.Append=true
log4j.appender.ROOT_Appender.MaxFileSize=10kb
log4j.appender.ROOT_Appender.MaxBackupIndex=9
log4j.appender.ROOT_Appender.layout=org.apache.log4j.PatternLayout
log4j.appender.ROOT_Appender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-15.15t %-8.8p %-30.30c %x %C %F %l %L %M: %m%n
############################ End of Properties File ############################

응용프로그램을 개발하다 보면 많은 System.out.println()을 남발하게 된다. 개발된 프로그램을 테스트하고 가동에 들어가면 System.out.println()문을 지우던가 아니면 지저분하게 두어야 하는 문제가 발생한다. 하지만 위와 같이 Log4J를 사용하면 개발과 테스트시에는 DEBUG 레벨로 두고 운영시에는 좀 더 레벨을 올려서 설정할 수 있게 되기에 좀 더 시스템 개발과 운영에 있어서 깔끔하게 된다. 또한 레벨별로 로그를 남길 수 있고 운영 중에도 동적으로 설정을 바꿀 수 있고, 로그를 남기는 형식 또한 다이나믹하게 지원하기 때문에 그 유용성이 크다고 볼 수 있다.

마지막으로 위에서 사용된 각 Pattern들의 인자값은
http://www.vipan.com/htdocs/log4jhelp.html에서 찾아볼 수 있다. 참고하길 바란다(단 해당문서가 Log4J Version 1.1을 기준으로 한거 같으니 잘 구별해서 사용하길 바란다).
 
Tomcat의 Logger(로거)가 이상해요..
Tomcat의 로거가 다음과 같은 오류를 내며 작동하지 않는다면...

log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester).
log4j:WARN Please initialize the log4j system properly.


혹은 내가 작성한 Log4j 를 사용하는 웹 어플리케이션의 로거가 내가 설정하지 않는 프라퍼티를 읽으려 들거나 한다면, 그것의 거의 log4j-*.jar가 의도하지 않게 클래스패스로 잡혀 있기 때문이다.

웹 어플리케이션의 log4j-*.jar 는 "WEB-INF/lib" 디렉토리 아래에만 둔다. 결코 "$CATALINA_HOME/common/lib" 등에 두지 말아야 한다.

또한 log4j-*.jar를 클래스 패스로 지정하지도 말고, $JAVA_HOME/jre/lib/ext 디렉토리에 둬서도 안된다.

이거 때문에 며칠 삽질... --;

절대 명심해야 할 사항중에 하나는 스스로 절대적인 확신이 없으면 $JAVA_HOME/jre/lib/ext 디렉토리에는 절대로 다른 *.jar 파일을 넣어 두면 안된다!!! 항상 수동으로 클래스패스를 설정하도록 하고, TOMCAT의 경우 WEB-INF/lib를 자기 스스로 클래스패스를 잡아주니, 그곳을 이용하도록 한다.
 
http://kwon37xi.egloos.com/2176400

Eclipse WTP에서 Apache Cactus사용하기

Cactus는 Web Application 에 올라가 있는 servlet, jsp, filter등을 테스트 할수 있도록 하는 JUnit 기반위의 Framework이다. (HttpUnit 과의 관계가 어떻게 되는지 모르겠네요..)

Cactus를 이용하여 서블릿에 대한 request를 설정하고 response를 확인할 수 있다.


  • New -> Java -> JUnit -> Servlet Test Case 를 클릭하여 Servlet Test Case를 만들면 자동으로 Cactus 설정이 프로젝트에 추가된다.
  • classpath 경로 안에 cactus.properties 파일을 만들고 아래와 같이 연동할 web application 의 url을 잡아준다.

  • 아래를 참고해서 Servlet Test Case를 만든다. beginXXX 에서 request를 보내기 전 작업을 할 수 있고, endXXX에서 response 에 대한 데이터를 확인할 수 있다.

public class ServletTest extends ServletTestCase {

    public void testProdSpecSel() throws IOException {

        ProdSpecSel servlet = new ProdSpecSel();

        servlet.service(request, response);

    }

    public void beginProdSpecSel(WebRequest request) throws Exception{

        String data = "product_spec";

        InputStream input = new ByteArrayInputStream(data.getBytes());

        request.setUserData(input);

    }

    public void endProdSpecSel(WebResponse response) throws Exception{

        System.out.println(response.getText());

    }

}

  • Web Application 을 띄운후 JUnit으로 실행하면 Test가 수행된다.

http://skccdev.pbwiki.com/Cactus

http://blog.naver.com/galad/140042153122

출처 블로그 > 쁘레오아저씨네
원본 http://blog.naver.com/freo39/110004398601

Table of Contents

Introduction

  • 개발자의 테스트 활동이 중요한 이유
    • 초기 단계에서 발견된 결함은 수정이 용이하다.
    • 개발 후기 단계에서 발견된 결함들을 수정하기에는 비용과 시간이 많이 소비되고,
      프로젝트가 실패될 확률이 높아진다.
    • 개발 단계에서의 효율적인 테스팅은 전체 프로젝트 시간을 감소시킨다.
  • 테스트의 종류
    • 단위테스트 : JUnit
      단위테스트는 단위 코드에서 문제 발생 소지가 있는 모든 부분을 테스트 하는 작업이다.
      보통 클래스의 public method 를 테스트 한다.
      좋은 단위 테스트란 모든 메서드를 테스트 하는 것이 아니라,
      상식 수준의 확인을 통해 단위 코드가 의도한 대로 동작하는지 여부를 판단하는 단계이다.
      이상적으로는 코딩전에 테스트 케이스를 작성하여 구현시 보조자료로 활용하는 것이 좋다. ( TDD의 기법 )
      단위테스트 후에 개발팀은 테스트를 프로젝트 테스트 스위트에 추가하여 매일 여러번 수행하고 모든 테스트를 항상 통과하게 해야 한다.
      기회가 된다면 Code Coverage 를 하는 것이 좋은데 오픈소스로는 JCoverage 등이 있다.
    • 통합/컨테이너 내부 테스트 : Cactus
      좋은 단위 테스트는 시스템내의 복잡한 부분에 관계없이 클래스 내의 함수들을 검사하는 것이다.
      단위 테스트는 가능한 의존성 없이 독립적으로 처리되어야 한다.
      Mock Object 로 테스트를 하는 경우도 있지만,
      Cactus 는 J2EE 컨테이너에 접근하는 방법을 제공한다.
      컨테이너 안에서 코드 테스트가 가능하도록 하기 위해서 Cactus 는 상세하거나 또는 까다로운
      실제와 같은 모형을(mock-ups) 개발자에게 제공한다.
      이 방법은 실행되는 코드가 제품이 출시되는 환경에서 실행되기 때문에 또 다른 피드백 기준을 제공한다.
      컨테이너 서비스와 상호 작용하는 단일 오브젝트 경우에 컨테이너 내부 테스트를 사용하여 간편한 단위 테스트를 할 수 있다.
    • 수락/기능 테스트 : HttpUnit
      기능 테스트는 전체 시스템이 의도한 바대로 동작하는 지를 검사하는 과정이다.
      이 방법은 완성된 시스템을 고객으로부터 검사받는 방법이므로 수락 테스트라고도 한다.
      기능 테스트는 구조적 기능에 대하여 어떤 프로그램의 기능에 대한 시험이며 진척 상태를 확인하고
      이전의 테스트나 누락된 결점을 잡아내거나 미완성 또는 불완전한 부분에서 발생된 문제를 찾아내는 것이 중요하다.
      수락 테스트는 고객에 의해 작성된다.
      기능 테스트는 항상 100% 구현될 필요는 없으나 제품 출시 전에는 100% 수행 되어야 할것이다.
      기능 테스는 종종 매우 구체적인 내용들을 테스트 하기도 한다.
      아직은 통괄적인 수락 테스팅 툴은 나오지 않았고 Junit은 어떤 자바클래스에서도 수행될 수 있으나
      수락 테스팅 도구는 특정 애플리케이션 요구에 따라 작성되어야 한다.
      HttpUnit을 이용하면 테스팅 API를 이용하여 웹 리소스에 대한 호출과 응답 값 조회를 프로그래밍 할 수 있도록 한다.

TDD

자동화된 테스트로 개발을 이끌어 가는 개발 방식을 테스트 주도 개발이라 부른다.
TDD는 분석 기술이며, 설계 기술이며, 개발의 모든 활동을 구조화하는 기술이다.
작동하는 깔끔한 코드(clean code that works).
이 핵심을 찌르는 한마디가 바로 테스트 주도 개발의 궁극적인 목표다.

테스트 주도 개발에서는 두 가지 단순한 규칙만을 따른다.

  • 오직 자동화된 테스트가 실패할 경우에만 새로운 코드를 작성한다.
  • 중복을 제거한다.

또한 위의 두 가지 규칙에 의해 프로그래밍 순서가 다음과 같이 결정 된다.

  • 빨강- 실패하는 작은 테스트를 작성한다. 처음에는 컴파일조차 되지 않을 수 있다.
  • 초록- 빨리 테스트가 통과하게끔 만든다. 이를 위해 어떤 죄악을 저질러도 좋다.
    (죄악이란 기존 코드 복사해서 붙이기-copy and paste, 테스트만 간신히 통과할 수 있게끔
    함수가 무조건 특정상수를 반환하도록 구현하기 등을 의미한다.)
  • 리팩토링- 일단 테스트를 통과하게만 하는 와중에 생겨난 모든 중복들을 제거한다

TDD 따라해보기

  • MyProject 라는 프로젝트를 만들었다. 메뉴> New> Project
  • TestCase를 생성한다. 이클립스에서는 TestCase와 TestSuite의 기본 템플릿을 제공하고 있다.
    메뉴> New> Other을 누르면 다음과 같은 창이 뜬다.

  • 생성할 TestCase 파일 이름 및 테스트 대상 클래스를 입력한다. (①)
    만약 setup() 메소드나 teardown() 메소드를 사용할 때는 해당 체크박스를 선택한다. (②)

  • 다음이 생성되었다.

  • 할일 목록을 작성해보자. 작업을 끝낸 항목에는 표시를 하고,
    또 다른 테스트가 생각나면 할일 목록에 새로운 항목을 추가할 것이다.

  • 자, 그럼 구현을 하기 위해 어떤 객체가 있어야 할까?
    방금 이건 속임수다. 객체를 만들면서 시작하는 게 아니라 테스트를 먼저 만들어야 한다.
    앞에서 언급한 TDD의 주기중 현재 단계는 빨강이다.
  • 그렇다면 어떤 테스트가 필요할까? 할일 목록을 보니 첫번째 테스트는 좀 복잡해보인다.
    작은 것부터 시작하든지, 아니면 손을 대지 않는 게 좋겠다. 이번엔 다음 항목인 곱하기를 보자.
    대단히 어렵진 않겠지? 이걸 먼저 하는게 좋겠다.
  • testMultiplication이라는 테스트를 추가해보자.

  • 다음 코드를 돌리면 당연히 에러가 난다. 메뉴> Run As> JUnit Test

  • 할일 목록에 3가지를 추가한다.

  • 빨간 막대기를 가능하면 빨리 초록 막대기로 바꾸고 싶다.
    실행은 안 되더라도 컴파일만은 되게 만들고 싶은데, 가장 쉬운 방법이 뭘까?
    이번 단계는 TDD주기에서 빨강에서 초록으로 넘어가는 과정이다.
  • 현재 네 개의 컴파일 에러가 있다.
    • Dollar 클래스가 없음
    • 생성자가 없음
    • times(int) 메서드가 없음
    • amount 필드가 없음
  • 네개의 컴파일 에러를 없앨 수 있는 가장 빠른 방법은 다음을 테스트 코드 아래 추가하는 것이다.


  • 당장의 목표는 완벽한 해법을 구하는 것이 아니라 테스트를 통과하는 것일 뿐이므로 최소한의 작업을 수행한다.

  • 테스트를 다시 실행해보자.

  • 드디어 초록색 막대가 나타났다. 하지만 아직 주기가 완성되지 않았으니까 서둘지 않는게 좋겠다.
    우리는 TDD의 주기중 빨강/초록을 넘었다.
  • 다음 단계는 리팩토링이다.코드를 다음과 같이 바꿔준다.

  • 테스트는 통과하고 테스트 막대 역시 초록색이다. 우리는 여전히 행복하다.

  • 이 단계가 너무 작게 느껴지는가? 하지만 기억하기 바란다. TDD의 핵심은 이런 작은 단계를
    밟아야 한다는 것이 아니라, 이런 작은 단계를 밟을 수 있는 능력을 갖추어야 한다는 것이다.
  • 5를 어디서 얻을 수 있을까? 이건 생성자에서 넘어오는 값이니 이걸 다음과 같이 amount 변수에 저장하면,

  • 그걸 time()에서 사용할 수 있다.
    인자 multiplier의 값이 2이므로, 상수를 이 인자로 대체할 수 있다.

  • 마지막으로 우리가 자바 문법을 완벽하게 알고 있다는 것을 보여주기 위해 *=연산자를 써주자.( 물론 중복을 제거하기 위해서다. )

  • 이제 첫 번째 테스트에 완료표시를 할 수 있게 되었다.

  • 마무리 - 우리는 다음과 같은 작업들을 해냈다.
    • 우리가 알고 있는 작업해야 할 테스트 목록을 만들었다.
    • 오퍼레이션이 외부에서 어떻게 보이길 원하는지 말해주는 이야기를 코드로 표현했다.
    • JUnit에 대한 상세 사항들은 잠시 무시하기로 했다.
    • 스텁 구현을 통해 테스트를 컴파일했다.
    • 끔찍한 죄악을 범하여 테스트를 통과시켰다.
    • 돌아가는 코드에서 상수를 변수로 변경하여 점진적으로 일반화했다.
    • 새로운 할 일들을 한번에 처리하는 대신 할일 목록에 추가하고 넘어갔다.

TDD의 특징

  • 격리된 테스트
  • 테스트 목록
  • 테스트 우선
  • 단언 우선
  • 명백한 데이터

TDD와 관련된 의문

  • 단계가 얼마나 커야 하나?
  • 테스트 할 필요가 없는 것은 무엇인가?
  • 좋은 테스트를 갖췄는지의 여부를 어떻게 알 수 있는가?
  • TDD로 프레임워크를 만들려면 어떻게 해야하나?
  • 피드백이 얼마나 필요한가?
  • 테스트를 지워야 할 때는 언제인가?
  • 프로그래밍 언어나 환경이 TDD에 어떤 영향을 주는가?
  • 거대한 시스템을 개발할 때도 TDD를 할 수 있는가?
  • 애플리케이션 수준의 테스트로도 개발을 주도할 수 있는가?
  • 프로젝트 중반에 TDD를 도입하려면 어떻게 해야 할까?
  • TDD는 누구를 위한 것인가?
  • TDD는 초기 조건에 민감한가?
  • TDD와 패턴의 관계는?
  • 어째서 TDD가 잘 동작하는가?
  • TDD와 익스트림 프로그래밍의 실천법 사이에는 어떤 관련이 있는가?

JUnit

▪ 다운로드 : http://www.junit.org/

JUnit 기본 클래스

1. TestCase 클래스 : 가장 간단하게 Junit을 사용하는 방법은 TestCase 클래스를 상속받은 클래스를 작성하는 것이다. 이 클래스에는 test로 시작하는 메소드만 나열하면 된다.

2. TestSuite 클래스 : testCase 클래스를 상속받은 클래스만을 사용하다 보면, 일부의 test 메소드는 간혹 실행하지 않고 싶거나 특정한 test 메소드만 실행하고 싶을 때가 생긴다. (①) 또는 Test 클래스를 한데 묶어서 한꺼번에 실행하고 싶은 경우(②)도 발생한다. 이때 사용하는 것이 바로 TestSuite이다.

3. Assersions

4. Fixture : 초기 값 설정 및 해제 – setUp(), teardown()


JUnit4.0에서의 변경사항

  • Test Annotation
    이전 버전에서 사용했던 TestCase를 대신에 org.junit.Test를 임포트하여 다음과 같은 형식으로 사용한다.
    • @Test public void functionName() { }
  • Expected Exception
    @Test Annotation은 "expected" 라는 파라메터를 option 으로 가지고 있는데
    이것은 Throwable의 서브 클래스들을 값으로 취한다.
    • @Test(expected= IndexOutOfBoundsException.class) public void empty() {
      new ArrayList<Object>().get(0);
      }
  • Timeout
    @Test Annotation은 long형 파라메터를 통해 timeout을 설정할 수 있다.
    • @Test(timeout=100) public void infinity() {
      for ( ; ; );
      }
  • Fixture
    • setup - Before Annotation
      • import org.junit.Before;
        @Before public void functionName()
    • tearDown - After Annotation
      • import org.junit.After
        @After public void functionName()
  • Ignore Annotation
    때때로 일시적으로 테스트를 작동시키지 않을 때가 있는데 Ignore이라는 Annotation을 사용할 수 있다.
    Ignore하는 이유를 옵션 파라메터를 통해 기록할 수 있다.
    • @Ignore("not ready yet") @Test public void something()

단위 테스트 지침 요약

일반 원칙

  • 망가질 가능성이 있는 모든 것을 테스트한다.
  • 망가지는 모든 것을 테스트한다.
  • 새 코드는 무죄가 증명되기 전까지는 유죄.
  • 적어도 제품 코드만큼 테스트 코드를 작성한다.
  • 컴파일 할 때마다 지역 테스트를 실행한다.
  • 저장소에 체크인하기 전에 모든 테스트를 실행해 본다.

자문해 봐야 할 사항

  • 이 코드가 옳게 동작한다면 어떻게 그것을 알 수 있는가?
  • 이것을 어떻게 테스트할 것인가?
  • ‘그밖에’ 어떤 것이 잘못될 수가 있는가?
  • 이와 똑같은 종류의 문제가 다른 곳에서도 일어날 수 있을까?

좋은 테스트란?

좋은 테스트는 'A- TRIP' 해야 한다.

  • 자동적('A'utomatic)
    • 테스트가 혼자 실행되고 자신을 검증할 수 있어야 한다.
  • 철저함('T'horough)
  • 반복 가능('R'epeatable)
    • 모든 테스트가 어떤 순서로든 여러 번 실행될 수 있어야 하고, 그때마다 늘 같은 결과를 내야 한다.
  • 독립적('I'ndependent)
    • 확실히 한 대상에 집중한 상태여야 한다.
    • 환경과 다른 개발자들에게서 독립적인 상태를 유지해야 한다.
    • 어느 테스트도 다른 테스트에 의존하지 않는다.
  • 전문적('P'rofessional)
    • 좋은 설계를 위한 모든 일반적인 규칙, 캡슐화 유지, DRY 원칙 지키기, 결합도 낮추기 등은 제품 코드에서 그랬듯이 테스트 코드에서도 반드시 지켜져야 한다,

무엇을 테스트 할 것인가?

: Right-BICEP (오른쪽 이두박근이라는 뜻)

  • Right - 결과가 옳은가?
    예)
  • B - 모든 경계('B'oundary) 조건이 correct 한가?
    <경계 조건에서 확인해봐야 할 사항들 - 'CORRECT'>
    • 형식 일치('C'onformance) – 값이 기대한 형식과 일치 하는가?
      예) 최상위 도메인 이름이 없는 이메일 주소 fred@foobar 이 넘어온다면?)
    • 순서('O'rdering) – 적절히 순서대로 되어 있거나 그렇지 않은 값인가?
      예)
    • 범위('R'ange) – 적당한 최소값과 최대값 사이에 있는 값인가?
      예)
    • 참조('R'eference) – 코드가 자기가 직접 제어하지 않는 외부 코드를 참조하는가?
      예)
    • 존재성('E'xistance) – 값이 존재 하는가?
      예) null이 아님, 0이 아님, 집합 안에 존재함)
    • 개체 수('C'ardinality) – 확실히 충분한 값이 존재하는가? 개수를 정확히 필요한 만큼 갖고 있다던가, 정확히 필요한 만큼 만들었다는 것을 확인해야 한다.
      예) 울타리 기둥 에러, 하나 차이에 의한 오류
    • 시간 ('T'ime) (절대적으로 그리고 상대적으로) – 모든 것이 순서대로 일어나는가? 제시간에? 때 맞추어?
      예) 로그인하기 전에 문서를 출력하려고 시도하는 것
  • I - 역('I'nverse) 관계를 확인할 수 있는가?
    예)
  • C - 다른 수단을 사용해서 결과를 교차 확인('c'ross-check) 할 수 있는가?
    예)
  • E - 에러조건('e'rror condition)을 강제로 만들어 낼 수 있는가?
    현실 세계에서는 에러가 발생한다. 여러분은 강제로 에러를 일으켜 코드가 현실 세계의 문제를 제대로 처리한다는 것을 테스트 할 수 있어야 한다.
    네트워크 에러 등을 시뮬레이션 하는 경우 모의객체(mock object)를 사용할 수 있다.
  • P - 성능('P'erformance) 특성이 한계 내에 있는가?
    예)

프로젝트에서 테스트하기

1. 테스트 코드를 어디에 둘 것인가?

  • 같은 디렉터리
    • 장점: TestAccont가 Account의 보호된 멤버 변수와 메서드에 접근할 수 있다.
    • 단점: 테스트 코드가 제품 코드 디렉터리의 공간을 잡아먹으면서 어질러져 있다.
  • 하위 디렉터리
    • 장점: 태스트 코드를 적어도 제품 코드와 똑 같은 디렉토리에 있지 않게 떨어뜨려 놓을 수 있다.
    • 단점: 테스트 코드가 다른 패키지에 있으므로 필요한 멤버들을 노출시키는 제품 코드의 하위 클래스를 사용하지 않는다면 테스트 코드는 보호된 멤버에 접근할 수 없다.
  • 병렬 트리
    • 장점: 테스트 코드와 제품 코드가 정말로 분리되었다. 테스트 코드가 같은 패키지에 있기 때문에 선택적으로 접근할 수 있다.
    • 단점: 편하게 쓰기에는 너무 멀리 떨어져버린 건지도 모른다.

2. 테스트 예절

  • 혼자하는 테스트와 다른 사람과 함께하는 테스트의 가장 큰 차이점은? 테스트 코드의 동기화
  • 팀 환경에서 코드를 체크인 할 때는, 그 코드가 단위 테스트를 완료하였고,모든 단위 테스트가 통과했다는 것을 확인해야한다.
    사실상, 전체 시스템의 코든 테스트가 새로운 코드에 대해 계속 통과해야 한다.
  • 잠재적 위반사항 목록을 만들자
    • 불완전한 코드(예: 클래스 파일 하나만 체크인 하고 그것이 의존할 수 있는 다른 파일은 체크인 하는 것을 잊어버린 경우)
    • 컴파일 되지 않는 코드
    • 컴파일 되기는 하지만, 다른 코드를 망가뜨려서 컴파일 되지 않게 만드는 코드
    • 대응하는 단위 테스트가 없는 경우
    • 단위테스트가 실패하는 코드
    • 자신의 테스트는 통과하지만, 시스템의 다른 테스트를 실패하게 만드는 코드

3. 테스트 빈도

  • 새 메서드를 작성할 때마다 지역 단위 테스트들을 컴파일하고 실행한다.
  • 버그를 고칠 때마다 버그를 드러내는 테스트를 시행한다.
  • 성공적으로 컴파일 할 때마다 지역 단위 테스트들을 실행한다.
  • 버전 관리 시스템에 체크인할 때마다 모든 모듈 또는 시스템의 단위 테스트들을 실행한다.
  • 따로 배정된 특정 컴퓨터가 자동으로 하루 종일(주기적으로, 또는 버전 관리 시스템에 체크인 할 때마다),
    처음부터 전체 빌드와 테스트를 수행하고 있어야 한다.

4. 테스트와 레거시 코드

  • 이미 있던 코드의 경우 : 가장 망가진 부분을 위한 테스트를 가장 먼저 추가하는 편이 좋다.
    이런 환경에서 실시하는 단위 테스트는 뒷걸음 질을 막는다.
    즉, 유지 보수하기 위해 수정하고 개선하다가 이미 있는 부분들에 버그를 만들어 내는 죽음의 나선을 피할 수 있다.
  • 연속적 빌드-테스트 프로그램을 사용하여 코드가 저장소에 전송될 때마다
    자동으로 단위테스트가 실행되게 만든다면 불량코드가 전체 회사에 돌아다니는 일을 방지할 수 있다.

5. 테스트와 검토

  • 코드 검토를 수행할 때, 그 검토과정의 필수 구성요소로 테스트 코드를 끼워넣어라
  • 코딩과 검토를 다음 순서로 하면 좋다
  • 테스트 케이스나 테스트 코드, 둘 다를 작성한다.
    1. 테스트 케이스나 테스트 코드, 또는 둘 다를 검토한다.
    2. 테스트 테이스나 테스트 코드, 또는 둘 다를 검토할 때마다 수정한다.
    3. 테스트를 통과하는 제품 코드를 작성한다.
    4. 제품코드와 테스트 코드를 검토한다.
    5. 검토할 때마다 테스트 코드와 제품코드를 수정한다.
    6. 모든 팀원을 이 과정에 참여시킴으로써 팀의 의사소통을 증진시킬 수 있다.
      다른 이들이 어떻게 테스트 하는지, 팀의 규칙이 무엇인지 알게된다.

설계와 관련된 문제들

1. 테스트의 용이성을 높이는 설계

2. 테스트를 위한 리팩토링

3. 클래스의 불변성(invariant)을 테스트 하기

  • 구조적
    • 주문 정보 입력 시스템은 다음과 같은 불변성을 가질 수 있다.
      • 모든 개별 항목은 어떤 주문에 속해야 한다.
      • 모든 주문은 개별 항목 하나 이상을 가져야 한다.
    • 데이터 배열을 다룰 때 인덱스 노릇을 하는 멤버 변수는 다음과 같은 불변성을 가질 수 있다.
      • 인덱스는 >=0이어야 한다.
      • 인덱스는 < 배열 길이여야 한다.
  • 수학적
    • 은행 계좌의 입금 부분과 출금 부분을 계산하면 잔고와 맞아 떨어져야 한다.
    • 다른 단위로 측정된 양은 변환 후에 맞아떨어져야 한다.
  • 데이터의 정합성(consistency)
    • 쇼핑 카트에 들은 항목 목록, 전체 판매액, 그 쇼핑 카트에 들은 전체 항목 개수는 밀접한 관련이 있다.
      항목 목록의 구체적인 내용을 알면, 다른 두 수치를 이끌어 낼 수 있다. 이 수치들이 조화를 이루어 맞아
      떨어진다는 사실은 불변성이 되어야 한다.

참고문헌

  • 이클립스 기반 프로젝트 필수 유틸리티 CVS,Ant,JUnit (민진우 & 이인선 공저, 한빛미디어)
  • 테스트 주도 개발 (켄트 벡 저, 김창준 & 강규영 역,인사이트)
  • 실용주의 프로그래머를 위한 단위 테스트 with JUnit (데이비스 토머스 & 앤드류헌트 공저, 이용원 & 김정민 역, 인싸이트)
  • 참고 싸이트 - TDD를 공부하고 싶다면?
    http://wiki.tdd.or.kr/wiki.py
    http://c2.com/cgi/wiki?TestDrivenDevelopment
    http://xper.org/wiki/xp/

문서에 대하여

최초작성자 : OSS:오혜진
최초작성일 : 2006년 2월 19일
버전 : 1.0 ? ㅎㅎ
문서이력 :

  • 2005년 2월 19일 오혜진 문서 최초 생성
  • 2005년 2월 20일 JUnit4.0에서의 변경사항 추가
  • 2005년 2월 21일 오픈소스스터디 1기 장회수님 자료 참고하여 보완, 테스트의 종류 추가
  • 2005년 2월 24일 프로젝트에서 테스트하기 항목 추가 및 문서 구조 수정


[펌] http://wiki.javajigi.net/display/OSS/TDD#TDD-JUnit4.0%EC%97%90%EC%84%9C%EC%9D%98%EB%B3%80%EA%B2%BD%EC%82%AC%ED%95%AD


http://blog.naver.com/galad/140035831360

출처 블로그 > 青山に会社を立ち上げるぞ。!!
원본 http://blog.naver.com/heopd000/80035503179

JUnit을 이용한효율적인테스트전략

Table of Contents

테스트란?

  • 자동화된 테스트란? 유형은?
    • 단위테스트 : JUnit
    • 통합/컨테이너 내부 테스트 : Cactus
    • 수락/기능 테스트 : HttpUnit.

Preview

  • 자동화된 테스트란? 유형은?
    • 자동화된 테스팅이란 특히 XP에서 중요시 되는 활동이다.
    • 물론 어느 방법론에 국한될 필요는 없으나
    • 어떤 점에서 잇점이 있는지의 여부의 판단은 중요하다고 생각한다.
    • XP의 중요한 문제는 리팩토링이다.
    • 리팩토링이란 간단하게 설명하면 오브젝트 책임의 명확성과 중복의 제거,
    • 그리고 코드의 간결함 일것이라 생각한다.
    • 자동화된 테스팅은 리팩토링을 하는 프로그래머에 확신을 준다.
    • 그리고 리팩토링은 궁극적으로 테스트를 통해서 완성이 된다.
  • 자동화된 테스트 유형
    • unit test는 가장 많이 언급되는 테스트 유형이나 이것은 전체테스팅의 일부이다.
    • 단위테스트는 통합테스트, 기능 테스트, 기타 테스트와 함께 사용되어 시스템의 동작이 의도에 맞게 동작함을 보증한다.
  • 테스트의 종류 ( 간략하게 정리 )
    • 단위테스트 : JUnit
      • 단위테스트는 단위 코드에서 문제 발생 소지가 있는 모든 부분을 테스트 하는 작업이다.
      • 보통 클래스의 public method 를 테스트 한다.
      • 좋은 단위 테스트란 모든 메서드를 테스트 하는 것이 아니라,
      • 상식 수준의 확인을 통해 단위 코드가 의도한 대로 동작하는지 여부를 판단하는 단계이다.
      • 이상적으로는 코딩전에 테스트 케이스를 작성하여 구현시 보조자료로 활용하는 것이 좋다. ( TDD의 기법 )
      • 단위테스트 후에 개발팀은 테스트를 프로젝트 테스트 스위트에 추가하여 매일 여러번 수행하고 모든 테스트를 항상 통과하게 해야 한다.
      • 기회가 된다면 Code Coverage 를 하는 것이 좋은데
      • 오픈소스로는 JCoverage 등이 있다. - 참고 : j2eestudy자료
    • 통합/컨테이너 내부 테스트 : Cactus
      • 좋은 단위 테스트는 시스템내의 복잡한 부분에 관계없이 클래스 내의 함수들을 검사하는 것이다.
      • 단위 테스트는 가능한 의존성 없이 독립적으로 처리되어야 한다.
      • Mock Object 로 테스트를 하는 경우도 있지만,
      • Cactus 는 J2EE 컨테이너에 접근하는 방법을 제공한다.
      • 컨테이너 안에서 코드 테스트가 가능하도록 하기 위해서 Cactus 는 상세하거나 또는 까다로운
      • 실제와 같은 모형을(mock-ups) 개발자에게 제공한다.
      • 이 방법은 실행되는 코드가 제품이 출시되는 환경에서 실행되기 때문에 또 다른 피드백 기준을 제공한다.
      • 컨테이너 서비스와 상호 작용하는 단일 오브젝트 경우에 컨테이너 내부 테스트를 사용하여 간편한 단위 테스트를 할 수 있다.
    • 수락/기능 테스트 : HttpUnit
      • 기능 테스트는 전체 시스템이 의도한 바대로 동작하는 지를 검사하는 과정이다.
      • 이 방법은 완성된 시스템을 고객으로부터 검사받는 방법이므로 수락 테스트라고도 한다.
      • 기능 테스트는 구조적 기능에 대하여 어떤 프로그램의 기능에 대한 시험이며 진척 상태를 확인하고
      • 이전의 테스트나 누락된 결점을 잡아내거나 미완성 또는 불완전한 부분에서 발생된 문제를 찾아내는 것이 중요하다.
      • 수락 테스트는 고객에 의해 작성된다.
      • 기능 테스트는 항상 100% 구현될 필요는 없으나 제품 출시 전에는 100% 수행 되어야 할것이다.
      • 기능 테스는 종종 매우 구체적인 내용들을 테스트 하기도 한다.
      • 아직은 통괄적인 수락 테스팅 툴은 나오지 않았고 Junit은 어떤 자바클래스에서도 수행될 수 있으나
      • 수락 테스팅 도구는 특정 애플리케이션 요구에 따라 작성되어야 한다.
      • HttpUnit을 이용하면 테스팅 API를 이용하여 웹 리소스에 대한 호출과 응답 값 조회를 프로그래밍 할 수 있도록 한다.
        **부하테스트 : JMeter, JUnitPerf등
        **인수테스트 : .

About Junit

기존에 TDD의 개념은 있었으나 도와주는 도구의 부재로 자바 개발자들은 주로 main() 에서 테스트 하는 방식을 주로 이용했을 것이다.
먼저 JUnit이 무엇이고 테스트란 무엇인지 알아보자.
테스트 코드는 작성시에 일반적으로 권장되는 몇가지 사항이 있다.

  • 이름짓기 규칙

    test 로 시작하는 메서드 이름으로 작성한다.
    즉, createMethod() 라는 메서드를 테스트 하려면 testCreateMethod()로 만드는 것이 좋다.
    그리고 eclipse의 junit 플러그인은 test로 시작된 메서드들을 찾아서 리플렉션을 통해서 테스트를 수행하게 한다.

  • 테스트 코드는 이런 작업들을 수행하도록 설정한다.

    테스트에 필요한 모든 조건과 상황을 준비 설정한다.
    테스트 대상이 되는 메서드를 호출한다.
    테스트 대상이 되는 메서드가 원하는 대로 동작한다는 것을 검증한다.
    실행이 끝나고 다른 코드에 영향이 없게 정리작업을 한다.

  1. JUnit 이란 독립된 테스트를 할 수 있도록 도와주는 framework이다.
  2. JUnit은 웹에서 무료로 다운로드할 수 있다. 설치는 classpath 환경 변수에 추가해주면 완료.
  • 우리는 이클립스 환경에서 사용할 것이므로 별다른 설치 없이 이클립스에서 제공하는 기능을 사용한다.
  • 이클립스의 Junit화면

    Failures 탭은 실패한 테스트의 목록을 나열한다.
    Hierarchy 탭은 실행된 모든 테스트의 전반적인 구조를 보여주는데 이것은 test suite(테스트 묶음) 을 실행할때 특히 유용하다.

  • JUnit의 단정메서드들 ( assert )

    *assertEquals - 같은지 비교
    *assertNull - null값을 리턴하는지 비교
    *assertNotNull - 인자로 넘겨받은 객체가 null인지 판정하고 반대인경우 실패로 처리한다.
    *assertSame - assertSame 은 expected 와 actual이 같은 객체를 참조하는지 판정하고 그렇지 않다면 실패로 처리한다.
    *assertNotSame - expected 와 actual이 서로 '다른' 객체를 참조하는지 판정하고, 만약 같은 객체를 참조한다면 실패로 처리한다.
    *assertTrue - boolean 조건이 참인지 판정한다. 만약 조건이 거짓이라면 실패로 처리한다.
    **assertTrue가 여기저기 들어가 있거나
    **테스트 코드라고 작성한 코드라고 주욱 작성해 놓고 마지막에 이 한줄을 넣어두는 코드는 의미가 없다.
    *fail - 테스트를 바로 실패 처리한다.
    *참고 : JUnit Quick Reference.pdf

  • 이 assert 메서드들은 테스트 대상이 되는 메서드의 검증을 위해 테스트 메서드 하나에는 assert 메서드가 여러개 들어간다.
    assert 메서드가 하나라도 실패하면 테스트 메서드는 중단되고, 나머지 assert 메서드들은 실행되지 않는다.
  • JUnit프레임워크
    1. import문으로 junit클래스들을 참조
    2. 테스트를 포함한 클래스는 모두 TestCase를 상속해야 한다.
    3. 테스트 클래스는 각 test.... 메서드를 정의한다.
    4. 모든 test..... 메서드는 Junit에 의해 자동으로 실행된다.
  • Junit 테스트 조합
    • test suite가 이것을 가능하게 하는데 모든 테스트 클래스는 suite라는 이름의 정적 메서드를 가질 수 있다.
    • public static Test suite();
    • 원하는 테스트 묶음을 반환하는 suite() 메서드를 작성하면 된다.
      ( 이 suite() 메서드가 없으면 JUnit은 모든 test.... 메서드를 자동으로 실행한다. )
  • 테스트별 준비 설정과 정리
    • setUp() 메서드는 각 test..... 메서드들이 실행되기전에 호출된다.
    • tearDown() 메서드는 각각의 테스트 메서드들이 실행되고 난 다음에 호출된다.

      테스트 클래스에 public void setUp() 메소드를 만들어주면 각 테스트 메소드가 실행되기 전에 먼저 setUp() 메소드가 실행된다.
      테스트 클래스에 public void tearDown() 메소드를 만들어주면 각 테스트 메소드가 종료할 때마다 tearDown() 메소드가 실행된다.

// 이 코드는 간단한 프레임워크및 실행순서를 보여준다. 
oneTimeSetup(){} //- 한번만 실행되는 스위트를 시작할 때의 준비설정코드와 끝날때의 정리코드
setUp(){} //- 메서드별로 테스트 메서드 이전에 실행되는 준비설정코드와, 이후에 실행되는 정리코드
testMethod(){}
tearDown(){}
setUp(){}
testMethod2(){}
tearDown(){}
oneTimeTearDown(){}

예를들어, 테스트마다 db연결 객체가 필요하다고 가정할때,
데이터베이스에 연결하고 접속을 종료하는 코드를 각 테스트 메서드에 일일이 넣을 필요 없이
setUp()과 tearDown() 메서드를 이용하여 해결하면 될것이다.

ex)

public Class TestDb extends TestCase()
{
private Connection dbConn;


protected void setUp()
{
dbConn = new Connection( "oracle", 1521, "scott", "tiger");
dbConn.connect();
}
	protected void tearDown()
{
dbConn.disconnect();
dbConn = null;
}
	public void testEmpAccess()
{
//dbConn 사용 어쩌고 저쩌고....
}
	public void testDeptAccess()
{
//dbConn 사용 어쩌고 저쩌고....
}
}
  • 이 간단한 예제에서는 setUp이 호출된 다음에 testEmpAccess() 가 호출이 되고 tearDown() 이 호출된다.
  • 그리고 setUp() 이 다시 호출되고 testEmpAccess() 가 실행되고 난 후에 tearDown()이 다시 호출된다.

대개는 이렇게 테스트별 준비 설정만으로 충분하지만
어떤 상황에서는 "전체" 테스트 스위트를 실행하기위해 어떤것을 설정하거나 정리해야 할 필요가 있다.
이런 경우 스위트별 준비 설정과 정리가 필요한데 이 설정은 조금 더 복잡하다.
필요한 테스트들의 스위트를 반들어서 TestSetup 객체 안에 감싸 넣어야 한다.

public static Test suite() 
{
TestSuite suite = new TestSuite();




// Only include short tests
suite.addTest(new TestClassTwo("testShortTest"));
suite.addTest(new TestClassTwo("testAnotherShortTest"));
	junit.extensions.TestSetup wrapper = junit.extensions.TestSetup(suite) 
{
// TestSetup 클래스의 setUp과 tearDown() 메서드를 재정의 한다.
protected void setUp() { oneTimeSetUp(); }
protected void tearDown() { oneTimeTearDown(); }
};
	return wrapper; 
}
public static void oneTimeSetUp() 
{
// 한번만 실행되는 초기화 코드가 여기에 들어간다.
tsp = new TSP();
tsp.loadCities("EasternSeaboard");
}
public static void oneTimeTearDown() 
{
// one-time cleanup code goes here...
tsp.releaseCities();
}
  • JUnit에서 제공하는 asssert 메서드만 사용하는 것보다 직접 사용자 정의 클래스를 만들어 상속하여 사용하는 것이 좋다.
  • JUnit과 예외
    1. 테스트에서 발생하는 예상된 예외
    2. 뭔가 크게 잘못 되어서 발생하는, 예상하지 못한 예외
      우리가 일반적으로 생각하는 것과는 달리 예외는 무언가 잘못되었다는 것을 알려주는 굉장히 유용한 도구다.
      가끔 테스트에서는 테스트 대상이 되는 메서드가 예외를 발생시키기를 '바라는' 경우도 있다.
      sortList()라는 메서드를 생각해보자. 이 메서드는 빈 목록을 받았을때 예외를 발생시켜야 한다.
       
public void testForException()
{
try
{
sortList(null);
fail("Should have trown an exception");
}
catch (RuntimeException e)
{
assertTrue(ture);
}
}

이 테스트 메서드의 경우 sortList를 테스트 할때 null이 넘어가면 예외를 발생시키는게 맞는 제어흐름이므로
catch절에 assertTrue(ture); 가 수행이 된다.
즉, 이는 나중에라도 코드를 잘못 해석할 가능성을 막아주는 강력한 문서화 기법이다.
다만 assertTrue(ture); 가 호출되지 않는다 하더라도 테스트가 실패하는 것은 아니라는 것은 명심하라.
그렇다면 예상하지 못한 예외들은?
사용자가 직접 처리하는 메서드를 구현할 수 있겠으나
메서드 선언부에 throws 절을 명시해 준다면 JUnit 프레임워크가 발생한 모든 예외를 잡아서 실패한 assert메서드를 출력하며
버그에 이르기까지 "전체" 호출 스택을 출력해 주므로 무엇때문인지 알아볼 때 많은 도움이 된다.

  • Java 의 JUnit은 test...로 시작하는 메서드가 자동으로 테스트 메서드로 인식되어 실행된다.

이것은 ,, 실제 테스트할 준비가 될때까지 메서드의 이름을 test로 시작하는 메서드가 아니라면 실행을 하지 않게 할수 있다는 것을 의미한다.
다만, 익숙해져선 안되는 것은 바로 테스트가 실패하는데도 이를 무시하는 습관이다.

  • JUnit의 테스트 골격 - JUnit테스트 사용에서 정말 필요한것은
    [{ImportantPlugin
  • junit.framework.* 를 반영하기위한 import 문
  • 테스트 클래스가 TestCase를 상속하게 하는 extends 문
  • supert(String)를 호출해주는 생성자
    많은 ide가 최소한 이만큼의 기능은 제공한다.

! 무엇을 테스트 할것인가?

  • 결과가 옳은가? - 당연한 말이다.

    또하나, 많은 양의 테스트 데이타가 필요한 테스트를 한다면, 단위 테스트에서 읽어들이는 별도의 데이타 파일에 테스트 값이나 결과를 넣는 것을 고려하는 것이 좋다.

  • 경계조건 - 대부분의 버그는 보통 '경계'에 서식한다.

    형식일치, 순서, 범위, 참조, 존재성, 개체수, 시간 등을 테스트한다.

    • 형식일치: 이메일, 전화번호, 주민번호등의 간단한 형식부터 레코드에 여러개의 레코드가 연결된 등의 형식 검증
    • 순서 : 정렬등의 루틴 등의 검증
    • 범위 : 애플리케이션 영역의 제약에 따른 범위
    • 물리적인 데이터 구조에 따라 제한되는 범위 - 배열이나 스택등의 인덱스 범위등
    • 참조
      **메서드가 자기 영역을 벗어난 어떤 것들을 참조하는가?
      **외부 의존성이 있는가?
      **클래스가 가져야 하는 상태는?
      **그 메서드가 제대로 동작하려면 그 밖에 어떤 조건을 가져야 하는가?

    예를 들면, 해당 메서드가 동작하기 위한 사전 조건( pre condition ) 이나 사후 조건( post condition ) 은
    어떤 상태여야 하는가? 등의 것들에 대한 것들인데.
    스택의 pop() 메서드처럼 비어있지 않은 스택을 필요로 한다던지
    고객의 거래 내용을 보여주는 어플리케이션에서는 고객의 로그인이 선행 되는 것을 필요로 한다던지
    dbConnection을 끊기 위해서는 먼저 dbConnetion 이 먼저 맺어져 있어야 한다던지 하는 것을

    • 존재성 : 주어진 것이 존재하는가.
      즉, null 이거나 비었거나 0이라면 그 메서드에 어떤 일이 일어날 것인가?
      메서드가 無를 확실히 이겨낼 수 있게 해야 한다.
    • 개체수
      테스트는 경계조건 0,1,n(한개 이상이면 n으로 논리적으로 취급된다.) 에 집중하게 된다.
      n은 업무상 필요에 따라 변하게 될 것이다.
    • 시간
      상대시간(시간적 순서)
      절대시간 ( 경과한 총 계산 시간)
      동시성 문제
  • 역관계 확인 - 논리적 inverse를 적용하여 검증해 볼 수 있다.
  • 다른 수단을 이용한 교차확인
  • 에러조건을 강제로 만들어내기
  • 성능특성

모의객체 사용하기 - 단위 테스트의 목표는 한번에 메서드 하나를 테스트 하는 것이다. 하지만, 테스트 하기가 어려운 상황이라면?

  1. 간단한 스텁 - 설계를 테스트 하는 동안 코드에서 임시로 만들어 사용한다.
    예)
    public long getTime()
    {
    if( debug )
    {
    return debug_cur_time;
    }
    else
    {
    return System.currentTimeMillis();
    }
    }

    하지만 우리에게 필요한것은 똑같은 일을 해내면서 더 깔끔하고, 더 객체지향 적인 방법이다.

  2. 모의 객체

    진짜 객체가 비결정적인 동작을 한다.( 예상할 수 없는 결과를 만들어 낸다.)
    진짜 객체를 준비 설정하기 어렵다.
    진짜 객체가 직접 유발시키기 어려운 동작을 한다.
    진짜 객체가 느리다.
    진짜 객체가 사용자 인터페이스를 가지거나, 사용자 인터페이스 자체다.
    테스트가 진짜 객체에게 그것이 어떻게 사용되었는지 물어보아야 한다.
    진짜 객체가 아직 존재하지 않는다.( 다른팀이나 새로운 하드웨어 시스템과 함께 일할 때 흔한 문제다.)

    모의 객체를 사용하기 위한 세단계
    *객체를 설명하기 위해 인터페이스를 사용한다.
    *제품 코드에 맞게 그 인터페이스를 구현한다.
    *테스트에 쓸 모의 객체의 인터페이스를 구현한다.

참고자료
http://sourceforge.net/projects/mockobjects
http://www.easymock.org

모의 객체의 사용법의 핵심은 각자가 흉내내는 뭔가에 의존하는 객체를 테스트 하기 위한것이다.

  • 좋은 테스트의 특징
  1. 자동적 : 테스트를 실행하는 경우와 결과를 확인하는 경우를 모두 의미하는 것.
  2. 철저함 - 문제가 될 수 있는 것은 모두 테스트한다.
  3. 반복가능
  4. 독립적
  5. 다른 테스트로부터도 독립적, 환경, 다른 개발자 로부터도 독립적
  6. 전문적 : 전문적 표준을 유지하면서 작성되어야 한다.

    테스트를 테스트 하기위한 방법의 일환으로
    일부러 버그를 집어넣어 테스트를 검증하기도 한다.
    그리고 코드를 고쳐서 테스트를 통과하게 하면 된다.

  • 프로젝트에서 코드의 구조화의 방법
    • 같은 디렉터리
    • 가장 쉬운 방법
    • 단점은 제품 코드와 테스트 코드가 같이 섞여 어질러져 있다는 것
    • 하위 디렉토리
    • 이방법은 테스트 코드를 적어도 제품 코드와 똑같은 디렉터리에 있지는 않게 떨어뜨려 놓을 수 있다는 이점이 있다.
    • test라는 하위의 패키지에 위치하게 되는 테스트 코드를 위해 가시성이 protected 같은 경우, 단지 테스트만을 위한 이 제품코드를 상속바받아서 정보를 노출하는 하위 클래스를 작성해야 한다.
    • 병렬트리
    • test 클래스를 제품 코드와 같은 패키지 안에, 그러나 다른 소스 코드 트리상의 위치에 넣는 것이다.즉, 컴파일러의 classpath안에 두개의 서로 다른 위치를 위치시켜서 인식을 시키는 것이다.
  • 팀작업에서 소스 공유시 테스트 예절은 말 하지 않아도 중요하다는 것에 모두 동의 하실 것이다.

    불완전한 코드(의존성 있는 코드가 체크인 되지 않은.)
    컴파일되지 않은 코드
    컴파일 되긴 하지만, 다른 코드를 망가뜨려서 컴파일 되지 않게 만드는 코드
    대응하는 단위 테스트가 없는 코드
    단위 테스트가 실패하는 코드
    자신의 테스트는 통과하지만, 시스템의 다른 테스트를 실패하게 만드는 코드

  • 테스트빈도의 종류

    새 메서드를 작성할 때마다: 지역단위 테스트들을 컴파일 하고 실행한다.
    버그를 고칠 때마다 : 버그를 드러내는 코드를 실행한다.버그를 고치고 단위테스트를 다시 실행한다.
    성공적으로 컴파일할 때마다 : 지역 단위 테스트들을 실행한다.
    버전 관리 시스템에 체크인할 때마다 : 모든 모듈 또는 시스템의 단위테스트들을 실행한다.
    끊임없이 : 따로 배정된 특정 컴퓨터가 자동으로 하루종일( 주기적으로 , 또는 버전 관리 시스템에 체크인 할때마다)처음부터 전체 빌드와 테스트를 수행하고 있어야 한다.

    Using JUnit Simple Demo

    먼저 테스트 해 볼 것은 간단한 예제로 주어진 배열중 가장 큰수를 리턴하는 메서드를 작성하는 테스트를 작성해 보기로 한다.
    그리고 TestSuite의 사용법을 위해 TestCase를 더 작성후 TestSuite를 작성해본다.

Make TestCases













Make TestSuite






논외

*TDD는 다음과 같은 순서로 진행을 하면 된다. 이 순서는 켄트벡이 제시한 순서이다.
1. Quickly add a test(테스트 프로그램을 작성한다.)
2. Run all tests and see the new one fail
(모든 테스트 프로그램을 수행시키고 테스트에 실패한 부분을 확인한다.)
3. Make a little change(소스를 추가하거나 변경한다.)
4. Run all tests and see them all succeed
(다시 모든 테스트를 수행시키고 모두 테스트를 통과했는데 확인한다.)
5. Refactor to remove duplication(중복을 제거하기 위해 Refactoring 한다.)


*이클립스에서 TestCase자동생성




 

[펌] JUnit 2

프로그래밍/Library 2007. 11. 28. 09:33 Posted by galad

http://blog.naver.com/galad/140035831352

출처 블로그 > もも***
원본 http://blog.naver.com/dmsl01/80035693427

JUnit 


 

테스트 클래스 작성
JUnit Test 클래스는 junit.framework.TestCase 를 상속받고,

public void test*() 형태의 테스트 메소드를 작성한다.

 

JUnit 테스트의 골격
1. junit.framework.* 을 코드에 반영하기 위한 import 문
2. 테스트 클래스가 TestCase를 상속하는 extends 문(되도록 TestCase를 상속하는 다른 클래스를 만들고, 그 클래스로 다시 상속 받아 테스트 클래스를 만드는 것이 좋다)
3. super(string)을 호출해 주는 생성자


테스트 수행
 * 텍스트 : junit.textui.TestRunner TestClass
 * AWT : junit.awtui.TestRunner TestClass
 * SWING : junit.swingui.TestRunner TestClass

 

테스트 수행 메소드 부르기
public static void main(String[] args) {
    junit.swingui.TestRunner.run(AllTest.class);
}


Assertions
각 메소드는 맨 처음 인자로 문자열 설명을 가질 수 있다.

assertEquals(primitive expected, primitive actual);
assertEquals(Object exprected, Object actual);
assertSame(Object exptected, Object actual); // 두 객체가 같은가?
assertNotSame(Object exptected, Object actual);
assertNull(Object object); // 객체가 NULL인가?
assertNotNull(Object object);
assertTrue(boolean condition);
assertFalse(boolean condition);

fail(String str); : 무조건 실패


테스트 클래스의 값 초기화
테스트 클래스에 public void setUp() 메소드를 만들어주면 각 테스트 메소드가 실행되기 전에 먼저 setUp() 메소드가 실행된다.

테스트 클래스에 public void tearDown() 메소드를 만들어주면 각 테스트 메소드가 종료할 때마다 tearDown() 메소드가 실행된다.

suite()
테스트할 메소드를 명시적으로 지정하고 싶을 때 테스트 클래스에 public static Test suite() 메소드를 만든다.
public static Test suite() {
    TestSuite = new TestSuite();
    suite.addTest(new TestClass("testMethod1")); // 테스트할 메소드 이름
    suite.addTest(new TestClass("testMethod2"));

    return suite;
}


JUnit과 ANT

<junit printsummary="true" haltonfailure="no">
        <classpath>
                <pathelement path="${classes.dir}"/>
        </classpath>
        <test name="helloproject.junit1.DayCounterTest"/>
</junit>

 

haltonfailover="yes" 이면 테스트가 하나라도 실패하면 거기서 테스트를
중지해버린다.

여러 테스트를 수행하려면

<junit printsummary="true" haltonfailure="no">
        <classpath>
                <pathelement path="${classes.dir}"/>
        </classpath>
        <formatter type="xml"> <!-- 결과를 XML로 내보냄 -->
        <batchtest todir="${test.dir}"> <!-- XML결과가 저장될 Directory -->
                <fileset dir="${classes.dir}">
                        <include name="**/*Test*.class"/>
                </fileset>
        </batchset>
</junit>

 

테스트 결과 XML을 이용해 HTML로 결과 보고서 만들기 - Xalan 2 필요

<junitreport todir="${test.dir}">
        <fileset dir="${test.dir}">
                <include name="TEST**.xml"/>
        </fileset>
        <report format="frames" todir="${test.dir}/html"/>
</junitreport>

 

[펌] eclipse short cuts

프로그래밍/Library 2007. 11. 28. 09:32 Posted by galad
페이지 이동 CTRL + E



VIEW 들의 이동. (Package Explorer, source, Outlines...) : CTRL+F7



Perspective 같은 이동(?)  : CTRL+F8







===== 실행 =====

1. Ctrl + F11 : 바로 전에 실행했던 클래스 실행







===== 소스 네비게이션 =====

1. Ctrl + 마우스커서(혹은 F3) : 클래스나 메소드 혹은 멤버를 상세하게 검색하고자 할때

2. Alt + ->, Alt + <- : 이후, 이전

3. Ctrl + o : 해당 소스의 메소드 리스트를 확인하려 할때

4. F4 : 클래스명을 선택하고 누르면 해당 클래스의 Hierarchy 를 볼 수 있다.



===== 문자열 찾기 =====

1. Ctrl + k : 찾고자 하는 문자열을 블럭으로 설정한 후 키를 누른다.

2. Ctrl + Shift + k : 역으로 찾고자 하는 문자열을 찾아감.

3. Ctrl + j : 입력하면서 찾을 수 있음.

4. Ctrl + Shift + j : 입력하면서 거꾸로 찾아갈 수 있음.

5. Ctrl + f : 기본적으로 찾기







===== 소스 편집 =====

1. Ctrl + Space : 입력 보조장치(Content Assistance) 강제 호출 => 입력하는 도중엔 언제라도 강제 호출 가능하다.

2. F2 : 컴파일 에러의 빨간줄에 커서를 갖져다가 이 키를 누르면 에러의 원인에 대한 힌트를 제공한다.

3. Ctrl + l : 원하는 소스 라인으로 이동

  로컬 히스토리 기능을 이용하면 이전에 편집했던 내용으로 변환이 가능하다.

4. Ctrl + Shift + Space : 메소드의 가로안에 커서를 놓고 이 키를 누르면 파라미터 타입 힌트를 볼 수 있다.



5. 한줄 삭제 CTRL + D



6. 파일 닫기 : CTRL+W



7. 들여쓰기 자동 수정. (3.0 NEW) : CTRL+I



8. 블록 주석(/*..*/) 추가.(3.0 NEW): CTRL+SHIFT+/



  8.1 Ctrl + / 해주면 여러줄이 한꺼번에 주석처리됨. 주석 해제하려면 반대로 하면 됨.

9. 위(아래)줄과 바꾸기 : ALT+UP(DOWN)



10. 블록 선택하기.  : ALT+SHIFT+방향키



11. 메소드의 파라메터 목록 보기. : CTRL+SHIFT+SPACE

12. 자동으로 import 하기 : CTRL+SHIFT+O



13. 열린 파일 모두 닫기 : CTRL + SHIFT + F4



14. 블록 주석 제거 : CTRL+SHIFT+\



15. 전체화면 토글 : CTRL+M



16. 한줄(블럭) 복사 : Ctrl + Alt + 위(아래)



17. 다음 annotation(에러, 워닝, 북마크 가능)으로 점프 : Ctrl + , or .



18. 퀵 픽스 : Ctrl + 1

19. 메소드 정의부로 이동 : F3

20. 하이어라키 팦업 창 띄우기(인터페이스 구현 클래스간 이동시 편리) : Ctrl + T



21. 메소드나 필드 이동하기 CTRL + O

22. ULTRAEDIT나 EDITPLUS 의 CTRL+TAB 과 같은 기능. : CTRL+F6







===== 템플릿 사용 =====

1. sysout 입력한 후 Ctrl + Space 하면 System.out.println(); 으로 바뀐다.

2. try 입력한 후 Ctrl + Space 하면 try-catch 문이 완성된다.

3. for 입력한 후 Ctrl + Space 하면 여러가지 for 문을 완성할 수 있다.

4. 템플릿을 수정하거나 추가하려면 환경설정/자바/편집기/템플리트 에서 할 수 있다.







===== 메소드 쉽게 생성하기 =====

1. 클래스의 멤버를 일단 먼저 생성한다.

2. override 메소드를 구현하려면 : 소스->메소드대체/구현 에서 해당 메소드를 체크한다.

3. 기타 클래스의 멤버가 클래스의 오브젝트라면 : 소스->위임메소드 생성에서 메소드를 선택한다.







===== organize import =====

1. 자바파일을 여러개 선택한 후 소스 -> 가져오기 체계화 해주면 모두 적용된다.







===== 소스 코드 형식 및 공통 주석 설정 =====

1. 환경설정 -> 자바 -> 코드 스타일 -> 코드 포멧터 -> 가져오기 -> 프로파일.xml 을 불러다가 쓰면 된다.

2. 또한 다수의 자바파일에 프로파일을 적용하려면 패키지 탐색기에서 패키지를 선택한 후 소스 -> 형식화를 선택하면 된다.

3. 환경설정 -> 자바 -> 코드 스타일 -> 코드 템플리트 -> 가져오기 -> 템플리트.xml 을 불러다가 쓰면 된다.







===== 에디터 변환 =====

1. 에디터가 여러 파일을 열어서 작업중일때 Ctrl + F6 키를 누르면 여러파일명이 나오고 F6키를 계속 누르면 아래로

2. Ctrl + Shift + F6 키를 누르면 위로 커서가 움직인다.

3. Ctrl + F7 : 뷰간 전환

4. Ctrl + F8 : 퍼스펙티브간 전환

5. F12 : 에디터로 포커스 위치







===== JAVA Doc 생성 =====

1. 프로젝트 -> Javadoc 생성







===== 내보내기 =====

해당 프로젝트를 zip 행태로 압축해서 보관할 수 있다.







===== 자바 찾아보기 perspective =====

해당 프로젝트를 보다 편리하게 한번 둘러보는데 좋다.







===== 스크랩북 =====

1. 스크랩북을 이용하면 자바파일을 만들어 테스트 해보지 않고도 간단하게 테스트 해 볼 수 있다.

2. 패키지 탐색기에서 신규 -> 기타 -> 자바 -> 자바 실행/디버그 -> 스크랩북 페이지 선택







===== 디버그 =====

1. F5(Step Into) : 현재의 명령문이 호출되는 메소드 속으로 진행하여, 그 첫 문장을 실행하기 전에 멈춘다.

  하지만 자바 라이브러리 클래스 수준까지 들어가므로 단계필터 사용을 체크(Shift+F5)를 하면 필터를 설정한 클래스에 대하서는 Step Over 기능과 같은 기능을 수행한다.

2. F6(Step Over) : 현재의 명령문을 실행하고 다음 명령문 직전에 다시 멈춘다.

3. F7(Step Return) : 현재의 메소드에서 리턴한 직후에 다시 멈춘다.

4. F8(Resume) : 멈추어 있던 쓰레드를 다시 계속 실행한다.

5. Display view(표시) : 창 -> 보기표시 -> 표시 선택하여 소스상에서 필요한 부분을 선택해서
실행시켜 볼 수 있다.  한 순간의 값만 필요할 때 볼 수 있는 반면에 아래놈은 계속적으로 값이 변하는 것을 확인 할 수 있다.

6. Expression view(표현식) : 복잡한 식 혹은 객체를 디버깅 하면서 계속 볼 수있는 창이다.

  마우스 오른버튼 -> 감시 표시식 추가 선택한 후 사용한다.

  환경설정 -> 자바 -> 디버그 -> 세부사항 포멧터 선택 후 보기 편한 식으로 편집하면



  Expression View 에서 결과를  실시간으로 확인 할 수 있다.

7. 디버깅 하면서 소스를 수정하고 프로그램을 다시 시작할 필요 없이 계속 디버깅을 진행 할 수 있다.

  다만 메소드를 추가하거나 필드를 추가하면 프로그램을 다시 시작해야 한다.

8. Drop to Frame(프레임에 놓기) 는 정말 모르겠다.

9. 디버깅 작업을 할때 해당 라이브러리의 소스코드를 첨부하지 않으면 진행상황을 볼 수 없을 경우

  해당 라이브러리에 소스코드를 첨부할 수 있다. 해당 프로젝트 -> 특성 -> Java 빌드경로 -> 라이브러리 -> 소스참조

  편집 버튼을 눌러서 첨부 한다.







===== 도움말 =====

"JDT 팁과 요령"이라고 치면 여러가지 흥미로운 팁이 나온다.







===== Refactoring =====

1. Pull Down : 수퍼클래스의 멤버나 메소드를 하위 클래스로 내리는 행위

2. Push Up : 하위 클래스의 멤버나 메소드를 상위 클래스로 올리는 행위







===== CVS =====

1. CVS 서버로는 윈도우에 CVSNT 최신버젼을 설치하고, [컴퓨터 관리]를 통해서 사용자를 추가한다.

- CVSNT 를 설치할때 윈도우의 경우 Repositories 를 추가할때 접두어를 사용하지 말고 디렉토리 풀이름(d:/cvs) 이런식

  으로 등록해야 Eclipse 와 에러없이 동기화가 잘 된다.

2. Eclipse 에 CVS 저장소 perspective 에서 새로운 저장소를 등록한 후 HEAD 에서 해당 프로젝트를 체크아웃하면

  자바 perspective 에 등록되는 것을 확인할 수 있다.
제목 : [질문]eclipse 에서 run 실행시 jvm 에 대한 세팅은 어디서 하나요?
글쓴이: 손님(guest) 2006/07/25 14:54:16 조회수:636 줄수:13
eclipse 에서 대용량의 파일(xml파일) 을 읽어 들여서 처리하는 프로그램을 개발한 후에 테스트를 하려고
이클립스의 Run As Java application 을 클릭하여 실행을 하니 OutOfMemory 에러가 발생했습니다.

이클립스에서 Run 을 하면 새로운 JVM 이 따로 떠서 실행을 하는 것 같던데 그 거에 대해서
초기 메모리 setting 을 하는 방법이 없는지 아시는 분은 답변부탁드립니다.

-Xms -Xmx option 을 설정하려고 하는데 찾아봐도 이클립스 자체를 실행시킬때 옵션 주는 거 밖에는
안나오더군요..

질문을 다시 정리하면 이클립스에서 Run을 했을때 어플리케이션을 실행시키기 위해 새로 실행되는 
JVM 에 대한 옵션을 주는 법을 알려주시면 감사하겠습니다.

제목 : Re: 제기억엔.
글쓴이: 깨끗한손(guest) 2006/07/31 17:12:34 조회수:339 줄수:9
이클립스에서 Run 을 하면 조그만 실행 윈도우가 열립니다.
메인 클래스 이름이 적혀있고. 아래에 Run, close 버튼이 있습니다.(^^)
여러가지 옵션을 줄수있게 탭들이 있는데 이곳에서 
아규먼트, jre , 클래스패스, 시스템 변수등을 다 세팅할 수 있습니다.

아규먼트 탭에. VM 아규먼트로 있을듯 합니다. 
(지금 이클립스가 안 깔린 컴퓨터 라서 ㅡ.ㅡ)
제목 : Re: 이렇게 하세요~
글쓴이: 손님(guest) 2006/08/03 09:54:36 조회수:334 줄수:6
실행할 화일의 등록정보를 여시고
아래처럼 셋팅하시면 됩니다.

D:\eclipse\eclipse.exe -vm C:\Progra~1\Java\j2sdk1.4.2_05\bin\javaw.exe -vmargs -Xmx256m

제목 : Re:Re:제기억엔.
글쓴이: 손님(guest) 2006/08/04 14:00:18 조회수:305 줄수:18
우선 답변 감사드립니다.

>이클립스에서 Run 을 하면 조그만 실행 윈도우가 열립니다.
>메인 클래스 이름이 적혀있고. 아래에 Run, close 버튼이 있습니다.(^^)
>여러가지 옵션을 줄수있게 탭들이 있는데 이곳에서 
>아규먼트, jre , 클래스패스, 시스템 변수등을 다 세팅할 수 있습니다.

>아규먼트 탭에. VM 아규먼트로 있을듯 합니다. 
>(지금 이클립스가 안 깔린 컴퓨터 라서 ㅡ.ㅡ)


거기는 찾아봤는데 JRE 탭에 jvm 의 옵션을 주는 란이 없는 것 같은데요.. 


그리고 바로 위에 이렇게하세요~ 라고 써주신 분이 알려주신 거에서 vm 옵션을 줄수 있다는 건 알겠는데 
그 vm 에 대해서 Xmx 옵션은 어떻게 줘야 하죠?
맨 뒤에 있는 -Xmx256m 은 C:\Progra~1\Java\j2sdk1.4.2_05\bin\javaw.exe 에 적용되는 옵션이 아니라
eclipse.exe 에 적용되는 옵션이 아닌지요...
제목 : Re: eclipse.ini 파일을 수정하시면 됩니다.
글쓴이: 손님(guest) 2006/11/20 15:59:38 조회수:248 줄수:13
eclipse 폴더에 보시면 
eclipse.ini 구성설정 파일이 있습니다. 

-vmargs-Xms40m-Xmx256m

이부분을 원하는 환경으로 설정해주시면 됩니다.

-vmargs-Xms40m(최소값)-Xmx256m(최대값)

'프로그래밍 > Library' 카테고리의 다른 글

[펌] JUnit 2  (0) 2007.11.28
[펌] eclipse short cuts  (0) 2007.11.28
Tomcat 다운현상  (0) 2007.11.28
james mail server  (0) 2007.11.28
[펌] james mail server setting  (0) 2007.11.28

Tomcat 다운현상

프로그래밍/Library 2007. 11. 28. 09:31 Posted by galad
제목 : Tomcat 다운현상
글쓴이: 손님(guest) 2005/12/21 14:20:39 조회수:1098 줄수:53
프로젝트 마무리 단계로 고객측 서버에서 테스트를 하고 있는데, 잘되다가 멈춰버리면서 접근이 안되네요.
좀 기다렸다가 다시 접속하거나 또는 톰캣을 내렸다가 올리면 되는데, 근본적으로 원인을
찾아야 할것 같습니다.

우선 톰캣로그에는 항상 저런형태는 아니지만, 비슷한 에러가 자주 발생을 하는듯
하구요, 톰캣 실행은  -server -Xms128m -Xmx256m -verbosegc 옵션을 주고 있고,
서버환경은

HP-UX B.11.11
Tomcat 5.5.9
Java 1.5.0.02

입니다. 아 그리고, 오늘 다운됐을때 로그를 보니까 계속 Full GC가 반복해서 일어나고 있더라구요.



2005. 12. 21 오전 9:45:07 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run
심각: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.jk.common.SocketConnection@aabe60, terminating thread
2005. 12. 21 오전 9:45:07 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run
심각: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.jk.common.SocketConnection@7e6732, terminating thread
2005. 12. 21 오전 9:45:07 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run
심각: Caught exception (java.lang.OutOfMemoryError: unable to create new native thread) executing org.apache.jk.common.SocketAcceptor@221b8b, terminating thread
2005. 12. 21 오전 9:45:21 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run
심각: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.jk.common.SocketConnection@85a60, terminating thread
2005. 12. 21 오전 9:46:16 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 21 오전 9:46:25 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:50:41 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:50:54 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:51:59 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 21 오전 9:53:36 org.apache.catalina.connector.CoyoteAdapter service
심각: An exception or error occurred in the container during the request processing
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:54:16 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:54:19 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:54:29 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run
심각: Caught exception (java.lang.OutOfMemoryError: Java heap space) executing org.apache.jk.common.SocketConnection@d9624, terminating thread
2005. 12. 21 오전 9:54:57 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
java.lang.OutOfMemoryError: Java heap space
2005. 12. 21 오전 9:58:50 org.apache.jasper.compiler.JspReader pushFile
심각: Exception parsing file 
제목 : Re: verbosegc 로그를 올려봐요.
글쓴이: 이원영(javaservice) 2005/12/21 19:59:09 조회수:447 줄수:6
verbosegc 로그를 올려봐요.

자바서비스넷 이원영
Phone: 010-6239-6498
E-mail: NOSPAM_lwy@javaservice.com
MSN: NOSPAM_javaservice@hanmail.net
제목 : Re: GC 로그 입니다.
글쓴이: 손님(guest) 2005/12/22 10:31:31 조회수:502 줄수:135
좀더 자세하게 출력해보기 위해서 옵션을 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC 로
줘서 다시 실행시켜 보고 있는 중입니다. 

오늘 outofmemory 발생 이전의 일부분과 발생후의 로그를 올려봅니다.


{Heap before GC invocations=1454:
Heap
 PSYoungGen      total 141120K, used 126050K [6e000000, 78aa0000, 78aa0000)
  eden space 109696K, 99% used [6e000000,74b1dd10,74b20000)
  from space 31424K, 52% used [76b60000,77b5ab68,78a10000)
  to   space 32512K, 0% used [74b20000,74b20000,76ae0000)
 PSOldGen        total 349568K, used 128281K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 36% used [58800000,60546648,6dd60000)
 PSPermGen       total 31744K, used 29458K [54800000, 56700000, 58800000)
  object space 31744K, 92% used [54800000,564c4978,56700000)
56943.386: [GC [PSYoungGen: 126050K->22406K(132160K)] 254331K->160687K(481728K), 1.2878866 secs]
 Heap after GC invocations=1454:
Heap
 PSYoungGen      total 132160K, used 22406K [6e000000, 78aa0000, 78aa0000)
  eden space 109696K, 0% used [6e000000,6e000000,74b20000)
  from space 22464K, 99% used [74b20000,76101850,76110000)
  to   space 35456K, 0% used [76800000,76800000,78aa0000)
 PSOldGen        total 349568K, used 138281K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 39% used [58800000,60f0a648,6dd60000)
 PSPermGen       total 31744K, used 29458K [54800000, 56700000, 58800000)
  object space 31744K, 92% used [54800000,564c4978,56700000)
} 
 {Heap before GC invocations=1455:
Heap
 PSYoungGen      total 132160K, used 132089K [6e000000, 78aa0000, 78aa0000)
  eden space 109696K, 99% used [6e000000,74b1cc68,74b20000)
  from space 22464K, 99% used [74b20000,76101850,76110000)
  to   space 35456K, 0% used [76800000,76800000,78aa0000)
 PSOldGen        total 349568K, used 138281K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 39% used [58800000,60f0a648,6dd60000)
 PSPermGen       total 31744K, used 29492K [54800000, 56700000, 58800000)
  object space 31744K, 92% used [54800000,564cd1e0,56700000)
57028.604: [GC [PSYoungGen: 132089K->2203K(140672K)] 270370K->141300K(490240K), 0.1712235 secs]
 Heap after GC invocations=1455:
Heap
 PSYoungGen      total 140672K, used 2203K [6e000000, 78aa0000, 78aa0000)
  eden space 105216K, 0% used [6e000000,6e000000,746c0000)
  from space 35456K, 6% used [76800000,76a26dc0,78aa0000)
  to   space 34048K, 0% used [746c0000,746c0000,76800000)
 PSOldGen        total 349568K, used 139096K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 39% used [58800000,60fd6258,6dd60000)
 PSPermGen       total 31744K, used 29492K [54800000, 56700000, 58800000)
  object space 31744K, 92% used [54800000,564cd1e0,56700000)
}  {Heap before GC invocations=1456:
Heap
 PSYoungGen      total 140672K, used 107419K [6e000000, 78aa0000, 78aa0000)
  eden space 105216K, 100% used [6e000000,746c0000,746c0000)
  from space 35456K, 6% used [76800000,76a26dc0,78aa0000)
  to   space 34048K, 0% used [746c0000,746c0000,76800000)
 PSOldGen        total 349568K, used 139096K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 39% used [58800000,60fd6258,6dd60000)
 PSPermGen       total 31744K, used 29531K [54800000, 56700000, 58800000)
  object space 31744K, 93% used [54800000,564d6c18,56700000)
57030.592: [GC [PSYoungGen: 107419K->33204K(138432K)] 246516K->173516K(488000K), 2.3490715 secs]
 Heap after GC invocations=1456:
Heap
 PSYoungGen      total 138432K, used 33204K [6e000000, 78aa0000, 78aa0000)
  eden space 105216K, 0% used [6e000000,6e000000,746c0000)
  from space 33216K, 99% used [746c0000,7672d248,76730000)
  to   space 36288K, 0% used [76730000,76730000,78aa0000)
 PSOldGen        total 349568K, used 140312K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 40% used [58800000,61106130,6dd60000)
 PSPermGen       total 31744K, used 29531K [54800000, 56700000, 58800000)
  object space 31744K, 93% used [54800000,564d6c18,56700000)
}  {Heap before GC invocations=1457:
Heap
 PSYoungGen      total 138432K, used 138397K [6e000000, 78aa0000, 78aa0000)
  eden space 105216K, 99% used [6e000000,746ba2a0,746c0000)
  from space 33216K, 99% used [746c0000,7672d248,76730000)
  to   space 36288K, 0% used [76730000,76730000,78aa0000)
 PSOldGen        total 349568K, used 140312K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 40% used [58800000,61106130,6dd60000)
 PSPermGen       total 31744K, used 29531K [54800000, 56700000, 58800000)
  object space 31744K, 93% used [54800000,564d6c18,56700000)
57035.835: [GC [PSYoungGen: 138397K->16265K(131776K)] 278709K->179145K(481344K), 0.9527750 secs]
 Heap after GC invocations=1457:
Heap
 PSYoungGen      total 131776K, used 16265K [6e000000, 78aa0000, 78aa0000)
  eden space 95488K, 0% used [6e000000,6e000000,73d40000)
  from space 36288K, 44% used [76730000,77712580,78aa0000)
  to   space 39616K, 0% used [73d40000,73d40000,763f0000)
 PSOldGen        total 349568K, used 162880K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 46% used [58800000,62710130,6dd60000)
 PSPermGen       total 31744K, used 29531K [54800000, 56700000, 58800000)
  object space 31744K, 93% used [54800000,564d6c18,56700000)
} 2005. 12. 22 오전 10:11:52 org.apache.tomcat.util.threads.ThreadPool$ControlRunnable run
심각: Caught exception (java.lang.OutOfMemoryError: unable to create new native thread) executing org.apache.jk.common.SocketAcceptor@b7299b, terminating thread
2005. 12. 22 오전 10:11:52 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:52 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:53 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:53 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:53 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:53 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:53 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:54 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:54 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
2005. 12. 22 오전 10:11:54 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2
 {Heap before GC invocations=1458:
Heap
 PSYoungGen      total 131776K, used 111753K [6e000000, 78aa0000, 78aa0000)
  eden space 95488K, 100% used [6e000000,73d40000,73d40000)
  from space 36288K, 44% used [76730000,77712580,78aa0000)
  to   space 39616K, 0% used [73d40000,73d40000,763f0000)
 PSOldGen        total 349568K, used 162880K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 46% used [58800000,62710130,6dd60000)
 PSPermGen       total 31744K, used 29578K [54800000, 56700000, 58800000)
  object space 31744K, 93% used [54800000,564e2810,56700000)
57041.924: [GC [PSYoungGen: 111753K->1897K(135104K)] 274633K->165667K(484672K), 0.0574536 secs]
 Heap after GC invocations=1458:
Heap
 PSYoungGen      total 135104K, used 1897K [6e000000, 78aa0000, 78aa0000)
  eden space 95488K, 0% used [6e000000,6e000000,73d40000)
  from space 39616K, 4% used [73d40000,73f1a5c0,763f0000)
  to   space 38464K, 0% used [76510000,76510000,78aa0000)
 PSOldGen        total 349568K, used 163770K [58800000, 6dd60000, 6dd60000)
  object space 349568K, 46% used [58800000,627eea38,6dd60000)
 PSPermGen       total 31744K, used 29578K [54800000, 56700000, 58800000)
  object space 31744K, 93% used [54800000,564e2810,56700000)
} 
제목 : Re: 오전에 발생한 현상은...
글쓴이: 이원영(javaservice) 2005/12/22 15:16:35 조회수:380 줄수:16
오전에 발생한 현상은 heap 메모리와는 무관하게 HP-UX의 커널파라메터인 max_thread_proc 값에
영향은 받은 것 같습니다. default가 64이기 때문에 하나의 process가 64개 이상의 thread를 
생성하지 못합니다.

보시는 방법은
kmtune | grep max_thread_proc
하시면 될 겁니다.

NOTE: 그러나, 맨 처음 올려주신 OutOfMemoryError는 heap 힙메모리와 관련되어 있는 것으로
추정되며, 오전 상황과는 다른 이슈로 보입니다. 해당 현상이 일어났을 때, 앞서처럼 verbosegc
결과를 올려주시면 가이드를 드리겠습니다.

자바서비스넷 이원영
Phone: 010-6239-6498
E-mail: NOSPAM_lwy@javaservice.com
MSN: NOSPAM_javaservice@hanmail.net
제목 : Re: 그렇다면 thread 수가 일반적인것인지요?
글쓴이: 손님(guest) 2005/12/22 15:48:14 조회수:343 줄수:12
그렇군요. heap 메모리에 대해서는 프로그램적인 누수가 있을수도 있지만, 아직 정확하게
파악할수 있지는 못해서 1차적으로 java option에서 메모리 옵션을 늘려서 지켜보고 있는
상황입니다.

말씀하신것처럼 thread의 수가 64개로 잡혀있네요.

max_thread_proc            64  -  64

그런데 제가 시스템 엔지니어가 아니다보니
이 수치가 준포탈급의 사이트를 운영하기에 적당한것인지에 대해서는 잘 모르겠네요.

항상 도움만 받아가네요. 감사합니다.
제목 : Re: HP-UX의 Thread 모델은..
글쓴이: 이원영(javaservice) 2005/12/22 15:55:02 조회수:633 줄수:31
HP-UX의 Thread 모델은 IBM AIX나 SUN Solaris에 비해 상대적으로 무겁습니다. 그래서 JVM하나에서
여러개의 Thread를 띄우는 것이 상대적으로 힘겹게 다가옵니다. 그래서인지, default로 설정된 
max_thread_proc 64개는 WAS(웹어플리케이션서버)와 같이 하나의 JVM에서 multi-thread로 구동되는
환경에서 늘 한번씩 겪는 것으로 상대적으로 작게 설정되어 있는 감이 늘 있습니다. 튜닝시 약방의
감초처럼 항상 올려주어야 합니다.

(Thread 모델의 특성 그렇다는 것이지, HP-UX가 WAS를 운영하기에 성능이 좋지 않다는 얘기가
 전혀 아닙니다. Thread를 키우는 것 보다 process를 multi로 클러스터링 하는 것이 HP-UX에서는 보다
 효과적이며, 개인적인 생각으로는 HP-UX가 WAS운영머신 및 성능적 관점에서 매우 유리한 위치를
 차지하고 있다고 생각합니다.)

Tomcat의 허용가능한 최대 thread 보다는 최소한 max_thread_proc 값이 크게 잡혀있어야 겠지요.

그러면 Tomcat의 최대 thread값은 얼마가 적당하냐란 질문이 나올 수 있는데, 이건 답이 없는
문제로서, 해당 사이트의 특성에 맞게 설정해야 합니다. (제니퍼와 같은 APM툴을 사용하시면
운영중에 몇개의 thread가 늘 쓰이는지를 모니터링 하실 수 있겠지요)

액티브서비스의 개수는 깔때기에 물을 일정하게 내려보낼 때, 그 물높이 해당 하는 특성이 있습니다.
단위시간당 흘러나올 수 있는 물의 량보다 단위시간당 흘러들어오는 물의 량이 근접하게 될 때,
물높이는 상대적으로 짧은 시간에 높아집니다.(정확히는 분수함수의 특성이 있습니다.)
무엇인가 backend에서 잠시 막히면 순식간에 차 올라오게 되지요. 따라서, 50개냐, 100개냐,
200개냐의 문제가 아닙니다. 50보 100보의 특성이 있는 것이지요.

-------
2005.12.23 첨언
아래 질문에 대해, "예, 적어도 그렇습니다."

자바서비스넷 이원영
Phone: 010-6239-6498
E-mail: NOSPAM_lwy@javaservice.com
MSN: NOSPAM_javaservice@hanmail.net
제목 : Re: 그렇다면...?
글쓴이: 손님(guest) 2005/12/22 18:36:40 조회수:297 줄수:9
일반적으로 tomcat의 server.xml에 

    <Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"

와 같이 설정이 되어 있는데요, 그렇다면 HP-UX의 max_thread_proc 값이 위의 maxThreads 값보다는 
즉, 150과 같거나 높게 설정이 되어야 하는건가요?


http://www.javaservice.net/ 펌...

'프로그래밍 > Library' 카테고리의 다른 글

[펌] eclipse short cuts  (0) 2007.11.28
[펌] eclipse 에서 run 실행시 jvm 에 대한 세팅은 어디서 하나요?  (0) 2007.11.28
james mail server  (0) 2007.11.28
[펌] james mail server setting  (0) 2007.11.28
[펌] JUnit 설정  (0) 2007.11.28

james mail server

프로그래밍/Library 2007. 11. 28. 09:30 Posted by galad

★ E-mail 보내기

http://james.apache.org/ 에서 james 메일 서버 다운로드
* C:\james 에 압축을 풀고 C:\james\bin 의 run.bat 파일을 실행
* James 환경 설정
– C:\james\apps\james\SAR-INF의 config.xml 파일 변경
사용자의 아이디와 암호를 변경 - <account login="itea" password="itea"/>
메일 서버 설정 - <servername>61.109.232.158</servername>
DNS 서버 지정
-  <dnsserver>
<servers>
<server>168.126.63.1</server>
<server>168.126.63.2</server>
<server>61.109.232.158</server>
<server>127.0.0.1</server>
</servers>
<autodiscover>true</autodiscover>
<authoritative>false</authoritative>
</dnsserver>
* config.xml 파일을 변경한 후 james 서버를 실행
* 메일 사용자 계정을 만들기 위해 명령어 창에서 이렇게 입력해서 james 서버에 연결
C:\> telnet localhost 4555
* 새로운 메일 계정을 만들기 위해서 이렇게 한다.
로그인을 한 다음,
adduser 아이디 비번  이렇게 입력하면 새로운 메일 계정이 생성됨.
 프로젝트 때는 ID: itea PW: itea 로 통합해서 사용하겠음.
* 메일을 전송하고 읽기 위해서 라이브러리 다운로드
http://java.sun.com/products/javamail/ 에서 JavaMail 위한 라이브러리 다운로드
압축을 풀고 mail.jar 파일을 j2SDK/jre/lib/ext 와 Tomcat/common/lib 에 복사
http://java.sun.com/products/javabeans/glasgow/jaf.html 에서 JAF 라이브러리 다운로드
압축을 풀고 activation.jar 파일을 j2SDK/jre/lib/ext 와 Tomcat/common/lib에 복사
톰캣 다시 시작

ps.

<authorizedAddresses>127.0.0.0/8, 61.109.232.*</authorizedAddresses>
메일 전송 권한 설정 - D:\www\james-2.2.0\apps\james\SAR-INF\config.xml 에서...

위의 속성을 없애면 아무나 메일을 보낼 수 있다. 즉, 스팸 메일 서버 등으로 사용가능해짐 ㅡ.ㅡ;;

[펌] james mail server setting

프로그래밍/Library 2007. 11. 28. 09:29 Posted by galad

http://blog.naver.com/galad/140033607909

출처 블로그 > もも***
원본 http://blog.naver.com/dmsl01/80033518048

 

james mail server setting

 

 


0. 실행 환경 2000 서버, Tomcat4.1.30, JDK1.4.3


1. http://james.apache.org/download.cg에 가서 실행파일을 받아 온다.
   Avalon Phoenix라는 것이 필요하다는 말이 있는데 실행 파일을 받아오면 그 안에 다 있는   

   것 같습니다. 그러니 따로 받지 않아도 됩니다.


2. 적당한 폴더에 압축을 풀고 james-2.1.3\bin 밑에 있는 run.bat를 실행시키십시요.
   물론 그전에 JDK는 설치가 되어 있어야 합니다. 실행이 되고 나면 Dos창이 하나 뜨는데 일

   단은 강제 종료를 시키십시요.


3. Dos창을 종료하고 james-2.1.3\apps 폴더를 보면 james라는 폴더가 생겨있을 겁니다.


4. james-2.1.3\apps\james\SAR-INF 폴더에 가서 보면 config.xml이라는 파일이 있는데

   이게 설정 화일입니다.


5. 에디터에서 그 파일을 열어 보면 여러가지 것들을 설청 할수 있습니다.
  

   5-1. 28번 줄에 <postmaster>Postmaster@abc.com</postmaster>으로 수정하세요.
         왜 그러는지는 알수 없지만 나중에 메일 서버를 관리 할때 필요
   5.2. 49번 줄에 <servername>abc.com</servername>으로 수정하세요.
         여기서 서버이름에 mail.abc.com으로 하시면 메일을 보낼때 메일 주소를

         user_id@mail.abc.com으로 해야 메일이 들어 오더라구요.
   5-3. <dnsserver>
          <servers>
          <!-- CONFIRM? -->
            <!--Enter ip address of your DNS server, one IP address per server -->
            <!-- element.  The default configuration assumes a DNS server on the localhost.

             -->
            <server>000.000.000.000</server>
          </servers>
          <authoritative>false</authoritative>
        </dnsserver> 부분을 수정하세요.
          메일 서버 James가 설치된 서버의 IP를 적으시면 됩니다.
   5-4. <remotemanager><remotemanager/>부분의 login/password가 있습니다. 자신이 원

         하는 ID와 패스로 수정하세요.
         나중에 유저를 관리할때 필요합니다.


6. james-2.1.3\bin 밑에 있는 run.bat를 다시 실행시키십시요. 다음과 같은 메시지가 나오면

   성공입니다.
     Using PHOENIX_HOME:   C:\james213\james-2.1.3
     Using PHOENIX_TMPDIR: C:\james213\james-2.1.3\temp
     Using JAVA_HOME:

     Phoenix 4.0.1

     James 2.1.3
     Remote Manager Service started plain:4555
     POP3 Service started plain:110
     SMTP Service started plain:25
     NNTP Service started plain:119
     Fetch POP Disabled


7. Dos창을 하나 더 띄우세요. 그리고 telnet abc.com 4555로 접속하면

   <remotemanager><remotemanager/>부분에서 정의한 ID로 접속하시면 됩니다.
   접속에 성곡하면 adduser test 1234같이 사용자를 추가 하세요.

   help를 치시면 도움말이 나옵니다.


8. outlook express 에서 메일 계정을 등록한 후에 테스를 해보시면 됩니다.


9. spoolmanager, Matchers, Mailets, DB접속은 아직 테스트 못해 봤습니다.



                                                                                                                           





1. 다운로드 및 설치
   우선 James를 받습니다...
   받을곳은 http://mirror.apache.or.kr/jakarta/james/binaries/
   여기서 james-2.1.3.zip를 받습니다
   받은다음 아무곳에나 압축을 풀고 james/bin 디렉토리에 run.bat를 실행하면

   Phienix 4.0.1이 먼저 가동되고 James 2.1.3이 실행되었다고 나옵니다..


2. 사용자 추가
   James를 가동한걸 잘 보면 Remote Manager Service Started plain:4555 라고 나올걸 볼

   수 있습니다.
   여기가 admin콘솔. 텔넷으로 접속합니다.
   명령 프롬프트에서 telnet localhost 4555 라고 치면 아이디랑 패스워드 넣으라고 나옵니

   다. 디폴트로 root/root로 잡혀있어요. 이거를 넣으면 Welcome root HELP for list 라고

   나옵니다.
  여기서 adduser [사용자 이름] [패스워드] 라고 치면 User [사용자이름] added 라는 메세

  지가 나옵니다. 추가된걸 확인하려면 listusers 라고 치면 됩니다.


3. 메일보내기/받기
   아웃룩에서 새로운 계정을 만듭니다.메일주소는 [사용자이름]@localhost
   POP3는 localhost , SMTP도 localhost, 사용자랑 비번은 아까 추가한 그걸로 넣으면 됩니

   다.그리고 테스트해보세요.


4. 설정하기
   James홈 밑에 app/james/SAR-INF/config.xml화일이 있읍니다..이게 설정화일입니다.

   28번째줄 정도에 보시면 <postmaster>admin@localhost</postmaster> 에서
   localhost대신에 도메인 네임을 적으시면 되고요~~
   49번째줄 정도에 보시면 <servername>localhost</servername> 에서 바꿔주심 돼 요.

   368번째줄 정도에 보시면
            <!-- Change the default login/password. -->
            <account login="root" password="root"/>
   이부분이 있는데 여기가 아까 어드민콘솔에 들어갈때 아이디랑 패스워드 입니다.



'프로그래밍 > Library' 카테고리의 다른 글

Tomcat 다운현상  (0) 2007.11.28
james mail server  (0) 2007.11.28
[펌] JUnit 설정  (0) 2007.11.28
CVS 설치 후, 사용자 추가하기  (0) 2007.11.28
cmd here!  (0) 2007.11.27

[펌] JUnit 설정

프로그래밍/Library 2007. 11. 28. 09:28 Posted by galad
출처 블로그 > もも***
원본 http://blog.naver.com/dmsl01/80033532103

 

[이클립스에서 JUnit 설정]

 

1. 상단 메뉴에서 [Window] -> [Preference] 를 선택한 다음, 좌측 트리에서 [Java]를 클릭한 다음 아래 생성된 [Junit] 클릭하여 JUnit 기본 설정을 변경할 수 있다.



[이클립스에서 JUnit 테스트]

 

1. [Package Explorer] 에서 소스가 위치한 소스폴더 또는 패키지에서 팝업메뉴를 띄운 다음 [New] -> [Other] 를 선택

2. 화면에 나타난 다이얼로그에서 [Java] -> [JUnit] -> [JUnit Test Case]를 선택

3. 화면에 나타난 메뉴 중단의 [Name] 항목에 새로운 JAVA 파일명을 입력하고, 하단의 [Class Under Test] 항목에는 테스트하고자 하는 JAVA 파일명을 입력한다.

4. 새로 나타난 화면에서 테스트 하고자 하는 메소드를 선택하여 체크한 다음 [Finish]버튼 클릭

5. 소스 창에 탬플릿이 생성된 것을 볼 수 있으며, 주어진 템플릿을 이용하여 코딩한다.

6. 소스 작성이 마무리 되면, 해당 소스를 선택한 다음, 팝업 메뉴에서 [Run] -> [Junit Test]를 클릭하면 테스트 내용을 [Junit] Perspective로 나타난다.


* JUnit Test Suite의 경우에도 위와 동일한 방식으로 템플릿 생성 및 테스트가 가능하다.

'프로그래밍 > Library' 카테고리의 다른 글

Tomcat 다운현상  (0) 2007.11.28
james mail server  (0) 2007.11.28
[펌] james mail server setting  (0) 2007.11.28
CVS 설치 후, 사용자 추가하기  (0) 2007.11.28
cmd here!  (0) 2007.11.27

1. CVS에서 사용할 디렉토리를 설정해줘야 한다.
Repository 라는 영역과 Temporary 라는 영역을 설정해 줘야 하는데

Temporary는 일반적인 임시파일을 쓸 경로로 지정해주면 되고
Repository는 CVS서버 하위의 저장공간이라고 생각하면 된다.

(각각의 Repository는 독립적인 경로를 가지게 되며 하위에 여러가지 모듈을

가지며 로그인 가능한 사용자등도 따로 가지게 된다.)


주의 Repository 와Temporary는 C:₩Documents and Settings₩ 하위 디렉토리에 설정을 하면 안된다.
(권한 관련한 문제가 생김)


2. 이제 CVS Conrtol Panel을 실행시켜

우선 CVSNT Service와 CVSNT Lock Service 를 멈춰준다.
Server Settings 탭으로 이동한후

Temporary를 설정해 준다.
Repository configuration 탭으로 이동후

Location 에 적당한 폴더를 설정한다.
Name 의 경우 외부에서 CVS에 접속을 할때 Repository를 선택할수 있는 이름을 나타낸다.

 

3. 이제 CVS의 각 Repository에 접속가능한 유저계정을 생성해야 한다.
이것은 윈도우의 계정을 설정할수도 있고 하나의 윈도우 계정을 사용하는 자체 cvs 계정을 생성할수도 있다.
물론 실제로 사용되는 윈도우 계정이 위에서 설정했던 디렉토리에 접근권한이 있어야 한다.
Administrator 를 cvs에서 사용하는 윈도우 계정으로 하고 사용자 계정을 만들어보면
윈도우의 시작 -> 실행 에서 cmd 를 입력하고 엔터를 눌러 커맨드 창을 띄운다.
프롬프트에서 cvs를 입력해 본다.
여기서 실행파일을 찾을수 없다는 메세지가 나오면 CVSNT를 설치하면서 정상적으로 PATH가 설정되지 않은 경우다. 이 경우는 환경변수(제어판->시스탬->고급->환경변수)의 PATH에 CVSNT가 설치된 디렉토리를 추가 시켜준다.
cvs에 정상적으로 접근을 하기위해서는 CVSROOT 라는 환경변수가 설정이 되어있어야 하므로 프롬프트 창에서
set CVSROOT=:pserver:Administrator@127.0.0.1:/SSA
를 입력한다. 위의 127.0.0.1 이 접속하려는 서버의 주소다.
그 앞의 Administrator 가 접속하려는 계정이고 가장 뒤의 /SSA는 위에서 설정해준 Repository 의 이름이다.
이제 로그인을 위해서 프롬프트 창에
cvs login
을 입력하고 해당계정의 패스워드를 입력한다.
정상적으로 로그인이 되면 아무메세지 없이 프롬프트로 돌아오며 이제 유저를 추가하면 된다.
cvs passwd -r Administrator -a yoway
을 입력하면 yoway 라는 계정을 추가하게 되며 CVS로 yoway 라는 계정으로 user가 로그인을 하면 윈도우의 Administrator 계정을 사용해서
CVS서버내의 리소스 접근권한을 제어하게 된다.


!! 위 처럼 해도 안되는 경우가 많다. 그 때는 새로이 cmd창을 열어서


C:\Documents and Settings\Administrator>set CVSROOT=:pserver:Administrator@127.0.0.1:/blog


C:\Documents and Settings\Administrator>cvs -d d:/www/CVS/blog passwd -r Administrator -a itea
Adding user itea
New Password:
Verify Password:


이것 처럼 한다


4. admin 권한주기
Repository 로 설정한 디렉토리의 CVSROOT 디렉토리 안에 admin 파일을 생성하고 각 줄에 하나씩 아이디를 적어주면 해당 아이디가 admin 권한을 가지게 된다.

5. 첨언
● Repository 는 각각이 source safe 에서 하나의 서버라고 생각하면 된다. 각각의 Repository 는 서로 다른 유저계정을 관리하므로 서로 다른팀, 완전히 독립된 프로젝트 등을 하나의 Repository 로 구분하는것이 좋다.
● 설치해서 Repository 를 설정하고 유저를 추가하는것 까지만 해두면 나머지 실제 모듈을 생성하고 소스를 올려두는것은 클라이언트 단에서 처리가 가능하다. 괜히 비어있는 Repository 에 소스를 올리고 할 필요는 없다.
● 방화벽이 있으면 외부에서 CVS에 접속을 할수가 없으므로 TCP 2401포트와 2402포트를 열어둬야 한다.

'프로그래밍 > Library' 카테고리의 다른 글

Tomcat 다운현상  (0) 2007.11.28
james mail server  (0) 2007.11.28
[펌] james mail server setting  (0) 2007.11.28
[펌] JUnit 설정  (0) 2007.11.28
cmd here!  (0) 2007.11.27

cmd here!

프로그래밍/Library 2007. 11. 27. 14:14 Posted by galad

'프로그래밍 > Library' 카테고리의 다른 글

Tomcat 다운현상  (0) 2007.11.28
james mail server  (0) 2007.11.28
[펌] james mail server setting  (0) 2007.11.28
[펌] JUnit 설정  (0) 2007.11.28
CVS 설치 후, 사용자 추가하기  (0) 2007.11.28