17. フロー部品のテスト

このチュートリアルでは、フロー部品をはじめとするデータフローのテストを作成する方法を説明していきます。

17.1. データフローのテスト

Flow DSLで記述したフロー部品やジョブフローなどのクラスは、通常のJavaクラスとしてはテストすることができません。 Flow DSLは単体では動作せず、実行可能なバッチアプリケーションを生成した上でテストを行う必要があるためです。

また、データフローに対するテストデータを実行プログラムが規定する方法で配置する必要があるため、そのままでは自動テストを行うことが困難です。

このためAsakusa Frameworkはテストの実行に必要な一連の処理を自動的に行う テストドライバー というモジュールを提供しています。

テストドライバーはテスト対象の要素に対して、次の一連の処理を行います。

  1. テストデータの定義に従って入力データを配置する
  2. 対象のプログラムをコンパイルして実行可能なバッチアプリケーションを生成する
  3. バッチアプリケーションを実行する
  4. テストデータの定義に従って出力結果と期待データを検証する

なおテストドライバーの実行には、テスト実行環境に対して Asakusa Frameworkのインストール が必要です。

17.2. テストデータの準備

テストドライバーでのテストを行うには、次の3種類の情報を用意します。

入力データ
それぞれのデータフローの入力に指定するデータセット。
期待データ
それぞれのデータフローからの出力に期待するデータセット。
出力の検証方法
それぞれの出力と期待データを比較して間違いを見つける方法。

ここでは、これらをまとめて テストデータ と呼ぶことにします。

テストデータはExcel形式, JSON形式, Javaプログラムなど様々な方法で定義することができますが、 ここでは理解しやすいExcel形式でテストデータを作成していきます。

Excelが用意できない環境では、このチュートリアルの 終わりに からテストデータを作成済みのExcelファイルをダウンロードできるのでそれを利用してください。 なおテストの実行はExcelがインストールされていないマシン上でも行うことができます。

17.3. テストデータテンプレートを生成する

Excel形式でテストデータを作成する場合、DMDLスクリプトで記述したデータモデルの定義からテストデータ用のExcelファイルのテンプレートを自動生成して利用することができます。

ここではテストデータテンプレートに対してテストデータを定義していきます。

17.3.1. Eclipse上でテストデータテンプレートを生成

Shafuを導入したEclipse環境では、コンテキストメニューから Jinrikisha (人力車) ‣ テストデータ・テンプレートを生成 を選択します。

_images/shafu-generate-testbook.png

17.3.2. コマンドライン上でテストデータテンプレートを生成

コマンドライン上からテストデータテンプレートを生成する場合は、Gradleの generateTestbook タスクを実行します。

./gradlew generateTestbook

17.3.3. テストデータテンプレート

テストデータテンプレートを生成するとプロジェクトのビルドフォルダ build/excel 以下に、データモデルごとにExcelファイルが生成されます。

このチュートリアルではDMDLスクリプト src/main/dmdl/models.dmdl のデータモデル定義に基づいて、以下のファイルが作られます。

  • sales_detail.xls
  • store_info.xls
  • item_info.xls
  • category_summary.xls
  • error_record.xls
  • joined_sales_info.xls

これらのExeclブックには以下の3種類のシートが含まれています。

入力データシート

入力データを定義するシート。 初期状態では input というシート名で作成されています。

入力データシートはレコードを各行で表し、各列にヘッダに指定したプロパティ値を定義します。 テンプレートの初期状態は空データ(ヘッダのみが記述されている)の状態です。

_images/testdata-excel-example-input.png

[入力データシートの定義例]

期待データシート
出力データに対する期待値を定義するシート。 初期状態では output というシート名で作成されています。 入力データシートと同じ形式を持ちます。
比較条件シート

出力結果データと期待データの比較条件を定義するシート。 初期状態では rule というシート名で作成されています。

全体的な比較の方針や、それぞれのプロパティをどのように比較するかをドロップダウン形式で選択します。

_images/testdata-excel-example-rule.png

[比較条件シートの定義例]

17.4. テストデータの構成を定義する

