지속적인 통합 빌드에서 crontab 처럼 주기적으로 빌드가 돌게 할 수 있습니다. 아래는 10분 주기로 실행하도록 한 결과입니다. trend 링크를 누르면 다음과 같이 그래프로도 확인이 가능합니다.

빌드의 실행 시점은 다음과 같이 정할 수 있습니다. 우측의 ? 아이콘을 클릭하면 해당항목에 대한 설명이 보이게 됩니다. 빌드에는 분 시간 일 월 요일 5가지 설정을 하게 됩니다. 매 10분마다 설정하려면 0,10,20,30,40,50 처럼 공백없이 분을 나열하고 이후 4항목을 * * * * 로 채우면 됩니다.

빌드 로그가 많이 남을까봐 Discard Old Builds처럼 옛날 빌드기록을 삭제할 수 있습니다. 7일간 최대 200개의 빌드기록을 보관한다는 의미입니다.


소스코드를 가져오는 방법은 다음과 같습니다. CVSROOT를 적어주면 됩니다. 아이디와 패스워드가 노출되는데, 인트라넷용이라는 전제가 있습니다. 또한 빌드전용 CVS아이디를 만들어 주는 것도 괜찮을 것입니다.

간략하게 hudson의 설정에 대해서 살펴보았습니다.






