본문 바로가기

TDD이론과연습&리팩토링

자바 플레이그라운드 with TDD, 클린코드 학습테스트

728x90
반응형

목차

     

    String 클래스에 대한 학습 테스트

    샘플 코드 참고

    • src/test/java 폴더의 study.StringTest 클래스의 replace() 메서드를 실행해 테스트가 가능한지 확인한다.
    package study;
    
    import org.junit.jupiter.api.Test;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    public class StringTest {
        @Test
        void replace() {
            String actual = "abc".replace("b", "d");
            assertThat(actual).isEqualTo("adc");
        }
    }

     

     

    요구사항 1

    • "1,2"을 ,로 split 했을 때 1과 2로 잘 분리되는지 확인하는 학습 테스트를 구현한다.
    • "1"을 ,로 split 했을 때 1만을 포함하는 배열이 반환되는지에 대한 학습 테스트를 구현한다.

    힌트

    • 배열로 반환하는 값의 경우 assertj의 contains()를 활용해 반환 값이 맞는지 검증한다.
    • 배열로 반환하는 값의 경우 assertj의 containsExactly()를 활용해 반환 값이 맞는지 검증한다.

    테스트코드

     @Test
    void split() {
        String[] arr = "1,2".split(",");
        assertThat(arr).containsExactly("1","2");
    
    }
    
    @Test
    void split2() {
        String[] arr = "1".split(",");
        assertThat(arr).contains("1");
    }

     

    • contains() 의 경우에는 set, List, String, Array 모두 사용이 가능하다.
    • containsExactly()는 포함하는 지 체크하는데 순서를 포함해서 정확히 일치하는지 체크한다. 

     

     

    요구사항 2

    • "(1,2)" 값이 주어졌을 때 String의 substring() 메소드를 활용해 ()을 제거하고 "1,2"를 반환하도록 구현한다.

    테스트코드

     @Test
    void subString() {
        String actual = "(1,2)".substring(1,4);
        assertThat(actual).isEqualTo("1,2");
    }

     

     

    요구사항 3

    • "abc" 값이 주어졌을 때 String의 charAt() 메소드를 활용해 특정 위치의 문자를 가져오는 학습 테스트를 구현한다.
    • String의 charAt() 메소드를 활용해 특정 위치의 문자를 가져올 때 위치 값을 벗어나면 StringIndexOutOfBoundsException이 발생하는 부분에 대한 학습 테스트를 구현한다.
    • JUnit의 @DisplayName을 활용해 테스트 메소드의 의도를 드러낸다.

    테스트코드

    @Test
    @DisplayName("특정 문자 가져오기")
    void charAt() {
        String str = "abc";
        char a = str.charAt(0);
        assertThat(a).isEqualTo('a');
    }
    
    @Test
    @DisplayName("예외 발생 테스트")
    void charAtException() {
    
        String str = "abc";
        int index = 10;
    
        assertThatThrownBy(()->{
          str.charAt(index);
        }).isInstanceOf(StringIndexOutOfBoundsException.class)
            .hasMessageContaining("String index out of range: %d", index);
    
    }
    • assertThatThrownBy() -> 예외처리를 가독성있게 테스트할 수 있음 
    assertThatThrownBy(() -> {
    	throw new Exception("boom!");
    }).isInstanceOf(Exception.class).hasMessageContaining("boom");

    AssertJ에서 자주 발생하는 예외들에 대해 함수가 정의되어있다.

    • assertThatNullPointerException
    • assertThatIllegalArgumentException
    • assertThatIllegalStateException
    • assertThatIOException

    Set Collection에 대한 학습 테스트

    • 다음과 같은 Set 데이터가 주어졌을 때 요구사항을 만족해야 한다.
    public class SetTest {
        private Set<Integer> numbers;
    
        @BeforeEach
        void setUp() {
            numbers = new HashSet<>();
            numbers.add(1);
            numbers.add(1);
            numbers.add(2);
            numbers.add(3);
        }
        
        // Test Case 구현
    }

     

     

    요구사항 1

    • Set의 size() 메소드를 활용해 Set의 크기를 확인하는 학습테스트를 구현한다.

    테스트코드

      @Test
      @DisplayName("Set Size 구하기")
      void size() {
        int size = numbers.size();
        assertThat(size).isEqualTo(3);
      }

    Set은 중복허용이 안되므로 사이즈는 3으로 체크해야 한다. 

     

    요구사항 2

    • Set의 contains() 메소드를 활용해 1, 2, 3의 값이 존재하는지를 확인하는 학습테스트를 구현하려한다.
    • 구현하고 보니 다음과 같이 중복 코드가 계속해서 발생한다.
    • JUnit의 ParameterizedTest를 활용해 중복 코드를 제거해 본다.
        @Test
        void contains() {
            assertThat(numbers.contains(1)).isTrue();
            assertThat(numbers.contains(2)).isTrue();
            assertThat(numbers.contains(3)).isTrue();
        }

    테스트코드

     @ParameterizedTest
    @ValueSource(ints = {1,2,3})
    @DisplayName("중복 코드 제거 - 내부값 존재하는지 확인")
    void contains(int nums) {
    	assertThat(numbers).contains(nums);
    }
    • ParameterizedTest - 여러 argument를 이용해 테스트를 여러번 진행할 수 있는 기능이다
    • @Test대신 @ParameterizedTest를 사용한다.
    • @ValueSource를 이용해 argument를 전달할 수 있다.
    • short, byte, int, long, float, double, char, boolean, string에 사용가능하다.

     

     요구사항3

    • 요구사항 2는 contains 메소드 결과 값이 true인 경우만 테스트 가능하다. 입력 값에 따라 결과 값이 다른 경우에 대한 테스트도 가능하도록 구현한다.
    • 예를 들어 1, 2, 3 값은 contains 메소드 실행결과 true, 4, 5 값을 넣으면 false 가 반환되는 테스트를 하나의 Test Case로 구현한다.

    힌트

    @ParameterizedTest
    @CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter = ':')
    void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
        String actualValue = input.toLowerCase();
        assertEquals(expected, actualValue);
    }

    테스트코드

      @ParameterizedTest
      @CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':')
      @DisplayName("메소드 결과값이 다른 경우 테스트")
      void csvSourceTest(int input, boolean excepted) {
        boolean result = numbers.contains(input);
        assertThat(result).isEqualTo(excepted);
      }
    728x90
    반응형