テストデータテンプレートからテストデータを作成する際には、ファイル名やファイルに含めるシートの構造は任意に変更することができます。 たとえば複数のデータモデルを表す入力データシートを1つのファイルにまとめたり、テストケースごとに各データモデルのテストデータを1ファイルにまとめる、といった使い方が可能です。

このチュートリアルでは、以下の2種類の構成でテストデータを作成することにします。

17.4.1. 共通マスタ

すべてのテストケースで利用する共通のマスタデータを定義します。 このテストデータには以下のシートを含めます。

  • store_info : 店舗マスタの入力データシート。テストデータテンプレートファイル store_info.xlsinput シートをベースとする。
  • item_info : 商品マスタの入力データシート。テストデータテンプレートファイル item_info.xlsinput シートをベースとする。

ここでは共通マスタのテストデータを masters.xls というファイルで作成します。 このシート構成を作成する手順の例を以下に示します。

  1. テストデータテンプレートファイル store_info.xls をコピーして masters.xls を作成する。
  2. masters.xls を開き、 シート名 inputstore_info に変更する。また output シートと rule シートは削除する。
  3. masters.xls を開いているExcel上から item_info.xls を開き、シート名 inputitem_info に変更する。
  4. item_info シートに対してコンテキストメニューから「移動またはコピー」を選択し masters.xls の末尾にコピーする。

17.4.2. テストケース

各テストケースごとに、入力データとなる売上明細、期待値となるカテゴリ別売上集計、検証ルールの3つの組み合わせをもつテストデータを定義します。 このテストデータには以下のシートを含めます。

  • sales_detail : 売上明細の入力データシート。テストデータテンプレートファイル sales_detail.xlsinput シートをベースとする
  • result : カテゴリ別売上集計の期待データシート。テストデータテンプレートファイル category_summary.xlsoutput シートをベースとする
  • result_rule : カテゴリ別売上集計の比較条件シート。テストデータテンプレートファイル category_summary.xlsrule シートをベースとする

ここでは最も単純なテストケースに対応するテストデータを simple.xls として作成します。 共通マスタ の例を参考にして simple.xls にシート構成を作成してください。

17.4.3. テストデータの配置

テストドライバーからテストデータを利用するにはプロジェクトのソースフォルダ src/test/resources 配下に、 テストデータを利用するテストクラスと同じパッケージかそのサブパッケージ上に配置します。

ここでは src/test/resources 配下にテストクラスと同じパッケージに対応するディレクトリ com/example/flowpart を作成し、 ここに テストデータの構成を定義する で作成したテストデータ masters.xlssimple.xls を配置します。

_images/testdata-excel-package-explorer.png

17.5. 入力データを定義する

配置したテストデータ masters.xlssimple.xls に対して入力データを定義していきます。

17.5.1. store_infoシート

まずは、 masters.xls のシート store_info に以下の店舗マスタのデータを定義します。

masters.xls - store_info
store_code store_name
0001 DUMMY
0002 DUMMY
0003 DUMMY
0004 DUMMY
0005 DUMMY
0006 DUMMY
0007 DUMMY
0008 DUMMY
0009 DUMMY
0010 DUMMY

文字列型のプロパティに対応するテストデータを入力する際には注意が必要です。

例えば上記のプロパティ store_code は文字列として定義する必要があるのですが、 Excelでは 0001 のように文字列をセルに入力した場合に、入力値に応じて数値や日付などの別の形式に変換されてしまう場合があります。 この場合 0001 は固定長の0埋め文字列として扱いたいのですが、数値の 1 として扱われてしまう恐れがあります。

テストドライバーではこのようなテスト時のミスを減らすため、文字列型のプロパティに対してExcel上で文字列型以外の値が入力されている場合、 テストが失敗するようになっています。

Excelのセルに対して入力値を強制的に文字列として扱うには、入力値の先頭に ' (シングルクウォート) を付与します。 このシングルクウォート記号は文字列に含まれず、以降の値が文字列として取り扱われます。

また、空のセルはテストドライバーでは NULL 値として取り扱われます。 長さ0の文字列を入力したい場合には ' のみを指定してください。

17.5.2. item_infoシート

続けて masters.xls のシート item_info に以下の商品マスタのデータを定義します。

