チャットbotお試し用アプリ開発_10日目


# 目次

・本日の成果・考え
・最後に

### 本日の成果
では、前回できなかったSettingLoaderのテストに移ります。
まずは、テスト対象のSettingLoaderのソースです。

``` SettingLoader.java
package app.windowView.config;

import java.util.Properties;

import app.util.CommonFunction;

public class SettingLoader {

	/**
	 * 読み込んだプロパティからDTOを生成し、Factoryに登録する
	 * @param props　呼び出し元で生成したPropertiesオブジェクト
	 * @return void
	 */
	public static void startSettings(Properties props,AppSettingFactory fact) {
		int windWidth;
		int windHeight;
		if (props == null) {
			throw new IllegalStateException("設定ファイルが読み込まれていません。");
		}
		String logPath = props.getProperty("LOGPATH");
		String logFileExtension = props.getProperty("LOGFILEEX");
		String title = props.getProperty("WINDOW_TITLE");
		String windUrl = props.getProperty("WINDOW_URL");
		
		//int型の引数の整数チェック。整数以外はNG。設定値が取得できなかった場合も例外。
		try {
			String windWidthStr = props.getProperty("WINDOW_WIDTH");
			String windHeightStr = props.getProperty("WINDOW_HEIGHT");
			windWidth = Integer.parseInt(windWidthStr);
			windHeight = Integer.parseInt(windHeightStr);
		} catch (NullPointerException | NumberFormatException e) {
			throw new IllegalStateException("設定ファイルのint型の項目に問題があります。：" + e);
		}

		//引数のNULLおよび空白チェック。int型は呼び出し元のLoaderクラスのメソッドでint型と制限しているのでnull混入はコンパイルで弾ける。
		//例外キャッチは呼び出し元。
		CommonFunction.checkNullBlank(logPath, logFileExtension, title, windUrl);

		fact.createInstance(logPath, logFileExtension, title, windUrl, windWidth, windHeight);
	}
}

```
::: note info
取得した設定値は一度変数に格納した上で、FactoryクラスのcreateInstanceメソッドに渡しています。
また、以前作成したNull,空白チェックの共通関数を使ってチェックと整数に関してint型の変数に格納する処理をTry-catchで例外がないか監視しています。
:::

#### テストパターン
1. 正常系　全ての項目が正しく設定されDTOが正しく生成される
※DTOの中身まで確認します。
1. 正常系　int型の設定値の前後に半角の空白が含まれていても正常に処理を実行できる
**以下全て異常系**
1. プロパティオブジェクトがNULLの場合、エラーとなる
1. 「WINDOW_WIDTH」がNULLの場合、エラーとなる
1. 「WINDOW_WIDTH」が空白の場合、エラーとなる
※空白は半角でテストします。全角の時点で文字列扱いのため。
1. 「WINDOW_WIDTH」が少数の場合、エラーとなる
1. 「WINDOW_WIDTH」が文字列の場合、エラーとなる
1. 「WINDOW_WIDTH」が全角数字の場合、エラーとなる
1. 「WINDOW_HEIGHT」がNULLの場合、エラーとなる
1. 「WINDOW_HEIGHT」が空白の場合、エラーとなる
1. 「WINDOW_HEIGHT」が少数の場合、エラーとなる
1. 「WINDOW_HEIGHT」が文字列の場合、エラーとなる
1. 「WINDOW_HEIGHT」が全角数字の場合、エラーとなる
1. 「logPath」「logFileExtension」「title」「windUrl」のいずれかがnullまたは空白の場合、エラーとなる
※共通関数のNullまたは空白チェックをSettingLoaderクラスで呼び出すのみのため、全てのパターンのチェックは省略する。


::: note info
引数ごとのテストパターンは数が多くて骨が折れますね。しかし、ここ以外で確認することはほとんどないので、やってしまおうと思います。
:::

ではテストソースですが、正常系と異常系をひとつずづあげます。
※パターン多すぎて、全部で800行近いソースになってしまいました。

