ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TDD ( Junit4 + Mokito + AssertJ ) 겉핥기 3
    Java/TDD 2019. 1. 29. 12:16
    반응형

    레거시 시스템에 적용 해보자!! 



     대충 필요한건 얼추 조사를 다한거 같고 , 원래 목적대로 적용을 해볼까 싶다. 


    적용전 아주 충격적인 사실을 알았다. Spring boot 를 사용할경우 기본적으로 Junit 4 + Mockito 가 내장 되어있다. Assertj 만 추가해주면 되는것이다. 

     spring boot 에 기본 내장되있는거 보면 spring 진영에서도 tdd 에 대한 관심이 있어보인다.  



    어쨌든 덕분에 굉장이 더욱더 쉽게 TDD 환경구성이 쉬어졌다. spring boot 를 쓰자... 참좋다! 



    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    @AutoConfigureWebMvc
    public class SbmanagerApplicationTests {

    @SpyBean
    private StatService statService;
    @SpyBean
    private BackService backService;
    @SpyBean
    private AccountService accountService;
    @SpyBean
    private BonusService bonusService;


    이것저것 시범 삼아서 어노테이션을 걸어보았다. Runwith 와 SpringTest 이것만 걸면 테스트가 빌드시에 실제로 진행된다. 어노테이션을 너무 남발하는거 안좋아하면서도 자꾸 쓰게 된다. 이러다 어노테이션의 노예가 될까 무섭다. 


    난 @Mockbean  대신 @SpyBean 을 사용했다. 전글에선 Mock에대해서만 조사했는데 사용하려고 좀 더알아보니 Spybean 이 지금 나에겐 더 필요한 녀석인거 같았다. 



    @Mockbean : 실체가 없고 가상의 조건을 주어 주어진 조건에 따라 응답을 내준다. 실제 데이터베이스와는 연동되는 로직이 있더라도 가상 객체기 때문에 연결하지 않는다. 


    @SpyBean : 실체 객체를 가져와서 사용한다. 구현된 로직이 직접 구동되며 실제 로직이기때문에 데이터베이스와도 연동이 실제로 이루어진다. 


    @SpyBean 을 선택한 이유 


     1. 테스트 케이스를 선정할때 이미 개발되있는 레거시 시스템이기때문에 실제 구현된 로직을 실행해보아야 한다는 점에서 한표 

     2. 실제 데이터를 가져오기때문에 추후 유지보수시 실제 값과 수정되 값이 정확히 일치하는지도 구현이 가능함. 

     3. RDBMS 를 사용중일 경우 Transaction 을 이용해서 CRUD 를 테스트 해볼수 있음 ( 단, 수행후 무조건 Rollback 실행 해야함 ) 


    무언갈 만들기 위해서가 아니라 , 있는걸 검증해보기엔 Mock 보단 훨씬 적합하다고 생각이 들었다. 


    그리고 한가지를 깨달은건 지금 내가 하는게 TDD 라기보단 통합테스트가 아닌가 라는 생각이 들었다. ( 이런걸 해보겠냐는 제안을 하신분도 실제론 TDD 에 대해서 잘모르셨던거 같다. 알았다면 개발 시작하기전에 제안을 하지 않으셨을까 싶다. ) 


    일단 데이터를 검증하기 위해서 요청 파라미터와 응답 파라미터 값 그리고 실제 호출할 메서드를 소유한 객체 클래스들이 필요했다.  


    import com.google.gson.Gson;
    import org.json.simple.JSONObject;

    public class TestParams {

    public JSONObject params1() {
    JSONObject topData = new JSONObject();
    JSONObject obj = new JSONObject();
    obj.put("type", "id");
    obj.put("data", "test");
    topData.put("params", obj);
    return topData;
    }

    public JSONObject params2(){
    String str = "{\"end_date\":\"2019-01-21\"}";

    return new Gson().fromJson(str, JSONObject.class);
    }


    그래서 각 서비스에 대해서 SpyBean 을 생성하고 , 위와 같이 세팅할 파라미터를 따로 관리하는 객체를 하나 생성 했다. SpyBean 에게 정확하게 혹은 부정확하게 파라미터를 전달하려면 따로 관리하기 좋게 모아놓는게 좋다고 판단을 하였다. 


    import org.json.simple.JSONObject;

    import java.util.ArrayList;
    import java.util.LinkedHashMap;
    import java.util.Map;

    public class TestResponse {

    public String response1(){

    return "{\"value\":166144631}";
    }


    그리고 응답은 실제 로그상에서 결과값을 찾아서 붙여 넣었다. 동일한 입력값에  내 예상 시나리오대로 값이 나오는지 확인하기 좋을거 같아서 

    응답값들을 모았다.  실제 @Spybean 에서 나오는 결과 값이랑 비교하는 용도 이다. 

    ( JSON 데이터를 비교해본결과 toString 형태로 변환하고 비교시 생각보다 잘 동작하는걸 확인했다. ) 


    @Test
    public void pginfo_test() throws Exception {

    TestResponse tr = new TestResponse();

    JSONObject obj = tr.prams1();

    JSONObject chk = statService.pg_list();


    assertThat(chk.toString()).isEqualTo(obj.toString());
    assertThat(chk.get("list")).isNotNull();


    }

    SbmanagerApplicationTests 클래스 안에 테스트 코드를 위와 같이 작성하고 실제 빌드를 해보니 아주~ 잘 동작 했다. 의도한대로 에러도 잘발생 시키는거같다. ( 이미 QA 까지 한 소스라서 잘안되는게 이상한 ^^;;)


     확실히 느낀건 겉핥기 식으로 해서 뭔가 제대로된 TDD 를 하기엔 생각보다 시작하는게 쉽지많은 않다는것과 정말 능숙하게 된다면 어느정도 자신이 만들어낼 로직에 대한 어느정도 품질 보장은 될거란것은 확실하게 보였다. 

     지금한건 TDD 라기에는 전문가들입장에선 잘못된 부분이 많이 보일것이고 실제로 하면서도 뭔가 이건 잘못되고 있다 혹은 다른식으로 해야할거 같다는 생각이 너무 명확하게 느껴졌다. 

     TDD 는 분명 개발 시작하기전에 먼저 선행으로 시작을 해야만 전적으로 여러가지를 해보고 응용이 가능하고 , 레거시 시스템에 붙인다는건 어떻게보면 리버스엔지니어링에 가까운 통합 테스트가 아닌가 싶다. 


     그리고 이런식으로 구현 것들은 로직에대한 안정성을 100% 커버가 절대 불가능 하고 특히 웹사이트라면 더더욱 힘들거 같다. 


    실제로 웹사이트에서 사용자의 이벤트 발생에 따른 동작을 검증 해보려 Selenium 이란걸 찾아보긴 했지만 


    결론은 배보다 배꼽이 더크겠다 . 였다. 

    ( https://www.seleniumhq.org/ )


    화면 크롤러로 많이 사용하는 제품으로 분명 어느정도 TDD 를 위한 도구가 충분히 될수 있겠지만 개인적으로는 QA 시나리오 테스트를 좀더 정밀하게 진행해서 기능의 품질을 보장 하는것과 저런 툴을 사용해서 자동화 품질 보장을 하는것 두가지 무엇이 나은가에 대해 심각하게 생각해봤다. 


    그리고 내린 결론은 전자가 더 효율적이라고 생각이 들었다. 우리는 개발자 아닌가 ? 개발자 직업병이 비효율적인것을 왜 해야 하는가에 대한 저항심이 아닌가 싶다. 


    그래서 깔끔히 포기했다. 


     우여 곡절끝에 실제 내용은 얼마 안되는 테스트 코드들을 프로젝트에 붙였고 빌드 할때마다 그 코드들은 내가 짜놓은 시나리오 대로 테스트 코드를 실행하고 Spring boot 라는 로고 와 함께 로고에 찍히고 있다. ( 테스트 코드를 많이 붙일수록 빌드타임에 영향이 갈거 같다. 이것도 작성시 고려 해보아야 한다.)


    물론 커버리지는 따져보면 50%도 채 안될거 같다. 그래도 TDD 란 개념에 대해서 겉핥기를 제대로 한거 같아 뿌듯하다.  이런기회가 없다면 해볼 일이 있을까 싶다. 맛을 봤다는거에 의의를 두고 싶다. 


    누군가 다음 프로젝트 시작히 TDD 를 할거냐 하고 물으신다면 자신있게 말할거 같다. 


    " TDD 는 개발하는데 옳은 방식 중 하나지만  전 안할겁니다. " 



    ( TDD 가 절대 안좋다는건 아니고 지극히 개인적 취향에 안맞다는점.... ) 






    반응형

    'Java > TDD' 카테고리의 다른 글

    TDD ( Junit4 + Mokito + AssertJ ) 겉핥기 2  (0) 2019.01.29
    TDD ( Junit4 + Mokito + AssertJ ) 겉핥기 1  (0) 2019.01.29
Designed by Tistory.