masters.xls - item_info
item_code item_name category_code begin_date end_date
0001 dummy test1 1970/01/01 2031/01/01
0002 dummy test2 1970/01/01 2031/01/01
0003 dummy test1 1970/01/01 2031/01/01
0004 dummy test2 1970/01/01 2031/01/01
0005 dummy test1 1970/01/01 2031/01/01
0006 dummy test2 1970/01/01 2031/01/01
0007 dummy test1 1970/01/01 2031/01/01
0008 dummy test2 1970/01/01 2031/01/01
0009 dummy test1 1970/01/01 2031/01/01
0010 dummy test2 1970/01/01 2031/01/01
1001 dummy test3 2011/01/01 2011/02/01
1001 dummy test3 2011/02/01 2011/03/01
1001 dummy test3 2011/03/01 2011/04/01
1001 dummy test3 2011/04/01 2011/05/01
1001 dummy test3 2011/05/01 2011/06/01
1001 dummy test3 2011/06/01 2011/07/01
1001 dummy test3 2011/07/01 2011/08/01
1001 dummy test3 2011/08/01 2011/09/01
1001 dummy test3 2011/09/01 2011/10/01
1001 dummy test3 2011/10/01 2011/11/01

テストデータテンプレートの初期状態ではデータモデルがもつすべてのプロパティがヘッダとして定義されていますが、 テストの入力時に不要なプロパティがある場合、その列は削除してしまってかまいません。 削除した場合、すべてのレコードでそのプロパティは NULL として取り扱います。

ここでは上記に記載しているプロパティのみを入力し、その他のプロパティ列は削除してください。

17.5.3. sales_detailシート

最後に simple.xls のシート sales_detail に以下の売上明細のデータを定義します。

ここでは最も単純なテストケースとして定義するため、以下の1レコードのみを定義します。

simple.xls - item_info
sales_date_time store_code item_code amount selling_price
2011-01-01 00:00:00 0001 0001 1 100

item_info の場合と同様、上記に記載しているプロパティのみを入力し、その他のプロパティ列は削除してください。

17.6. 期待値を定義する

続けて simple.xls に対して期待値データを定義します。

17.6.1. resultシート

ここでは simple.xls の期待データシート result に期待値を記述していきます。 記述方法は 入力データを定義する と同様です。

ここでも、最も単純なテストケースとして定義するため、1レコードのみを定義します。

simple.xls - result
category_code amount_total selling_price_total
test1 1 100

17.7. 出力の検証方法を定義する

最後に simple.xls に対して比較検証ルールを定義します。

17.7.1. result_ruleシート

ここでは simple.xls の比較条件シート result_rule に検証ルールを設定していきます。 比較条件シートは、検証ルールの各項目をドロップダウン形式で選択することで設定していきます。

_images/testdata-excel-result-rule.png

17.7.1.1. 全体の比較

まず2行目の 全体の比較 を指定します。

ここではテストの実行結果として、期待値のみ存在するレコードや実際のテスト実行結果のみ存在するレコードがあった場合の動作を決定します。

_images/testdata-excel-whole-verify.png

ここでは すべてのデータを検査 を指定します。 このルールは期待値のみ存在するレコードがあった場合、および実際のテスト実行結果のみ存在するレコードがあった場合のどちらも比較失敗として扱います。

検査しない を選択した場合、レコードを一切比較しません。これはデータフロー実行の疎通確認を行いたい場合や、一時的に比較を行わない場合などに利用します。

17.7.1.2. 値の比較

4行以降では、データモデルの各プロパティに対する 値の比較 を指定します。

ここではテストの実行結果に対して、各データモデルをプロパティ単位でどのように比較するかを指定します。

_images/testdata-excel-property-verify.png

まず4行目の category_code には 検査キー を指定します。

検査キーは、期待データシートに定義した期待値と実際のテスト実行結果のレコードの突き合せに、データモデルのどのプロパティを使うかを指定します。

検査キーを指定したプロパティは キープロパティ と呼びます。キープロパティは複合キーとして、複数のプロパティを指定することもできます。

