Java 어설션: 가정 테스트

JavaBeginner
지금 연습하기

소개

이 랩에서는 Java 의 어설션 (assertion) 에 대해 배우게 됩니다. 어설션을 생성하는 방법과 언제 사용해야 하는지 배우게 됩니다. 어설션은 코드에 대한 가정을 테스트하는 데 사용되며, 주로 소프트웨어의 테스트 단계에서 활용됩니다.

간단한 어설션 생성

숫자가 짝수인지 테스트하는 간단한 어설션을 만들어 보겠습니다. 숫자가 짝수라고 가정하고 짝수를 사용하여 어설션을 작성합니다. 그런 다음 숫자를 변경하고 코드를 실행합니다. AssertionError가 발생해야 합니다.

public class AssertionsLab {
    public static void main(String[] args) {
        int number = 4;
        assert (number % 2) == 0;
        System.out.println("Number is even");

        // change the value of number variable to odd
        number = 3;
        assert (number % 2) == 0;
        System.out.println("Number is even");
    }
}

어설션 비활성화

기본적으로 Java 에서 어설션은 비활성화되어 있습니다. 명령줄 옵션을 사용하여 어설션을 활성화할 수 있습니다.

-ea 옵션을 사용하여 어설션을 활성화하고 코드를 실행해 보겠습니다.

java -ea AssertionsLab

코드는 "Number is even"을 출력한 다음 AssertionError를 출력해야 합니다.

이제 -da 옵션을 사용하여 어설션을 비활성화하고 코드를 다시 실행해 보겠습니다.

java -da AssertionsLab

코드는 예외를 발생시키지 않고 "Number is even"을 두 번 출력해야 합니다.

어설션을 사용한 입력값 테스트 방법

어설션은 메서드에 대한 입력을 테스트하는 데에도 사용할 수 있습니다. 두 개의 매개변수를 받아 첫 번째 매개변수를 두 번째 매개변수로 나눈 몫을 반환하는 divide 메서드를 만들어 보겠습니다. 두 번째 매개변수가 0 이 아니라고 가정하고 이를 확인하기 위해 어설션을 생성합니다.

public class AssertionsLab {
    public static void main(String[] args) {
        int a = 10;
        int b = 5;
        int result = divide(a, b);
        System.out.println("Result: " + result);

        // change the value of b to zero
        b = 0;
        result = divide(a, b);
        System.out.println("Result: " + result);
    }

    private static int divide(int a, int b) {
        assert b != 0 : "Cannot divide by zero";
        return a / b;
    }
}

디버깅 및 테스트를 위한 어설션 사용법

디버깅 및 테스트를 위해 어설션을 사용할 수 있습니다. 파일을 읽고 첫 번째 0 이 아닌 숫자를 반환하는 프로그램이 있다고 가정해 보겠습니다. 이 프로그램을 테스트하기 위해 세 개의 숫자가 있는 입력 파일을 만들어 보겠습니다.

echo "0\n3\n0" > input.txt

파일을 읽고 첫 번째 0 이 아닌 숫자를 반환하는 프로그램을 작성해 보겠습니다. 그런 다음 프로그램이 올바른 출력을 반환하는지 테스트하기 위해 어설션을 생성합니다.

import java.io.File;
import java.io.FileNotFoundException;
+ import java.util.Scanner;

public class AssertionsLab {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(new File("input.txt"));
        int number = 0;
        while (scanner.hasNext()) {
            number = scanner.nextInt();
            if (number != 0) {
                break;
            }
        }
        assert number == 3 : "Incorrect number read from file";
        System.out.println("First non-zero number: " + number);
    }
}

어설션을 사용하지 말아야 할 경우

어설션은 public 메서드의 인수를 검증하는 데 적합하지 않습니다. 이러한 어설션은 런타임 중에 비활성화될 수 있으며, 이는 예기치 않은 동작으로 이어질 수 있습니다.

public class AssertionsLab {
    public static void main(String[] args) {
        int negativeNumber = -1;
        printPositiveNumber(negativeNumber);
    }

