앞 이야기:
- 2013/10/21 - [개발자이야기] - 작은 프로젝트 구현 이야기 1 - DB 코드(plsql) 백업툴 초기 설계
- 2013/10/22 - [개발자이야기] - 작은 프로젝트 구현 이야기 2 - DB 코드 백업 툴 설계 변경
- 2013/10/22 - [개발자이야기] - 작은 프로젝트 구현 이야기 3 - 변경된 소스 제공 위한 DbCode 구현
작은 요구 사항 변경이 발생했다. 최초의 계획은 '전날 6시 이후의 변경 내역'을 읽어와 리포지토리에 반영하는 것이었는데, 대화를 진행하면서, 아래와 같이 변경되었다.
- 나: 팀장님, 말씀하신 것 개발이 완료되어 가는데요, '전날 6시 이후로 변경된 내역을 보관하도록 했어요. 매일 오전 6시에 배치로 돌리면 될 것 같아요.
- A: 최팀장, 그거 업무 시간 중에 변경되는 증분을 보고 싶은 그런 것도 있어서 24시간은 너무 긴 거 같아. 좀 더 짧았으면 좋겠는데....
- 나: 그럼 얼마나요?
- A: 음.. 10~20분 주기로?
- 나: 아,, 네. 단순히 일단위 백업이 아니라 소스 버전 관리 느낌을 좀 더 보태고 싶다는 말씀이시죠?
- A: 네 그래요~
이 요구사항을 충족하려면 전날 6시가 아니라 마지막으로 백업 받은 이전 시간을 어딘가에 기록했다가 다음에 실행할 때 그 시간을 찾아야 한다. 기록할 장소로 파일을 선택했고, 이를 반영하기 위해 테스트를 수정했다.
public class BackupToolTest {
private static final String TIMEFILE_PATH = "target/timefile.txt";
private DbCodeFinder mockDbCodeFinder = mock(DbCodeFinder.class);
private BackupTool tool = new BackupTool();
private SvnClient mockSvnClient = mock(SvnClient.class);
private ArgumentCaptor<Date> captor;
private List<DbCode> dbCodeList;
@Before
public void setUp() {
tool.setDbCodeFinder(mockDbCodeFinder);
tool.setSvnClient(mockSvnClient);
captor = ArgumentCaptor.forClass(Date.class);
createDbCodeList();
when(mockDbCodeFinder.findUpdatedDbCodesBetween(any(Date.class), any(Date.class)))
.thenReturn(dbCodeList);
deleteTimeFileIfExists();
}
private void deleteTimeFileIfExists() {
File file = new File(TIMEFILE_PATH);
file.delete();
}
@Test
public void givenTimeFileNotExists_run() throws IOException {
tool.backup();
verify(mockDbCodeFinder).findUpdatedDbCodesBetween(captor.capture(), captor.capture());
verify(mockSvnClient).commit(dbCodeList);
List<Date> dateValues = captor.getAllValues();
Date fromDate = dateValues.get(0);
// 파일이 없는 경우 하루 전달 이후 변경 분을 읽어오는 지 검사
assertThat(getTimeByMinutes(fromDate), equalTo(getOneDayBefore()));
// tool.backup() 실행 후, 지정한 파일에 마지막 실행 시간 기록하는 지 검사
assertTimeFileWritten(dateValues.get(1));
}
@Test
public void givenTimeFileExists_run() throws Exception {
givenTimeFile();
tool.backup();
verify(mockDbCodeFinder).findUpdatedDbCodesBetween(captor.capture(), captor.capture());
verify(mockSvnClient).commit(dbCodeList);
List<Date> dateValues = captor.getAllValues();
// 변경된 쿼리 구할 때 사용할 시작 시간 값을 파일에서 읽어오는 지 검증
assertThat(DateUtil.formatDate(dateValues.get(0)), equalTo("20131018120130"));
// tool.backup() 실행 후, 지정한 파일에 마지막 실행 시간 기록하는 지 검사
assertTimeFileWritten(dateValues.get(1));
}
private void givenTimeFile() throws Exception {
File file = new File(TIMEFILE_PATH);
FileCopyUtils.copy("20131018120130", new FileWriter(file));
}
private void assertTimeFileWritten(Date toTime) throws IOException {
String fileContents = FileCopyUtils.copyToString(new FileReader(TIMEFILE_PATH));
assertThat(fileContents, equalTo(DateUtil.formatDate(toTime)));
}
... // 나머지 다른 메서드들
처음부터 위 테스트 코드가 완성된 것은 아니고, 아래의 순서로 위 코드가 만들어졌다.
- givenTimeFileExists_run() 메서드를 작성
- 마지막 실행 시간을 기록한 파일이 존재할 경우, DB에서 조회할 때 사용되는 시간 값으로 파일에 기록된 값을 사용하는지 검사
- 실행 종료 후 마지막 실행 시간을 지정한 파일에 보관하는지 검사
- givenTimeFileExists_run() 테스트를 통과시키기 위해 BackupTool의 backup() 메서드 구현
- 기존 테스트 메서드의 이름을 givenTimeFileNotExists_run() 으로 변경
- 기존 파일이 없는 경우이므로, setUp() 메서드에서 파일 존재시 삭제 처리
- 파일이 없는 경우 24시간 이전 시간을 조회 시작 시간으로 사용하는 지 검사
- 실행 종료 후 마지막 실행 시간을 지정한 파일에 보관하는지 검사
- givenTimeFileNotExists_run() 테스트를 통과시키기 위해 BackupTool의 backup() 메서드 구현
이제 남은 작업은 정리하지 못한 코드들을 마저 정리하는 것이다. 이건 어린개발자1에게 숙제로 남겨둘 예정이다.