study/JUnit

[sailor-moon] 2024.09.24_JUnit : 각도기, 숫자 비교

듀2 2024. 9. 24. 16:48

* 프로그래머스 입문 문제 중 선택하여 코드 작성 후 테스트 코드 작성

 

1. 각도기

 

* 코드 작성 전 테스트 조건

  1. 매개변수 angle이 숫자인지 확인
  2. angle이 각의 범위인지 확인(0도 초과 180도 이하)
  3. 예각의 범위인지 확인(0도 초과 90도 미만)
  4. 직각의 범위인지 확인(90도)
  5. 둔각의 범위인지 확인(90도 초과 180도 미만
  6. 평각의 범위인지 확인(180도)
  7. angle이 각의 범위가 아닐 때 예외 처리가 되었는지 확인
  8. angle이 숫자가 아닐 때 예외 처리가 되었는지 확인
  • 정수인지도 테스트가 필요할까?
  • 제한사항에 걸려있는 것은 테스트가 필요할까?

→ 매개변수가 int 값이라면 숫자인지, 정수인지 테스트 불필요 / 만약 매개변수가 String으로 주어질 경우 테스트 필요

→ 제한사항에 걸려있는 것 중 angle의 범위는 테스트 필요

 

* 작성 코드

package jh.day0924;

public class Angle {

    public int checkAngle(int angle) {
        if(angle > 0 && angle < 90) {
            return 1;
        } else if(angle == 90) {
            return 2;
        } else if(angle > 90 && angle < 180) {
            return 3;
        } else if(angle == 180) {
            return 4;
        } else {
            throw new IllegalArgumentException("입력값은 0 초과 180 미만이어야 합니다.");
        } // end else
    } // checkAngle

} // class

 

* 테스트 코드

package jh.day0924;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@DisplayName("각도기 테스트")
public class AngleTest {

    private Angle angle;
    
    @BeforeEach
    void createInstance() { angle = new Angle(); } // createInstance
    
    @Test
    @DisplayName("예각 확인")
    void testAcute() {
        assertThat(angle.checkAngle(1)).isEqualTo(1);
        assertThat(angle.checkAngle(89)).isEqualTo(1);
        // assertThat(angle.checkAngle(0)).isEqualTo(1);
        // assertThat(angle.checkAngle(90)).isEqualTo(1);
    } // testAcute
    
    @Test
    @DisplayName("직각 확인")
    void testRight() {
        assertThat(angle.checkAngle(90)).isEqualTo(2);
    } // testRight
    
    @Test
    @DisplayName("둔각 확인")
    void testObtuse() {
        assertThat(angle.checkAngle(91)).isEqualTo(3);
        assertThat(angle.checkAngle(179)).isEqualTo(3);
        // assertThat(angle.checkAngle(90)).isEqualTo(3);
        // assertThat(angle.checkAngle(180)).isEqualTo(3);
    } // testObtuse
    
    @Test
    @DisplayName("평각 확인")
    void testSquare() {
        assertThat(angle.checkAngle(180)).isEqualTo(4);
    } // testSquare
    
    @Test
    @DisplayName("예외 확인")
    void testException() {
        assertThatThrownBy(() -> angle.checkAngle(0))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("입력값은 0 초과 180 미만이어야 합니다.");
        assertThatThrownBy(() -> angle.checkAngle(181))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("입력값은 0 초과 180 미만이어야 합니다.");
    } // testException

} // class

 

테스트 조건은 입력값, 반환값을 고려하여 작성하기.
그렇지 않았더니 테스트 코드 작성 시 반환값과 비교하지 않고 범위와 비교하는 상황이 발생!

 

2. 숫자 비교

 

* 코드 작성 전 테스트 조건

  1. num1 num2 같으면 1 반환
  2. num1 num2 다르면 -1 반환

* 작성 코드

package jh.day0924;

public class CompareNumber {

    public int compareNumber(int num1, int num2) {
        if((num1 < 0 || num1 > 10000) || (num2 < 0 || num2 > 10000)) {
            throw new IllegalArgumentException("입력값은 0 이상 10000 이하의 값이어야 합니다.");
        } // end if
        if(num1 == num2) {
            return 1;
        } else {
            return -1;
        } // ene else
    } // compareNumber
    
} // class

 

* 테스트 코드

package jh.day0924;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@DisplayName("숫자 비교 테스트")
public class CompareNumberTest {

    private CompareNumber compareNumber;
    
    @BeforeEach
    void createInstance() {
        compareNumber = new CompareNumber();
    } // createInstance
    
    @Test
    @DisplayName("같은지 확인")
    void isEqual() {
        assertThat(compareNumber.compareNumber(0, 0)).isEqualTo(1);
        assertThat(compareNumber.compareNumber(10000, 10000)).isEqualTo(1);
    } // isEqual
    
    @Test
    @DisplayName("다른지 확인")
    void isNotEqual() {
        assertThat(compareNumber.compareNumber(0, 10000)).isEqualTo(-1);
        assertThat(compareNumber.compareNumber(10000, 0)).isEqualTo(-1);
    } // isNotEqual
    
    @Test
    @DisplayName("예외 확인")
    void testException() {
        assertThatThrownBy(() -> compareNumber.compareNumber(-1, 10001))
                .isInstanceOf(IllegalArgumentException.class);
        assertThatThrownBy(() -> compareNumber.compareNumber(10001, -1))
                .isInstanceOf(IllegalArgumentException.class);
        assertThatThrownBy(() -> compareNumber.compareNumber(-1, 10000))
                .isInstanceOf(IllegalArgumentException.class);
        assertThatThrownBy(() -> compareNumber.compareNumber(10000, -1))
                .isInstanceOf(IllegalArgumentException.class);
    } // testException
    
} // class

 

예외 테스트 시 assertThatThrownBy를 사용할 때 람다식을 사용하여 여러 케이스를 테스트했더니 케이스 중 한 가지에서 예외가 터지면 테스트가 성공한 것으로 확인됨.
→ 테스트 케이스 별로 각각 한 개씩 테스트 해주어야겠다.

 

* 그 외 배운 점

- assertThat의 경우 기본 assertions와 다르게 기대값과 실제값의 위치가 반대. 가독성 좋은 장점을 살려 읽히는 대로 비교해주면 된다.

- 매개변수가 String일 때 parseInt()를 적용하여 숫자에 대한 예외처리도 해보면 좋겠다.

- 예외처리 테스트를 할 때 각 예외가 어떤 예외에 해당하는지 바로바로 떠오르지 않았다. 예외처리에 대해서도 공부가 필요하다.

728x90