2008년 8월 27일 수요일

JtestR 써보기 - 실행

(이 글의 많은 내용은 JtestR 홈페이지의 Getting StartedConfiguration 에 기초하고 있다.)

디렉토리, 기본 설정

JtestR 은 기본적으로 test 디렉토리에 jtestr_config.rb 와 Ruby 테스트들이 있을 것을 기대한다. 물론 이 디렉토리가 test 가 아닐 경우 실행시 지정해 줄 수 있다. 지정해 주는 방식은 JtestR을 실행하는 방식에 따라 조금씩 다르다. (Getting Started 를 참조) JtestR의 기본 classpath 구성은 아래와 같이 이루어 진다.

   def find_existing_common_paths
     Dir["{build,target}/{classes,test_classes}"] + Dir['{lib,build_lib}/**/*.jar']
   end

이것과 현재의 구성이 다를 경우에는 jtestr_config.rb 에서 classpath 를 설정해 주어야 한다.

classpath 설정 예

   classpath ['classes','test_classes']
   classpath Dir['lib/*.jar']
   classpath Dir['test_lib/*.jar']

JUnit 테스트들의 경우는 jtestr_config.rb 에서 지정을 해 주어야 실행이 된다. TestNG 의 경우도 거의 같은 방식으로 지정해줄 수 있다고 한다.(TestNG를 써보지는 않았다.)

jtestr_config.rb 예

   junit 'unit' => ['com.some.company.any.prj.util.SomeAllTest',
                    'com.some.company.any.prj.app.SomeAllTest']

실행

background 서버

JtestR은 시작하는데 시간이 많이 걸린다. 이것은 JRuby 가 시작하는데 시간이 많이 걸리기 때문이다. 이 문제를 해결하기 위해 JtestR은 background 서버를 실행시키는 방법을 제공한다. background 서버가 실행 중일 경우 JtestR은 자동적으로 이것을 사용하도록 되어있다.

Ant, Maven 과 연동

Ant 예

   <target name="test" description="Runs all tests">
     <taskdef name="jtestr" classname="org.jtestr.ant.JtestRAntRunner" classpath="test_lib/jtestr-0.3.1.jar"/>
     <jtestr tests="test"/>
   </target>

Background 서버

   <target name="test-server" description="Starts test server">
     <taskdef name="jtestr-server" classname="org.jtestr.ant.JtestRAntServer" classpath="test_lib/jtestr-0.3.1.jar"/>

     <jtestr-server/>
   </target>
JUnit

JUnit의 TestCase 로 실행시키는 방법을 제시한 것은 다른 IDE 와 결합해서 사용하기 쉽게 해주려는 의도인 것 같다. org.jtestr.ant.JtestRSuite 을 JUnit 테스트로 사용하면 된다.

원문의 예

   <junit haltonfailure="false" fork="yes">
     <jvmarg value="-Djtestr.junit.tests=test_tests/one_of_each"/>

     <formatter type="xml" usefile="false"/>

     <test name="org.jtestr.ant.JtestRSuite"/>
   </junit>

(www.evalcode.com/2008/08/jruby-jtestr-in-eclipse 에 Eclipse 에서 이 방법을 사용해서 JtestR 을 실행시키는 방법이 소개되어 있다.)

command line

classpath 가 바르게 설정되어 있다고 가정한다면 그냥

   java org.jtestr.JtestRRunner

하면 된다.

테스트 디렉토리가 test 가 아닐 경우는

   java org.jtestr.JtestRRunner 22332 my_prj/my_tests

와 같이 하면 된다. (그 외 기타 옵션들에 대한 자세한 안내는 Getting Started 참조)

   java org.jtestr.JtestRRunner [port] [tests] [logging] [configFile] [outputLevel] [output] [groups]

(실수 - 처음 JtestR을 실행시킬 때 엉뚱한 문제로 한참 고생을 했었다. 기존의 JUnit 테스트들을 실행할 때 MethodNotFound 였던가? exception 을 내고는 중단 되는 것이다. 한참을 헤멘 뒤에야 CLASSPATH 에 junit.jar 가 있기 때문이라는 것을 알았다. 컴파일 시의 JUnit 과 실행시의 JUnit 버젼이 달랐다는 …)

(Getting Started 에는 없지만 background 서버를 command line 에서 실행시키는 방법이 있다. (JtestR 0.3.1 기준)

   java org.jtestr.BackgroundServer

)

Eclipse 에서 JtestR

