수업은 2일전에 들었지만 당일날 너무 정신도 없고 잘 이해가 되지 않아서 바로 정리를 못했다.

 

그러고 이전에 구매해놓았던 패스트캠퍼스에서 홍종완 선생님의 강의를 들으며 조금 이해된거같아 정리하려 한다.

 

우리는 이전 프로젝트에서 테스트코드를 사용하지 않았다. 일일이 view페이지에서 데이터를 넘겨가며 로그를 찍어서
어디서 문제가 생기는지 확인하고 수정하는식으로 했다.

하지만 테스트코드를 사용한다면 view페이지가 만들어지지 않은 상황에서도 테스트를 실행할 수 있고 더욱 구체적인 조건을 줄 수 있다. 

 

테스트코드를 작성하는 이유는 4가지가 있다.

하나씩 코드와 함께 정리해보려 한다.

 

1. 문서화 역할

@DisplayName("패스워드를 초기화한다.")
    @Test
    void passwordTest() {
        //given
        User user = new User();

        //when
        user.initPassword(() -> "aabbccddee");

        //then
        assertThat(user.getPassword()).isNotNull();
    }

하나씩 DisplayName에 설명을 달아놓다 보면 이 코드가 어떤일을 하는 지 알수 있다.

 

 

2. 코드에 결함을 발견하기 위함

당연히 테스트를 통해 코드의 결함을 확인할 수 있다.

 


3. 리팩토링시 안정성 확보

완성된 기능에 대해서 리팩토링을 할 때, 미리 테스트를 해보니 안정성을 확보할 수 있다.

 


4. 테스트 하기 쉬운 코드를 작성하다 보면 더 낮은 결합도를 가진 설계를 얻을 수 있음

이건 예시상황을 들면 이해가 쉬워진다. 

유저의 비밀번호 초기화 메서드를 만들고 테스트를 하고자 한다. 비밀번호의 조건은 8자리 이상 12자리 이하이다.

그리고 그걸 위해 랜덤 하게 0에서 12자리의 숫자+문자열을 생성하는 메서드(randomPassword)를 만들었다. (코드는 아래에)

그리고 유저의 비밀번호를 초기화하는 메서드는 다음과 같다. 8자리에서 12자리의 값이 생성된다면 멤버변수의 password가 채워질 것이고, 그렇지 않다면 password는 null값이 된다.

public void initPassword(){
        //as- is 방식
        RandomPasswordGenerator randomPasswordGenerator = new RandomPasswordGenerator();
        String randomPassword = randomPasswordGenerator.generatePassword();
        if(randomPassword.length()>=8&&randomPassword.length()<=12){
            this.password = randomPassword;
        }
    }

 

이 상황에서 테스트 코드를 실행한다면?

저 randomPassword가 어떤값이 생성되느냐에 따라 성공 실패가 달라질 것이다. 이 때 인터페이스를 만들고

package org.ict.ooppractice;
@FunctionalInterface
public interface PasswordGenerator {
    String generatePassword();
}

RandomPasswordGenerator가 해당 인터페이스를 구현하도록 한다.

public class RandomPasswordGenerator implements PasswordGenerator {

initPassword 메서드를 다음과 같이 수정하고

public void initPassword(PasswordGenerator passwordGenerator){
        //as- is 방식
        //RandomPasswordGenerator randomPasswordGenerator = new RandomPasswordGenerator();
        //String randomPassword = randomPasswordGenerator.generatePassword();
        String randomPassword = passwordGenerator.generatePassword();
        if(randomPassword.length()>=8&&randomPassword.length()<=12){
            this.password = randomPassword;
        }
    }

잘못된 패스워드만을 return하거나 올바른 패스워드만을 return하는 테스트 전용 클래스를 두 개 만들어서

package org.ict.ooppractice;

public class WrongFixedPasswordGenerator implements PasswordGenerator {

    @Override
    public String generatePassword() {
        return "aa";
    }
}

랜덤한 결과를 없앨 수 있다.

또는 @FunctionalInterface 어노테이션을 PasswordGenerator에 달아줌으로써

테스트용 클래스를 따로 생성하지 않고 테스트를 진행할 수 있다.

class UserTest {

    @DisplayName("패스워드를 초기화한다.")
    @Test
    void passwordTest() {
        //given
        User user = new User();

        //when
        user.initPassword(() -> "aabbccddee");

        //then
        assertThat(user.getPassword()).isNotNull();
    }

    @DisplayName("요구사항에 부합하지 않아 패스워드가 초기화되지 않는다.")
    @Test
    void passwordTest2() {
        //given
        User user = new User();

        //when
        user.initPassword(() -> "aab");

        //then
        assertThat(user.getPassword()).isNull();
    }


}

테스트를 진행하기 쉽게하기 위해 interface를 만듬으로서

User 클래스가 RandomPasswordGenerator를 임포트를 하지 않을 수 있었다. 서로의 결합도를 낮춘것이다. 

'국비지원교육 > Spring boot' 카테고리의 다른 글

리액트/ 스프링부트 연동하기  (0) 2024.05.16
Security - 2  (0) 2024.05.09
스프링부트 - Security  (0) 2024.05.08
정리 시작  (0) 2024.05.08
복사했습니다!