5行目の amount_total , および6行目の selling_price_total には 完全一致 を指定します。 完全一致は、プロパティの値が完全に同じ場合のみ比較成功とみなします。

17.8. フロー部品のテストクラスを作成する

テストデータを作成したら、これを使ってテストを実行するテストクラスを作成します。 フロー部品のテストも演算子と同様にJUnitを使ったテストクラスとして実装します。

テストクラスは演算子の場合と同様に、プロジェクトのソースフォルダ src/test/java 配下に任意のJavaパッケージ名とクラス名を持つクラスとして作成できます。 テスト対象のフロー部品クラスをベースにしたクラス名を指定すると便利でしょう。

ここでは、 フロー部品の作成 で作成したフロー部品クラス CategorySummaryFlowPart に対するテストクラスを以下のように作成します。

パッケージ名 com.example.flowpart
クラス名 CategorySummaryFlowPartTest
CategorySummaryFlowPartTest.java
package com.example.flowpart;

public class CategorySummaryFlowPartTest {

}

17.9. フロー部品のテストメソッドを作成する

各テストケースに対応するテストメソッドを作成していきます。 このチュートリアルで作成するテストクラスでは以下の構成でテストメソッドを作成します。

  • テストケース で作成するテストデータの単位でテストメソッドを作成する
  • テストメソッドでは使用するテストデータを指定するのみで、テスト実装は共通のプライベートメソッド run に記述する。

まず、テストケースに対応するテストメソッドを作成します。 このメソッドは run メソッドを呼ぶだけで、テストデータのExcelファイル名を渡すようにしました。

CategorySummaryFlowPartTest.java
@Test
public void simple() {
    run("simple.xls");
}

次にテスト実装の本体であるプライベートメソッド run を実装します。

CategorySummaryFlowPartTest.java
private void run(String dataSet) {

}

フロー部品をテストするには、まずテストドライバー用のAPIクラス FlowPartTester [1] をインスタンス化します。

CategorySummaryFlowPartTest.java
...
import com.asakusafw.testdriver.FlowPartTester;
...

private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

}

FlowPartTester をインスタンス化する際には、引数に getClass() を呼んでテストケース自身のクラスを引き渡します。 このクラス情報は配置したテストデータを検索するなどに利用します。

次に、このテストケースの入力データをデータモデルごとに指定します。 ここでは 入力データを定義する で定義した store_infoシート , item_infoシート , sales_detailシート の3つの入力データシートを指定します。

まず store_infoシート を指定します。

CategorySummaryFlowPartTest.java
...
import com.asakusafw.vocabulary.flow.In;
import com.example.modelgen.dmdl.model.StoreInfo;
...

private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

    In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
        .prepare("masters.xls#store_info");

}

テストで使用する入力データを指定するには、 FlowPartTester が持つ input メソッドを利用します。 この引数には第1引数に入力の名前、第2引数に入力のデータモデル型を指定します。 第1引数の名前は他の名前と重複せず、アルファベットや数字のみで構成して下さい

input に続けて、 prepare で入力データシートを指定します。 引数には テストデータの配置 で配置したテストデータを <Excelのファイル名>#<シート名> という形式で指定します。

prepare メソッドの戻り値は、 In<データモデル型> [2] の変数に保持します。 この入力オブジェクトはフロー部品の実行時に指定します。

同様にして item_infoシート , sales_detailシート を指定します。 sales_detailシート はテストケースごとに異なる値を使用するため、引数で受け取ったファイル名を指定します。

CategorySummaryFlowPartTest.java
private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

    In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
        .prepare("masters.xls#store_info");
    In<ItemInfo> itemInfo = tester.input("itemInfo", ItemInfo.class)
        .prepare("masters.xls#item_info");
    In<SalesDetail> salesDetail = tester.input("salesDetail", SalesDetail.class)
        .prepare(dataSet + "#sales_detail");

}

続けてこのテストケースの出力に対する期待値データと検証ルールをデータモデルごとに指定します。 ここでは 期待値を定義する で定義した resultシート出力の検証方法を定義する で定義した result_ruleシート を指定します。

