'PHPUnit'에 해당되는 글 2건

  1. 2007/10/29 Zend Studio for Eclipse로 PHPUnit 놀이 (2)
  2. 2007/10/29 PHPUnit에서 Trac까지 (1)
http://www.zend.com/products/zend_studio/eclipse

Zend Studio가 연말쯤 새 버젼을 내면서 Eclipse를 기반으로 할 예정이라고 한다. 더불어 PHPUnit 개발자가 제안해서 PHPUnit의 지원을 제대로 해 준다. http://gendoh.com/2510973 을 할때 물론 PHPUnit 자체가 Test Skelecton 만들기를 제공해 주기는 하지만 커맨드 프롬프트에서 하는 건 역시 귀찮다. 역쉬 IDE에서 해야 :)

사용자 삽입 이미지

텍스트 큐브로 한번 장난을 쳐볼까 한다. 위의 링크에 있는 튜토리얼 동영상도 있겠지만 /lib/database.php에 있는 함수들을 테스트 해 보자. 텍스트큐브의 트렁크 파일들을 받아보자. (http://dev.textcube.org/svn/trunk) 그리고 편의상 /testsuit 란 폴더를 별도로 만든다.
사용자 삽입 이미지

/lib/database.php의 escapeString 함수에서 우클릭 후 위처럼 PHPUnit Test Case를 선택한다.
사용자 삽입 이미지

소스폴더를 변경해 주고 Finish. escapeSearchStringTest.php를 선택하고 Run/Run-as/PHPUnit Test(Alt+Shift+x, u)를 수행해 보자.
사용자 삽입 이미지

어렵쇼. -ㅅ-. 텍큐 현재 상태가 좀 모듈간의 디펜던시가 심하다. 예제도 그나마 적은 걸로 찾아본거지만 쉽지많은 않다.
require_once('components/Needlworks.DBMS.MySQL.php');
if (!function_exists('mysql_escape_string')) {
 function mysql_escape_string($string) {
  return str_replace(array("\x00","\n","\r","\\","'","\"","\x1a"),array("\\\x00","\\\n","\\\r","\\\\", "\\'","\\\"","\\\x1a"),$string);
 }
}

소스 상단에 위의 내용을 넣고 돌려보자.
사용자 삽입 이미지
정확히 고치려면 모듈화를 다시 수행하고 테스트시의 파일 연결을 어떻게 할까 고민해야 겠지만 여기서는 걍 돌게만 해보자. 최초의 테스트이니 구현되지 않았다고 궁시렁 거린다. 이제 제대로 짜봅시다.
 public function testEscapeSearchString()
 {
  // TODO Auto-generated escapeSearchStringTest->testEscapeSearchString
  $this->assertEquals(mysql_escape_string('\\'),'\\\\');
  $this->assertEquals(escapeSearchString('as_df%'),'as\\_df\\%');
  $this->assertEquals(escapeSearchString('as\\_df%'),'as\\\\\\_df\\%');
  $this->assertEquals(escapeSearchString('아이팟'),'아이팟');
 }

\의 개수때문에 정신 없지만 뭐 이정도는 해야 되겠죠. '아이팟'테스트는 특정 환경에서 '\'가 붙어버리는 버그를 확인하기 위한 케이스입니다. 돌리면 깔끔하게 떨어집니다.

Test Suite를 만드는 것은 별로 어렵지 않습니다. Suite은 Test Case를 한번에 돌려주는 역할이 전부입니다. 가능하면 Test케이스는 함수 혹은 클래스 단위로 만드는 것이 좋습니다. 그리고 그것을 Suite로 묶는 것이죠.
사용자 삽입 이미지

지금 비스타와 Neon이 살짝 맛이 갔는지 결과가 보이지 않습니다만 대충 돌고 있습니다. (둘다 아직 베타인게냐 -ㅅ-)

아직 Eclipse의 PDT에서는 PHPUnit이 완벽하게 연결이 되지 않습니다. PHPed와 Zend Studio for Eclipse 정도만 잘 되는 것 같습니다. 물론 위처럼 좀 삐거덕 하기는 합니다만. -ㅅ-

PHP를 쓰는 환경이라면 이 글을 기반으로 좀 찾아보길 권장하며 다른 환경이라도 Unit Test 환경을 준비해 보길 권장합니다. 이 작업의 이점은 최근 책들을 찾아보면 침이 마르도록 나올껍니다.

PS.
음 텍큐는... 음... 언제 하지 --? 시간나면. 아니면 티켓던지기 신공이나.. --?
이글을 쓰는 시점에서 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 테스트파일을 어떻게 만드는지는 다음 시간에. (같이 적으려니 글이 무척 길어진다.)