    public static void printPositiveNumber(int number) {
        assert (number > 0) : "Not a valid positive number";
        System.out.println("Positive number: " + number);
    }
}

어설션을 유용하게 만들기

어설션에 정보 메시지를 추가하여 더 많은 정보를 제공하고 실패 시 더 나은 피드백을 제공할 수 있습니다. 이제 이전 코드의 어설션을 수정하여 정보 메시지를 포함시키겠습니다.

public class AssertionsLab {
    public static void main(String[] args) {
        int number = -1;
        assert (number > 0) : "Negative number found";
        System.out.println("Number is positive: " + number);
    }
}

"Negative number found" 메시지는 코드가 실행될 때 표시됩니다.

어설션으로 코드 손상 방지

어설션의 목적은 일반적으로 소프트웨어 테스트 시 버그를 찾는 것입니다. 그러나 어설션 자체가 코드를 손상시키는 경우 문제가 발생합니다. 예를 들어, 일시적인 네트워크 오류나 시스템의 타이밍 문제로 인해 어설션이 실패할 수 있습니다. 또한, public 메서드의 입력을 검증하기 위해 어설션을 사용하는 경우, 유효하지 않거나 악의적인 입력으로부터 시스템을 보호하지 못할 위험이 있습니다.

어설션의 부정적인 영향을 피하는 한 가지 방법은 신중하게 사용하는 것입니다. 잘 설계된 시스템에서 절대 발생하지 않아야 하는 상황에만 어설션을 사용하십시오.

public class AssertionsLab {
    public static void main(String[] args) {
        double result = squareRoot(4);
        System.out.println("Square root: " + result);

        double negativeNumber = -4;
        result = squareRoot(negativeNumber);
        System.out.println("Square root: " + result);
    }

    public static double squareRoot(double number) {
        assert number >= 0 : "Number should be non-negative";
        return Math.sqrt(number);
    }
}

사이드 이펙트 (Side Effect) 방지

어설션을 사용하는 동안 부작용을 피하는 것이 중요합니다. 어설션 내에서 변수를 변경하는 것을 피해야 합니다. 대신, 표현식을 사용하여 문제가 있는 상황을 감지하고 더 많은 진단 정보를 제공해야 합니다.

public class AssertionsLab {
    public static void main(String[] args) {
        int firstNumber = 1;
        int secondNumber = 2;
        assert (firstNumber = secondNumber) == 0 : "Values are not equal";
        System.out.println("Values are equal");
    }
}

어설션 (Assertion) 을 사용한 Switch 문 검사 방법

어설션을 사용하여 switch 문의 모든 가능한 케이스가 처리되었는지 확인할 수 있습니다. 숫자를 기반으로 요일 이름을 반환하는 switch 문을 만들어 보겠습니다. 숫자가 0 에서 6 사이의 범위에 있다고 가정하고 이를 확인하기 위한 어설션을 생성합니다.

public class AssertionsLab {
    public static void main(String[] args) {
        int dayNumber = 2;
        String day = getDayName(dayNumber);
        System.out.println("Day: " + day);

        // set dayNumber to an invalid number
        dayNumber = 10;
        day = getDayName(dayNumber);
        System.out.println("Day: " + day);
    }

    public static String getDayName(int dayNumber) {
        String day;
        switch (dayNumber) {
            case 0:
                day = "Sunday";
                break;
            case 1:
                day = "Monday";
                break;
            case 2:
                day = "Tuesday";
                break;
            case 3:
                day = "Wednesday";
                break;
            case 4:
                day = "Thursday";
                break;
            case 5:
                day = "Friday";
                break;
            case 6:
                day = "Saturday";
                break;
            default:
                assert false : "Invalid day number";
        }
        return day;
    }
}

요약

축하합니다! Java 어설션 랩을 완료했습니다. LabEx 에서 더 많은 랩을 연습하여 기술을 향상시킬 수 있습니다.