필자의 Eclipse 환경은 대략 이렇다.

  • OS - ubuntu8.04 x86_64
  • JDK - sun-jdk-1.5.0
  • Eclipse - 3.4

(java 6 가 깔려 있기는 하지만 Eclipse 실행이나 개발시에는 쓰지 않는다.)

myeclipse.sh

   LANG=ko_KR \
     JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun \
     PATH=/usr/lib/jvm/java-1.5.0-sun/bin:$PATH \
     ~/usr/eclipse3.4/eclipse

필자 외에는 전부 MS 윈도우가 주 개발 환경이고 기존 코드의 한글 주석이나 스트링이 완성형이었기 때문에 LANG=ko_KR 로 설정하고 실행한다. (eclipse 안에서 설정할 수도 있지만, 처음 eclipse 를 쓰기 시작할 당시에는 이 방법이 가장 간단했다.)

Eclipse 에서 JtestR 을 실행시키는 방법은 위의 방법들이 거의 다 적용 가능하다. ant 도 지원하고 JUnit 테스트도 지원하고, JtestRRunner 를 Run 으로 실행시킬 수도 있다.

처음 시도한 방법은 JUnit 테스트로 실행시키는 방법이다. 그러나, 이 방법은 생각만큼 유용하지 않았다. Fail 이나 Error 시에 해당 파일로 이동이 잘 되지 않았다. JUnit 테스트들은 Failure Trace 가 제대로 나오지도 않았다.

ant 실행이나, 일반 Java Run configuration 을 이용하는 방법은 출력이 거의 유사하다. 이 경우 console 윈도우에서 ruby 파일로의 이동은 여전히 안 되지만, JUnit 테스트 Failure 의 경우는 이동이 가능하다. 현재 상태로는 일반 Java Run configuration 을 이용하는 것이 최선인 것 같다.

(Eclipse 플러그인 중에 coverage 분석 툴인 Emma 를 기반으로한 eclEmma 가 있다. JtestR을 실행하면서 coverage 분석을 하려면 background 서버를 사용하지 않도록 해야 한다.)

Emacs 에서 JtestR

Java 개발에 있어서는 팀의 준 표준 툴이기도 하고, 꽤 괜찮은 툴인 eclipse 를 주로 사용하기는 하지만, 원래 필자는 emacs 신도이다. ruby 파일 수정은 여전히 emacs 에서 주로 이루어지기도 하고, Eclipse 에서 ruby 파일로 바로 링크도 되지 않기 때문에 emacs 에서 JtestR 을 실행시켜 보기로 하였다.

처음 떠오른 것이 C 개발을 emacs 에서 해 본 사람이라면 누구나 기억할 emacs 의 compile 명령이다. M-x compile. (필자의 경우 예전에 너무도 자주 사용하던 명령이라 키 바인딩이 되어 있었다.) Compile command: 하고 물어온다. 관련 설정을 바꾸지 않았다면 처음 실행시에는 "make -k" 가 디폴트로 나올 것이다. "java org.jtestr.JtestRRunner" 라고 입력해도 되지만, 이건 좀 아니다. ant 를 쓴다면 "ant test" 해도 되겠지만, ant 실행시의 출력은 compile 이 적절한 파일을 찾는데 방해가 된다. (물론 여전히 그냥 실행시킨다고 적절한 파일을 바로 찾는 것은 아니긴 하지만 말이다.)

Rake 를 이용하자.

Makefile 을 만들고 make -k 를 그대로 사용하는 방법도 있겠지만, 루비스트 들에게는 Rake 가 있다.

필자가 만든 Rakefile 의 일부이다.

   task :test do |t|
     sh "java -cp test_lib/jtestr-0.3.1.jar org.jtestr.JtestRRunner" rescue nil
   end

(Java 빌드를 위한 ruby 툴로 rake 기반의 툴들이 있다. raven 과 buildr 이 그것들인데 불행하게도 이들을 사용하려할 당시 raven 은 잘 동작하지 않았고 buildr 홈페이지의 문서들은 온전한 상태가 아니었다. 지금은 buildr 의 문서들이 온전히 돌아와 있다.)

이제 Compile command: 에 rake test 를 입력하면 테스트들을 실행한다.

rspec Failure 로 바로 이동

실험을 위해 test/unit/fail_spec.rb 을 만들어 보았다.

   describe "fail test" do
     it "should fail" do
       'a'.should be == 'b'
     end
   end

