개발&Development/프로그래밍 일반

PHPUnit에서 Trac까지

겐도 2007. 10. 29. 00:33
이글을 쓰는 시점에서 PHPUnit과 Trac은 완벽하게 붙지는 않는다. 그래도 시늉까지 해 보는 방법을 설명한다. 이후 좀더 깔끔하게 된다면 업데이트 하겠다.

유닛테스팅은 최근의 개발방법론에서 중요한 요소이다. 유닛테스트를 깨지지 않게 하는 것은 코드의 안정성을 유지하는 좋은 방법중 하나이다. 혹은 TDD(Test Driven Development)를 적용하는데도 기본적인 방법이다. CruiseControl을 사용해서 SubVersion Repository를 감시하며 지속적으로 실행하는 방법도 있겠지만 Trac에 바로 통합하는 방법을 설명코자 한다.

목표는 아래와 같다.
커밋이 일어나면 자동으로 유닛 테스트가 수행되고 그 결과가 Trac 페이지에 떡하니 뜨길 바란다.

우선 Trac과 SubVersion은 설치되어 있고 서로 잘 연결되어 있는 것으로 가정하겠다. (물론 이것도 아직 쉬운편은 아니다. python이 국내에선 그리 인기있는 플랫폼도 아니고...)

bitten의 설치는 http://bitten.edgewall.org/wiki/Documentation/install.html을 보면서 삽질을 좀 하면 된다. 우선 ez_setup이 필요하다.
wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python ./ez_setup.py
sudo로 명기한 것은 슈퍼유저 권한이 필요한 것이니 참고.
아직 bitten은 적당한 패키지를 제공하지 않는다. 소스를 받아야 한다.
svn co http://svn.edgewall.org/repos/bitten/trunk bitten
sudo python setup.py install
trac의 config(conf/trac.ini)에서 플러그인을 활성화 시켜주자. 아래는 추가할 내용이다.
[components]
bitten.* = enabled
퍼미션을 주자.
sudo trac-admin TestProject upgrade

sudo trac-admin TestProject permission add anonymous BUILD_EXEC
sudo trac-admin TestProject permission add anonymous BUILD_VIEW
sudo trac-admin TestProject permission add <관리자 계정> BUILD_ADMIN
웹어드민도 필요한데 아래의 과정을 수행한다.
wget "http://trac.edgewall.org/attachment/wiki/WebAdmin/TracWebAdmin-0.1.2dev_r4240-py2.4.egg.zip?format=raw"
받은 파일의 zip 확장자를 없애 준다. (rename) 그리고는

sudo easy_install TracWebAdmin-0.1.2dev_r4240-py2.4.egg

trac config에 아래 내용을 추가한다.
[components]
webadmin.* = enabled

마지막으로 아파치 한번 리스타트를 해 준다.


이제 Trac으로 들어가보면 Build라는 탭이 보인다. Admin에 가서 Builds/Configuration으로 가보자.
새로운 빌드를 만들때 중요한 점은 타겟을 적어도 하나 만들어야 한다. 그리고 레시피가 중요하다.
<build xmlns:svn="http://bitten.cmlenz.net/tools/svn" xmlns:php="http://bitten.cmlenz.net/tools/php" xmlns:sh="http://bitten.cmlenz.net/tools/sh" > <step id="Update" description="Update source from repository" svn:update revision="${revision}" /> </step> <step id="test" description="Run unit tests"> <sh:exec executable="/usr/bin/phpunit" <args="--log-xml testsuit/results.xml --tap testsuitSuiteForLib testsuit/testsuitSuiteForLib.php" /> <php:phpunitsuite file="testsuit/results.xml" /> </step> </build>
레시피 만드는 방법은 http://bitten.edgewall.org/wiki/Documentation/commands.html 를 참고하시고,
phpunit 실행부의 args는 phpunit의 설명을 보고 잘 맞춰보기 바라다. xml로 결과를 출력하며(필수) testsuit/testsuitSuiteForLib.php에서 testsuitSuiteForLib클래스를 수행한다.

위에서 보면 php:phpunit을 사용하지 않고 php:phpunitsuite라는 것을 사용한다. 단순히 testcase를 사용하는 경우 phpunit을 사용하면 되지만 suite를 사용하는 경우 파싱 에러가 난다. 이는 현재 http://bitten.edgewall.org/ticket/199 상황이다. 여차하면 수정을 제안하겠는데 python은 젬병이라 땜빵을 했다.

우선 bitten 소스에서
Index: setup.py
===================================================================
--- setup.py    (revision 515)
+++ setup.py    (working copy)
@@ -68,6 +68,7 @@
             NS + 'java#cobertura = bitten.build.javatools:cobertura',
             NS + 'php#phing = bitten.build.phptools:phing',
             NS + 'php#phpunit = bitten.build.phptools:phpunit',
+            NS + 'php#phpunitsuite = bitten.build.phptools:phpunitsuite',
             NS + 'php#coverage = bitten.build.phptools:coverage',
             NS + 'python#coverage = bitten.build.pythontools:coverage',
             NS + 'python#distutils = bitten.build.pythontools:distutils',

그리고 bitten/build/phptools.py 에서 "def phpunit"이란 곳을 찾아서 해당 함수를 아래에 복사한 후 phpunitsuite라는 함수로 변경한다.
for testsuit in xmlio.parse(fileobj).children('testsuite'):

부분을
for testsuitset in xmlio.parse(fileobj).children('testsuite'):
    for testsuit in testsuitset.children('testsuite'):

로 수정하고는 들여쓰기를 맞춰준다. 그리고는 다시 설치한다. 이걸로 대충 준비는 끝났다.

사용자 삽입 이미지

PHPUnit 테스트파일을 어떻게 만드는지는 다음 시간에. (같이 적으려니 글이 무척 길어진다.)