CategorySummaryFlowPartTest.java
private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

    In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
        .prepare("masters.xls#store_info");
    In<ItemInfo> itemInfo = tester.input("itemInfo", ItemInfo.class)
        .prepare("masters.xls#item_info");
    In<SalesDetail> salesDetail = tester.input("salesDetail", SalesDetail.class)
        .prepare(dataSet + "#sales_detail");

    Out<CategorySummary> categorySummary = tester.output("categorySummary", CategorySummary.class)
        .verify(dataSet + "#result", dataSet + "#result_rule");

}

テストの出力に関するテストデータを定義するには、 FlowPartTester が持つ output メソッドを利用します。 引数の構成は input と同様です。

output に続けて、 verify で第1引数に期待値データ、第2引数で検証ルールをそれぞれ指定します。 引数の形式は prepare と同様です。 出力の定義結果は、 Out<データモデル型> [3] の変数に保存します。

エラー情報 ErrorRecord については検証を行わないので verify を呼ばす、 代わりに出力データをExcelファイルに出力するための dumpActual メソッドを利用します。 dumpActual は引数で指定したパスに実行結果を出力します。

CategorySummaryFlowPartTest.java
private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

    In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
        .prepare("masters.xls#store_info");
    In<ItemInfo> itemInfo = tester.input("itemInfo", ItemInfo.class)
        .prepare("masters.xls#item_info");
    In<SalesDetail> salesDetail = tester.input("salesDetail", SalesDetail.class)
        .prepare(dataSet + "#sales_detail");

    Out<CategorySummary> categorySummary = tester.output("categorySummary", CategorySummary.class)
        .verify(dataSet + "#result", dataSet + "#result_rule");
    Out<ErrorRecord> errorRecord = tester.output("errorRecord", ErrorRecord.class)
            .dumpActual("build/dump/error_" + dataSet);

}

テストデータの定義が終わったら、入力オブジェクトと出力オブジェクトを指定してフロー部品クラスをインスタンス化します。

CategorySummaryFlowPartTest.java
private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

    In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
        .prepare("masters.xls#store_info");
    In<ItemInfo> itemInfo = tester.input("itemInfo", ItemInfo.class)
        .prepare("masters.xls#item_info");
    In<SalesDetail> salesDetail = tester.input("salesDetail", SalesDetail.class)
        .prepare(dataSet + "#sales_detail");

    Out<CategorySummary> categorySummary = tester.output("categorySummary", CategorySummary.class)
        .verify(dataSet + "#result", dataSet + "#result_rule");
    Out<ErrorRecord> errorRecord = tester.output("errorRecord", ErrorRecord.class)
            .dumpActual("build/dump/error_" + dataSet);

    FlowDescription flowPart = new CategorySummaryFlowPart(
        salesDetail, storeInfo, itemInfo, categorySummary, errorRecord);

  }

このインスタンスを引数にして FlowPartTester が持つ runTest メソッドを実行すると、テストデータに応じたテストを自動的に実行します。

CategorySummaryFlowPartTest.java
private void run(String dataSet) {
    FlowPartTester tester = new FlowPartTester(getClass());

    In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
        .prepare("masters.xls#store_info");
    In<ItemInfo> itemInfo = tester.input("itemInfo", ItemInfo.class)
        .prepare("masters.xls#item_info");
    In<SalesDetail> salesDetail = tester.input("salesDetail", SalesDetail.class)
        .prepare(dataSet + "#sales_detail");

    Out<CategorySummary> categorySummary = tester.output("categorySummary", CategorySummary.class)
        .verify(dataSet + "#result", dataSet + "#result_rule");
    Out<ErrorRecord> errorRecord = tester.output("errorRecord", ErrorRecord.class)
            .dumpActual("build/dump/error_" + dataSet);

    FlowDescription flowPart = new CategorySummaryFlowPart(
        salesDetail, storeInfo, itemInfo, categorySummary, errorRecord);
    tester.runTest(flowPart);
}
[1]com.asakusafw.testdriver.FlowPartTester
[2]ここの名前は他の名前と重複せず、アルファベットや数字のみで構成して下さい
[3]com.asakusafw.vocabulary.flow.In
[4]com.asakusafw.vocabulary.flow.Out

17.10. テストを実行する

テストクラスを作成したら、テストを実行してみましょう。

テストクラスは通常のJUnitのテストを実行する方法と同じです。 JUnitのテストを実行する手順は、 演算子のテスト - テストを実行する などを参考にしてください。

17.11. テストケースを追加する

ここまでの手順でもっとも単純なテストケースが確認できたので、同様の手順でテストケースを追加していきましょう。

想定されるテストケースの例を以下に示します。

  • カテゴリ別の集計が正しく行われることを確認する
  • マスタ有効期限に基づく正しいマスタが選択される
  • 正しくない店舗情報を含む場合にエラー情報が出力される

すべてのテストケースに対応するテストデータとテストクラスの例は、このチュートリアルの最後に記載します。

17.12. 終わりに

このチュートリアル終了時点のフロー部品テストクラス CategorySummaryFlowPartTest.java は、次のようになります。

CategorySummaryFlowPartTest.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.example.flowpart;

import org.junit.Test;

import com.asakusafw.testdriver.FlowPartTester;
import com.asakusafw.vocabulary.flow.FlowDescription;
import com.asakusafw.vocabulary.flow.In;
import com.asakusafw.vocabulary.flow.Out;
import com.example.modelgen.dmdl.model.CategorySummary;
import com.example.modelgen.dmdl.model.ErrorRecord;
import com.example.modelgen.dmdl.model.ItemInfo;
import com.example.modelgen.dmdl.model.SalesDetail;
import com.example.modelgen.dmdl.model.StoreInfo;

public class CategorySummaryFlowPartTest {

    @Test
    public void simple() {
        run("simple.xls");
    }

    @Test
    public void summarize() {
        run("summarize.xls");
    }

    @Test
    public void available_date() {
        run("available_range.xls");
    }

    @Test
    public void invalid_store() {
        run("invalid_store.xls");
    }

    private void run(String dataSet) {
        FlowPartTester tester = new FlowPartTester(getClass());

        In<StoreInfo> storeInfo = tester.input("storeInfo", StoreInfo.class)
                .prepare("masters.xls#store_info");
        In<ItemInfo> itemInfo = tester.input("itemInfo", ItemInfo.class)
                .prepare("masters.xls#item_info");
        In<SalesDetail> salesDetail = tester.input("salesDetail", SalesDetail.class)
                .prepare(dataSet + "#sales_detail");

        Out<CategorySummary> categorySummary = tester.output("categorySummary", CategorySummary.class)
                .verify(dataSet + "#result", dataSet + "#result_rule");
        Out<ErrorRecord> errorRecord = tester.output("errorRecord", ErrorRecord.class)
                .dumpActual("build/dump/error_" + dataSet);

        FlowDescription flowPart = new CategorySummaryFlowPart(
                salesDetail, storeInfo, itemInfo, categorySummary, errorRecord);
        tester.runTest(flowPart);
    }

}

また、テストクラスに対応するテストデータのExcelは以下からダウンロードできます。

17.13. トラブルシューティング

このチュートリアルに関するトラブルシューティングです。

17.13.1. Asakusa Framework is not installed

テストを実行する の手順を実行すると、以下のエラーメッセージが表示されテストが失敗する。

...
java.lang.IllegalStateException: java.io.IOException: Asakusa Framework is not installed: C:\Users\asakusa\asakusa
  at com.asakusafw.testdriver.JobFlowTester.runTest(JobFlowTester.java:105)
...

17.13.1.1. 想定される原因

開発環境 ASAKUSA_HOME にAsakusa Frameworkがインストールされていない可能性があります。 Asakusa Frameworkのインストール の手順が正しく行われているかを確認してください。

17.13.2. Failed to locate the winutils

Windows環境で テストを実行する の手順を実行すると、以下のエラーメッセージが表示される。テスト自体は成功する。

...
ERROR Failed to locate the winutils binary in the hadoop binary path
java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
...

17.13.2.1. 想定される原因

現時点でのAsakusa Frameworkの制限事項で、Windows上でテストドライバーを実行するとこのメッセージが出力されることがあります。 テスト自体の動作には影響ありません。