그러나 compile 에서 fail_spec.rb 로 바로 이동하는 것은 여전히 잘 되지 않았다. 엄밀히 말해서 이동 시켜줄 생각이 전혀 없어 보였다. 이것은 JtestR 이 테스트 결과를 통합해 보여주면서 indent 를 하기 때문인 것 같다.

간단한 해결 방법은 jtestr_config.rb 에 rspec_formatter "p" 라는 내용을 추가 하는 것이다. (Configuration 참조) 이것은 rspec 자체의 출력기를 사용하는 것으로 indent 되지 아니한 결과를 출력하게 되고 이것은 compile 에서 잘 잡아 준다. 대략 다음과 같은 출력이 나온다.

   ...
   'fail test should fail' FAILED
   expected == "b", got "a"
   /home/hjlee/workspace/a_project/test/unit/fail_spec.rb:5:
   ...
그러나 아직은

그러나 compile 과 JtestR을 현재 상태 그대로 사용하는 것은 문제가 있다. (compile 이라는 명령 이름에서 보이듯이 테스트 를 위한 것이 아니라, compile 을 위한 도구이니 딱 입맛에 맞기를 바라는 것이 사실 무리이다.)

rspec 의 경우 위와 같은 꼼수를 사용해서 어찌할 수 있었지만 JUnit 의 경우나 Test::Unit 의 경우에는 여전히 해당 파일로 바로 가기가 어려웠다. 아마도 JtestR이 지원하는 다른 종류의 ruby 테스트 툴들도 비슷할까?

이것이 마음에 드는 수준으로 동작하게 하려면 JtestR과 포함된 테스트 툴들의 출력을 모두 고치거나, 새로운 emacs-lisp 페키지를 만들거나 compile 이 JtestR의 결과를 이해할 수 있도록 커스터마이징, 아니면 수정을 해야 한다.

차선책 - tags

이런 일들이 이루어지거나 누군가 해 놓은 것을 발견하거나 스스로 해결하기 전에는 차선책을 사용할 수 있다. 필자가 생각한 차선책은 TAGS 파일을 사용하는 방법이다. TAGS 파일을 만들고 visit-tags-table 로 이 파일을 읽어둔다. compile 결과 화면에서 이동하고 싶은 class 나 method 이름 위에 커서를 위치하고 C-x 4 . (‘find-tag-other-window’) 로 돌아다니는 것이다.

tags:emacs task

(blog.lathi.net/articles/2007/11/07/navigating-your-projects-in-emacs 여기서 본 것 같은데 열리지가 않는다.)

필자가 어떤 글에서 긁어서 조금 수정한 rake 소스 이다. (원문과의 차이 - *.java 는 없었다. TAGS 과 SRC_FILES 간의 의존 설정이 안 되어 있었다. xctags 가 ctags 로 바뀌었다.) 시스템에 설치되어 있는 ctags 명령은 오리지널 ctags 가 아닌 exuberant-ctags 이어야 한다. (ruby 를 이해하고 emacs 용의 TAGS 도 만들 수 있다.)

   module Tags
     SRC_FILES = FileList['**/*.rb'].exclude("pkg") + FileList['**/*.java']
   end

   namespace "tags" do
     task :emacs => "TAGS"
     file "TAGS" => Tags::SRC_FILES do
       puts "Making Emacs TAGS file"
       sh "ctags -e #{Tags::SRC_FILES}", :verbose => false
     end
   end

   task :tags => ["tags:emacs"]

소스 변경이 있으면 rake tags 로 TAGS 파일을 함께 수정해 준다. 뭐 test 테스크가 tags 테스크에 의존하도록 해 놓아도 될 것 같긴 하지만, 그렇게 해보지는 않았다. (기본 설정 상태에서 TAGS 파일의 변경이 있으면 emacs 가 find-tag 수행 전에 다시 읽을 것인지 물어본다. tags-revert-without-query - 이 customizing variable 로 물어 볼지 그냥 항상 다시 읽을지 설정할 수 있다.)

마치며

간단한 글들을 자주 올리려고 했는데, 세번째 글이 꽤 길어져 버렸다. JtestR은 시작한지 얼마 되지 않아 다른 툴들(시도해 본 것은 Eclipse 와 emacs 뿐이지만)과 함께 사용하기에 아쉬운 부분들이 있기는 하지만, 쓸만한 상태에 도달한 것 같다. 아무튼 누군가 JtestR을 써보려 하는 사람이 있다면 이 글이 도움이 되었으면 좋겠다.

댓글 없음: