Java アサーション:前提条件のテスト

JavaJavaBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Java におけるアサーションについて学びます。アサーションを作成する方法と、それを使用するタイミングについて学びます。アサーションは、コードに関する仮定をテストするために使用され、主にソフトウェアのテスト段階で利用されます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/FileandIOManagementGroup(["File and I/O Management"]) java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java/BasicSyntaxGroup -.-> java/operators("Operators") java/BasicSyntaxGroup -.-> java/variables("Variables") java/BasicSyntaxGroup -.-> java/switch("Switch") java/BasicSyntaxGroup -.-> java/output("Output") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/user_input("User Input") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("Exceptions") java/FileandIOManagementGroup -.-> java/files("Files") java/SystemandDataProcessingGroup -.-> java/math_methods("Math Methods") java/SystemandDataProcessingGroup -.-> java/system_methods("System Methods") subgraph Lab Skills java/operators -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/variables -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/switch -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/output -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/user_input -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/exceptions -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/files -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/math_methods -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} java/system_methods -.-> lab-117470{{"Java アサーション:前提条件のテスト"}} end

単純なアサーションの作成

数値が偶数であるかどうかをテストする単純なアサーションを作成しましょう。数値が偶数であると仮定し、偶数を使用してアサーションを記述します。その後、数値を変更してコードを実行します。AssertionError が発生するはずです。

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

        // number 変数の値を奇数に変更する
        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」を2回表示するはずです。

入力をテストするためのアサーションの使用

アサーションは、メソッドの入力をテストするためにも使用できます。2つのパラメータを受け取り、最初のパラメータを2番目のパラメータで割った後の商を返す divide メソッドを作成しましょう。2番目のパラメータがゼロでないと仮定し、それをチェックするためのアサーションを作成します。

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);

        // b の値をゼロに変更する
        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;
    }
}

デバッグとテストにおけるアサーションの使用

デバッグとテストにアサーションを使用することができます。ファイルを読み取り、その中から最初のゼロでない数値を返すプログラムがあるとしましょう。このプログラムをテストするために、3つの数値を含む入力ファイルを作成しましょう。

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

ファイルを読み取り、その中から最初のゼロでない数値を返すプログラムを書きましょう。その後、プログラムが正しい出力を返すかどうかをテストするためのアサーションを作成します。

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 メソッドの入力を検証するためにアサーションを使用すると、無効な入力や悪意のある入力に対してシステムが保護されていないリスクがあります。

アサーションのマイナスな影響を回避する1つの方法は、適切に使用することです。設計が良好なシステムでは決して起こらないことにのみアサーションを使用します。

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);
    }
}

副作用の回避

アサーションを使用する際には、副作用を回避することが重要です。アサーション内で変数を変更することを避ける必要があります。代わりに、式を使用して問題のある状況を検出し、より診断情報を提供する必要があります。

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");
    }
}

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 でさらに多くの実験を行って練習してください。