ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 단위 테스트용 테스트 데이터베이스 싱크하기
    Object & Test 2011. 7. 7. 19:41

    데이터베이스에 대한 단위 테스트를 작성하고 실행하기 위한 전략으로 우리는 보통 로컬 컴퓨터에 테스트용 데이터베이스를 구축하고 테스트를 수행합니다. 개인 PC에서 테스트가 성공적으로 수행되면 SVN, CVS같은 소스형상관리 서버에 커밋을 하게 되고, 이를 CI(Continuous Integration) 도구가 통합하게 됩니다. CI도 통합 테스트를 수행하기 위해 테스트 데이터베이스가 필요한데 이럴 때는 공용 테스트 데이터베이스를 따로 구축해서 사용하고 있습니다. 

    로컬 데이터베이스는 개발자가 마음대로 변경할 수 있기 때문에 구현하고 있는 기능에서 필요한 데이터베이스 변경 사항을 바로 반영해 테스트를 수행하며, 테스트가 온전히 수행되면 변경내역을 공용 데이터베이스에 반영합니다. (직접 하거나 혹은 DBA를 통해서…)

     이런 흐름에서는 변경사항이 계속 공용(중앙) 테스트 데이터베이스에 누적 반영되며, 병합(merge)되기 때문에 혹여, 문제가 생길 경우 테스트가 실패하면서 바로 인지하고 대처할 수 있게 됩니다. 문제는 개발자 로컬 데이터베이스도 주기적으로 공용 데이터베이스와 동기화할 필요가 있다는 것입니다. 개발자 로컬 데이터베이스에서 너무 오래된 버전의 데이터 모델을 사용할 경우 형상관리에서 체크아웃 받은 컴포넌트들에 대한 테스트가 동작하지 않는 문제가 생길 수 있기 때문입니다.

    래서 동기화 작업을 주기적으로 수행하게 되는데 보통은 변경 사항이 누적된 SQL을 받아 로컬 데이터베이스에서 실행함으로써 변경 분을 업데이트 하거나, 아니면 로컬 데이터베이스를 깨끗이 밀어버리고 공용 테스트 데이터베이스에 대한 덤프(dump)를 밀어 넣습니다.

    변경 분 업데이트의 경우 팀원들이 실수(혹은 고의;;;)로 변경 사항을 누락하게 되면, 업데이트 후에도 단위테스트가 동작하지 않는 문제가 발생할 수 있습니다. 그러면 작업자를 찾아 변경된 부분을 체크하고 다시 SQL을 업데이트 해야 합니다. 당연히, 상당히 귀찮은 작업입니다.

    그래서 저는 작동이 확인된 공용 데이터베이스에 덤프를 밀어 넣는 방법을 선호합니다. 근데 그것도 덤프를 만들고 로컬 데이터베이스를 날리고, 덤프를 밀어 넣는 과정이 귀찮기는 마찬가지 입니다. 오늘 더이상의 귀차니즘을 참지 못하고 점심 시간에 Ant를 이용해 이 과정을 자동화하는 배치 스크립트를 작성했습니다. 구글링 해서 나온 몇 가지 스크립트를 조합하고 실행하는데 까지 한 시간 정도 걸렸습니다. (구글 만세!) 그리고 자동화 스크립트 실행시간은 40초 정도 걸립니다. 4~5분 정도 걸리던 작업이 40초로 줄었습니다. ㅋㅋㅋ

    <?xml version="1.0" encoding="UTF-8"?>

    <!--
     
      * mysql용 원격 테스트 데이터베이스와 로컬 테스트 데이터베이스 동기화를 위한
     
      * ANT 스크립트.
     
      * 지정된 원격 테스트 데이터베이스에 접속해서 데이터베이스를 덤프한 후 
     
      * 로컬 데이터베이스에 카피한다.
     
      *
     
      * 테스트 데이터베이스 카피하기 귀찮아서 만듬
     
      * Maven 레포지토리 위치가 안맞으면 동작하지 않을 수 있음.
     
      * 
     
      * 작성자 : 김영진 at 넥스트리소프트
     
      * 작성일 : 2011.07.07
     
     -->

    <project name="dbsync"  default="make" basedir=".">

    <description>test database sync script</description>

    <tstamp>
     
        <format property="today" pattern="yyyy-MM-dd" />
     
    </tstamp>

    <property environment="env"/>

    <!-- maven configuration -->
    <property name="maven-repsoitory-dir"                  value="${env.HOMEDRIVE}${env.HOMEPATH}\.m2\repository"/>

    <!-- mysql driver -->
    <property name="mysql-driver"  value="${maven-repsoitory-dir}\mysql\mysql-connector-java\5.1.6\mysql-connector-java-5.1.6.jar" />

    <!-- dump file name -->
     
    <property name="dump-file-name"  value="${java.io.tmpdir}/vizend-test-dump-${today}.sql" />


    <!-- remote test server -->
     
    <property name="remote-host"  value="nextreesvn" />
     
    <property name="remote-user-id"  value="XXX" />
     
    <property name="remote-password"  value="XXX" />
     
    <property name="remote-target-db-name"  value="vizend_test" />

    <!-- local test server -->
     
    <property name="local-host"  value="localhost" />
     
    <property name="local-user-id"  value="XXX" />
     
    <property name="local-password"  value="XXX" />
     
    <property name="local-target-db-name"  value="vizend_test" />
     

    <!-- database dump-->
     
    <target name="dump">
         <echo message="database dump start..."/>  
     
        <exec executable="mysqldump" output="${dump-file-name}">  
     
            <arg value="--user=${remote-user-id}" />  
     
            <arg value="--password=${remote-password}" />  
     
            <arg value="--host=${remote-host}" />  
     
            <arg value="--port=3306" />  
     
            <arg value="${remote-target-db-name}" />  
     
        </exec>
     
        <echo message="database dump complete!"/>  
     
    </target>

    <!-- local database initiation -->
     
    <target name="init" depends="dump">
         
    <echo message="local database init..."/> 
        
    <sql  driver="com.mysql.jdbc.Driver"
             
    url="jdbc:mysql://${local-host}:3306" 
             
    userid="${local-user-id}" 
             
    password="${local-password}"
             
    autocommit="true">
         
    <classpath>
                
    <pathelement location="${mysql-driver}"/>
         </classpath>
         
          
    drop database ${local-target-db-name};
          
    create database ${local-target-db-name}; 
          
    use ${local-target-db-name};
         grant all privileges on ${local-target-db-name} to '${local-user-id}'@'localhost';      grant all privileges on ${local-target-db-name} to '${local-user-id}'@'%'; 
     
    </sql> 
         
    <echo message="local database init complete!"/>
     
    </target>

    <!--  building tables... -->
     
    <target name="make" depends="init">
          <echo message="db table build start..."/>
           <
    sql  driver="com.mysql.jdbc.Driver" 
                
    url="jdbc:mysql://${local-host}:3306/${local-target-db-name}"  
               
    userid="${local-user-id}" 
          password="${local-password}"> 
            <classpath>
                    
    <pathelement location="${mysql-driver}"/>
             
    </classpath>
              
    <transaction src="${dump-file-name}"/>
            
    </sql>
           
    <echo message="db table build complete!"/>
    </target>
    <
    /project>

    대상 데이터베이스는 mysql이며, 이클립스 Indigo에서 동작을 확인했습니다. :)

Designed by Tistory.