``` SettingLoader.java
public class SettingLoaderTest {

	//プロパティファイルのオブジェクト
	private Properties testProps;
	AppSettingFactory testFact = new AppSettingFactory();
	/*
	* 設定ファイルのプロパティオブジェクトの初期化メソッド。
	*/
	private void setUp() {
		try {
			//正常系のみで使用する。
			testProps = CommonFunction.load("/resources/app.properties");
		} catch (IOException e) {
			fail("設定ファイルの読み込みに失敗しました: " + e.getMessage());
		}
	}
	/**
	 *テストパターン　正常系　全ての項目が正しく設定され、DTOが正しく生成される。 
	 */
	@Test
	public void test1_1() {
		String className = new Object() {
		}.getClass().getName();
		String resultOutput = className + "のテストパターン1_2";
        setUp();

		try {
			out.println("**********************************************");
			out.println(resultOutput + "が開始されました。");
			SettingLoader.startSettings(testProps, testFact);
			AppSettingDto test1 = testFact.getInstance();

			// プロパティオブジェクトの内容チェック
			out.println("logPath: " + test1.getLogPath());
			out.println("logFileExtension: " + test1.getLogFileExtensionString());
			out.println("title: " + test1.getTitle());
			out.println("windUrl: " + test1.getWindUrl());
			out.println("windWidth: " + test1.getWindWidth());
			out.println("windHeight: " + test1.getWindHeight());

			//　app.propertiesの中身と同等かチェック。
			assertEquals("testLogPath", test1.getLogPath());
			assertEquals(".log", test1.getLogFileExtensionString());
			assertEquals("チャットbot_Dify", test1.getTitle());
			assertEquals("https://example.com", test1.getWindUrl());
			assertEquals(800, test1.getWindWidth());
			assertEquals(800, test1.getWindHeight());

			out.println(resultOutput + "が正常終了しました。");

		} catch (Exception e) {
			String resultError = String.format("エラーが発生しました。内容は{%s}", e);
			out.println(resultError);

		} finally {
			out.println(resultOutput + "が終了しました。");
			out.println("**********************************************");
		}
	}

    /**
	 *テストパターン　異常系　「WINDOW_WIDTH」がNULLの場合、エラーとなる
	 */
	@Test
	public void test3_1() {
		String className = new Object() {
		}.getClass().getName();
		String resultOutput = className + "のテストパターン3_1";

		try {
			out.println("**********************************************");
			out.println(resultOutput + "が開始されました。");
            setUp();

			//「WINDOW_WIDTH」にNULLをセット。
			testProps.setProperty("WINDOW_WIDTH", null);

			SettingLoader.startSettings(testProps, testFact);
			AppSettingDto test1 = testFact.getInstance();

			// プロパティオブジェクトの内容チェック
			out.println("logPath: " + test1.getLogPath());
			out.println("logFileExtension: " + test1.getLogFileExtensionString());
			out.println("title: " + test1.getTitle());
			out.println("windUrl: " + test1.getWindUrl());
			out.println("windWidth: " + test1.getWindWidth());
			out.println("windHeight: " + test1.getWindHeight());

			//　app.propertiesの中身と同等かチェック。
			assertEquals("testLogPath", test1.getLogPath());
			assertEquals(".log", test1.getLogFileExtensionString());
			assertEquals("チャットbot_Dify", test1.getTitle());
			assertEquals("https://example.com", test1.getWindUrl());
			assertEquals(800, test1.getWindWidth());
			assertEquals(800, test1.getWindHeight());

			out.println(resultOutput + "が正常終了しました。");

		} catch (Exception e) {
			String resultError = String.format("エラーが発生しました。内容は{%s}", e);
			out.println(resultError);

		} finally {
			out.println(resultOutput + "が終了しました。");
			out.println("**********************************************");
		}
	}

```
テストを実行した結果ですが、

![スクリーンショット 2025-06-23 21.25.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3338426/6a2b7592-9ec0-4a75-81a2-ed232568c2cf.png)

テストパターンで
「「WINDOW_WIDTH」が全角数字の場合、エラーとなる」
としていたのですが、エラーになっていません。

以下のようにわかりやすく出力するようにしています。
```　工夫箇所.java
//「WINDOW_WIDTH」に少数の値をセット。
			testProps.setProperty("WINDOW_WIDTH", "８００");
			out.println("セットした値" + testProps.getProperty("WINDOW_WIDTH"));

//結果
セットした値８００
```
:::note warn
プロパティの設定値は確実に全角の800になっているのに、帰ってきたら半角になっています。
気になって調べてみましたが、Javaが全角も許容しているみたいでした。
:::

https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Character.html#digit(char,int)

というわけで、テストパターンの内容を全角の箇所を異常系→正常系とすることにしました。

前のテストは確認していませんでしたが、
![スクリーンショット 2025-06-23 21.45.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3338426/ece34e0c-b95e-4b57-b74a-38674fb7e6ba.png)

::: note info
SettingLoaderのカバレッジは96.4%で、ほぼ全て網羅しているといえそうです。
:::
### 最後に
テストの内容とは関係ないですが、このテスト実行中にEclipseのビルドがフリーズしてしまって、画面上のテストソースと実行される内容が違うということが発生しました。
PCごと再起動するとビルドパスの問題が発生していたんですが、すでに存在しない内容だったので困りました。既存のパスを削除して、再度のパス設定＋自動ビルドのON/OFFの切り替えでなんとかなりました。
今日の振り返りは、Integer.parseIntは全角もOKという点が学びでした。
あとは、詳細は省きますが、処理の実行方法を明確にイメージできていなかったので、各クラスの修飾子を基本的にパッケージプライベートにしたせいで、テストできないなどもありました。
例えばDtoクラス自体をパッケージプライベートにしたせいで、生成したオブジェクトを格納する箱がないということになり、急遽修正しました。

ここまでお付き合いありがとうございました。