지속적인 통합 툴인 Hudson(https://hudson.dev.java.net)은 기업 내부 즉 인트라넷용입니다. 회사 밖에서는 접근하지 않는다는 것을 기본으로 설정하게 되어있죠. 만약 인터넷 같은 외부에 노출이 되는 경우는 인증을 걸어서 아무나 컨트롤하지 못하도록 하는 것이 중요합니다.

구글에서 "hudson access control"이라고 검색해봤습니다. wiki페이지가 나오는군요.


첫번째 링크를 클릭해서 들어가면 Hudson 보안강화하기 위키페이지가 나옵니다.
http://hudson.gotdns.com/wiki/display/HUDSON/Securing+Hudson

보안 레벨을 다양하게 지원하는데, 토픽은 다음과 같습니다.

Topics


저는 간략하게 설정해 보았습니다. 아직 경험이 많지 않아서 성큼성큼 나아가기 힘드니까요.
Quick and Simple Security 페이지의 설명에서 발췌한 내용입니다.

$ java -jar hudson.war --argumentsRealm.passwd.user=password --argumentsRealm.roles.user=admin

이러한 형식으로 시작 옵션을 줍니다.

$ java -jar hudson.war --argumentsRealm.passwd.kenu=okjsp --argumentsRealm.roles.kenu=admin

user와 password 부분을 변경해 주면 됩니다. 그리고 Hudson 설정에서 보안을 사용한다고 설정해야 합니다.
Hudson 관리(Manage Hudson) > Configure System 메뉴를 선택합니다.

설정화면에서 위쪽 설정 옵션 중 Enable security를 체크합니다. 하단의 옵션은 Delegate  to servlet container 에 그 아래 옵션은 Legacy Mode 를 선택하고 저장하면 됩니다.


설정이 완료되고 옵션을 주어서 시작하면 다음과 같은 메시지를 볼 수 있습니다.


로그인 id별  권한처리도 가능하다 하니 위키 문서를 참고하시면 될 것입니다.

최신버전에 대한 permalink 가 있군요.
http://hudson.gotdns.com/latest/hudson.war 
현재 1.260 버전이 최신입니다.


wget으로 받으려했는데, https로 포워딩되는군요. 바뀌 주소에 --no-check-certificate 옵션을 주어서 받았습니다.

[hudson@169s /home/hudson]# ls -altr
합계 20
-rw-r--r--    1 hudson   hudson        411 11월 10 22:03 .bashrc
-rw-r--r--    1 hudson   hudson        250 11월 10 22:03 .bash_profile
-rw-r--r--    1 hudson   hudson         25 11월 10 22:03 .bash_logout
drwxr-xr-x   10 root     root         4096 11월 10 22:03 ../
drwx------    2 hudson   hudson       4096 11월 10 22:03 ./
[hudson@169s /home/hudson]# wget http://hudson.gotdns.com/latest/hudson.war
--22:05:57--  http://hudson.gotdns.com/latest/hudson.war
           => `hudson.war'
Resolving hudson.gotdns.com... 192.18.49.133
Connecting to hudson.gotdns.com|192.18.49.133|:80... connected.
HTTP 요청을 보냅니다, 서버로부터의 응답을 기다림...302 Found
장소: https://hudson.dev.java.net/files/documents/2402/116126/hudson.war [following]
--22:05:59--  https://hudson.dev.java.net/files/documents/2402/116126/hudson.war
           => `hudson.war'
Resolving hudson.dev.java.net... 204.16.104.198
Connecting to hudson.dev.java.net|204.16.104.198|:443... connected.
ERROR: Certificate verification error for hudson.dev.java.net: unable to get local
issuer certificate
To connect to hudson.dev.java.net insecurely, use `--no-check-certificate'.
Unable to establish SSL connection.
[hudson@169s /home/hudson]# wget --no-check-certificate  https://hudson.dev.java.net/files/documents/2402/116126/hudson.war
--22:07:28--  https://hudson.dev.java.net/files/documents/2402/116126/hudson.war
           => `hudson.war'
Resolving hudson.dev.java.net... 204.16.104.198
Connecting to hudson.dev.java.net|204.16.104.198|:443... connected.
WARNING: Certificate verification error for hudson.dev.java.net: unable to get local
issuer certificate
HTTP 요청을 보냅니다, 서버로부터의 응답을 기다림...200 OK
길이:   20,804,156 (20M) [text/plain]
[========================================>] 20,804,156   790.53K/s    ETA 00:00
22:08:08 (724.78 KB/s) - `hudson.war' saved [20804156/20804156]


실행은 간단히 됩니다.
java -jar hudson.war


[hudson@169s /home/hudson]# java -jar hudson.war
[Winstone 2008/11/10 22:13:48] - Beginning extraction from war file
[Winstone 2008/11/10 22:13:55] - No webapp classes folder found - /home/hudson/.hudson/war/WEB-INF/classes
hudson home directory: /home/hudson/.hudson
2008. 11. 10 오후 10:13:59 hudson.model.Hudson load
정보: Took 219 ms to load
2008. 11. 10 오후 10:14:00 hudson.TcpSlaveAgentListener <init>
정보: JNLP slave agent listener started on TCP port 48801
2008. 11. 10 오후 10:14:02 org.springframework.context.support.AbstractApplicationContext prepareRefresh
정보: Refreshing org.springframework.web.context.support.StaticWebApplicationContext@1a9d1b: display name [Root WebApplicationContext]; startup date [Mon Nov 10 22:14:02 KST 2008]; root of context hierarchy
2008. 11. 10 오후 10:14:02 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
정보: Bean factory for application context [org.springframework.web.context.support.StaticWebApplicationContext@1a9d1b]: org.springframework.beans.factory.support.DefaultListableBeanFactory@146e381
2008. 11. 10 오후 10:14:02 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
정보: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@146e381: defining beans [filter,legacy]; root of factory hierarchy
[Winstone 2008/11/10 22:14:02] - HTTP Listener started: port=8080
[Winstone 2008/11/10 22:14:02] - AJP13 Listener started: port=8009
[Winstone 2008/11/10 22:14:02] - Winstone Servlet Engine v0.9.10 running: controlPort=disabled

결과는 다음과 같이 볼 수 있습니다.


job 을 죠브라고 번역해 놓았네요. 구글 번역기 짓인가요? ^^; 리포팅해야할 듯 합니다. 일본 개발자인 Kohsuke님에게 보내면 되겠지요.
from: http://www.zentus.com/sqlitejdbc/ 
구글링해서 제일 먼저 나온 사이트입니다. 검색어는 sqlite jdbc 였죠. freshmeat project로 버전업 발표가 된다고 합니다. 
sqlite3를 보고 처음 든 생각은 음, 이거 자바에서 어떻게 연결하지 였습니다. 리스너 또는 데몬이 떠 있지 않기 때문이죠. sqlitejdbc를 써보고 난 느낌은 약간 허탈했습니다. 원래 데몬이 뜨지 않더군요. 파일DB 입출력을 ANSI SQL로 만들어 놓은 느낌이었습니다. 따로 프로세스가 도는 것이라기보다는 애플리케이션에 애드온으로 삽입된 느낌이라고 할까요.

sqlitejdbc에는 현재 sqlite3가 포함되어 있습니다. 따로 sqlite를 받지 않아도 됩니다. 이클립스에서 테스트한 프로젝트 통째로 압축해서 올립니다. 라이센스는 BSD군요.


jdbc에 익숙한 분들은 아시겠지만 코드는 간결합니다.
사용법(usage) 부분에 사용시 주의사항이 나와 있습니다. 경량DB의 제한사항이 있으니 꼭 숙지하고 작업하셔야 할 것 같습니다. 항목은 다음과 같습니다.

간단한 DB가 필요할 때 유용할 것 같습니다. 대용량이나 빈번한 사용은 아직 무리겠지요.


http://www.sqlite.org/

용량은 다음과 같습니다. 맥용이죠. 476,916 바이트 0.5메가도 안됩니다.
-rwxr-xr-x@  1 kenu  staff  476916 11  6 22:29 sqlite3-3.6.4-osx-x86.bin

실행은 bin 파일 실행하면 됩니다. 물론 chmod +x 실행권한을 줘야죠.
(이름은 살짝 링크 만들었습니다. )
ln -s sqlite3-3.6.4-osx-x86.bin sqlite3

매뉴얼에 있는 예제를 실행하면 다음과 같습니다.

ex1 데이터베이스파일 만들고, tbl1 테이블을 만들어 레코드 2개 넣습니다.
kenu-heoyi-macbook-air-2:sqlite3 kenu$ sqlite3 ex1
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> create table tbl1(one varchar(10), two smallint);
sqlite> insert into tbl1 values('hello!',10);
sqlite> insert into tbl1 values('goodbye', 20);
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite> ^D
kenu-heoyi-macbook-air-2:sqlite3 kenu$ ls -ltr
total 952
-rwxr-xr-x@  1 kenu  staff  476916 11  6 22:29 sqlite3-3.6.4-osx-x86.bin
lrwxr-xr-x   1 kenu  staff      25 11  7 01:28 sqlite3 -> sqlite3-3.6.4-osx-x86.bin
-rw-r--r--   1 kenu  staff    2048 11  7 01:31 ex1
kenu-heoyi-macbook-air-2:sqlite3 kenu$ cat ex1;
???mtabletbl1tbl1CREATE TABLE tbl1(one varchar(10), two smallint)
   oodbye
hello!
kenu-heoyi-macbook-air-2:sqlite3 kenu$
from: http://www.sqlite.org/sqlite.html

일단 ansi sql이 동작하는 db입니다. Google, Adobe 등의 많은 데스크탑 애플리케이션에서 내장DB로 사용되고 있습니다. 문서 이후에 여러 커맨드들이 소개되고 있습니다.

jdbc 연결에 관해서는 더 연구를 해봐야겠습니다.


프로젝트 모니터링이라고 제목을 정한 이유는 Continuous Integration 은 평소 잘 하라는 의미입니다. 빅뱅통합이라고 하는 프로젝트 오픈 직전의 코드 통합은 전장을 방불케합니다. 평소에 만들어지는 코드에 대한 건강진단은 프로젝트가 산으로 가는 것을 막아줍니다. 그리고 버그가 숨어있을 여지도 줄여줍니다.

이번 세미나는 hudson을 중심으로 프로젝트의 건강상태를 모니터링할 수 있는 방법에 대해서 공유하려고 합니다.

소스 코드 공유
 - SVN,CVS
 - 저장소의 무결성
빌드서버
 - only for application source codes
Hudson
 - Continuous Integration Tools
 - Build Automation
 - Plugins
Project Report
 - JUnit
 - FindBugs
 - Checkstyle
 - PMD


강사: 허광남 okjsp운영자

장소: 아트레온 토즈 (신촌역 4번출구 아트레온극장 14층)
약도: http://www.toz.co.kr/v2/01about/pop_map_art.gif

일시: 2008/11/15 토 오전 10:00~12:00

회비: 20,000원 (당일 접수, 영수증 가능)

인원: 선착순 25명

 

메일로 신청받습니다.

kenu 골뱅 okjsp.pe.kr

 

이름:

닉네임:

이메일:

휴대폰:

 

본 강의는 실습강의가 아닙니다.

 

백기선님이 잘 번역하신 글입니다.
http://www.ibm.com/developerworks/kr/library/j-ap07088/index.html?ca=drs-kr 
findbugs를 통해서 코드의 취약성을 발견할 수 있었습니다.

CheckStyle, PMD, JDepend 등의 도구는 코드의 유지보수성과 가독성, 확장성을 떨어뜨리는 구문을 찾아줍니다.
이러한 도구들의 사용법과 리팩토링에 대한 글이 올라왔습니다. 아울러 글에서는 Switch구문을 polymorphism으로 리팩토링하기, 중복코드 줄이기, 긴 메소드(큰 클래스) 경량화하기, 너무 많은 import 줄이기 등에 대한 예들이 나옵니다.

참고하시면 좋은 애플리케이션 만드는데 큰 힘이 될 것입니다.

고전적인 자바 클래스의 테스트는 main() 메소드에 값을 찍어보는 코드를 넣어서 콘솔에서 확인합니다. 이클립스에 익숙해진 덕에 JUnit에서 System.out.println() 집어 넣는 것은 초딩같은 습관이라고 생각을 "저만"했었습니다. 하지만, 찍어본다는 것 그리고 그것을 눈으로 확인하는 것은 굉장한 심리적 안정감을 주기는 합니다. 아직 assertEquals() 는 보이지 않는 신뢰가 필요하기 때문이죠.

httpunit의 테스트코드를 보니 재밌는 부분이 있었습니다. 상당히 많은 수의 테스트케이스에 main() 메소드가 있었고, 그 메인메소드는 JUnit을 기반으로 해당 테스트코드를 수행하도록 만들어주는 것이었습니다.


suite() 메소드를 inline 리팩토링하면 junit.textui.TestRunner.run( new TestSuite( EncodingTest.class ));  를 통해서 실행을 합니다. Java Application 으로 실행한 결과는 다음과 같습니다.

..............
Time: 3.813

OK (14 tests)

물론 이 클래스는 JUnit을 통해서도 실행됩니다.

다른 사람의 코드를 읽는 것, 프로그래머 소통의 시작이 아닐까 생각해봅니다.

참고로 HttpUnitTest 클래스의 상속구조입니다. ctrl+T 로 이클립스에서 볼 수 있습니다.


 

최근 TSS에 재밌는 기사가 하나 떴습니다. 테스트케이스가 공식적으로 개발과정에 포함되는지 아니면 비공식적으로 만들어지는지에 관한 조사였습니다. 2006년에 이어서 2년 후인 2008년 설문을 진행했습니다. 데이터는 다음과 같습니다.

Answers 2008 (2006)
Unit testing is not performed: 17% (13%)
Unit testing is informal: 40% (46%)
Unit tests cases are documented: 9% (11%)
Unit tests cases and their executions are documented: 14% (16%)
We use a Test Driven Development approach: 20% (14%)

Participants: 384 (2006: 460)
Ending date: October 2008 (February 2006)
Source: Methods & Tools (http://www.methodsandtools.com/)

TDD 접근법을 사용하는 것은 20%로 증가한 것에 비해 단위테스트에 대한 노력은 오히려 감소했습니다. 그리고 의외인 것은 외국에서도 아직 단위테스트가 보편적이지 않다는 것이었습니다.

오픈소스 프로젝트 하나를 앞서 살펴봤습니다. 여기에는 test라는 테스트케이스를 모아놓은 폴더가 있었습니다. 소스의 양은 얼마나 될까요. httpunit 이라는 단위테스트용 프로젝트이기 때문에 좀 더 많이 있을 거라 예상했습니다.
예상대로 제가 회사에서 만든 테스트코드들과는 비교할 수 없이 많더군요.

요기까지가 패키지 하나에 들어있는 소스 코드들입니다. 이 코드들을 테스트하는 테스트케이스는 다음과 같습니다.
그리 많은 것은 아니지만 대략 1/5 정도 테스트케이스의 클래스들이 있지않나 생각됩니다. 각 테스트케이스 내의 테스트 메소드들이 애플리케이션에 대한 코드 커버리지를 책임지겠지요.

테스트케이스를 모아놓은 것이 테스트스위트입니다. *Suite.java 로 찾아보면 다음과 같은 스위트들이 보입니다.

빌드 스크립트에서도 테스트 관련 배치작업을 찾을 수 있습니다.



test 타겟을 실행해보니 다음과 같은 결과가 나오는군요.
test:
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .....................................F....
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .........................................
     [java] .....................................
     [java] Time: 22.656
     [java] There was 1 failure:
     [java] 1) testCookieAge(com.meterware.httpunit.cookies.CookieTest)junit.framework.AssertionFailedError: cookie2 expiration expected:<1223798608260> but was:<1112124642000>
     [java]  at com.meterware.httpunit.cookies.CookieTest.testCookieAge(CookieTest.java:202)
     ...
     [java]  at com.meterware.httpunit.HttpUnitSuite.main(HttpUnitSuite.java:49)
     [java] FAILURES!!!
     [java] Tests run: 775,  Failures: 1,  Errors: 0
BUILD SUCCESSFUL
Total time: 36 seconds

디버깅을 할 것은 아니지만, 이렇게 테스트케이스를 775가지 이상 갖고 있는 애플리케이션을 관리하는 것은 좀 더 수월하지 않을까 생각됩니다. 작업환경의 차이에서 발생하는 버그도 찾을 수 있고, 코드 변경으로 인한 틀어짐도 놓치지 않기 때문입니다.

읽어주셔서 감사합니다. 알찬 11월 되시길...
dw 기사를 보다가 JSDT(JavaScript Development Toolkit)를 알게 되었습니다. JavaScript 자동완성에 실시간 문법체크를 해줍니다. 어~ 좋은데, 그런데 어떻게 설치하지 찾아봤습니다만 WTP3.0 (Ganymede JEE 버전과 동일합니다.)에 기본적으로 포함되어 있더군요.

다음 이미지를 보시면 알 수 있듯이 다른 js 파일에서 선언된 변수도 가져다 쓸 수 있습니다.

위키를 보니 JSDT는 ATF(Ajax Toolkit Framework) 프로젝트의 서브 프로젝트로 진행중이네요.

JSDT에 대해 잘 요약된 DW기사도 일독을 권합니다.

+ Recent posts