山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

【java】DTO のテストコードを自動生成への道②


前回の記事はこちら。

yyama1556.hateblo.jp


とりあえず動くものを作った。

github.com

DtoTestGenerator と命名した。

今のところ対応している型は int, long, Integer, Long, String のみ。

テスト対象にできるクラスは 1 個 で、クラス名もハードコードとなっている。(今後、機能追加していく)

生成されるテストコード

次のような DTO があるとする。

package org.some.dto;

import java.io.Serializable;

public class SomeDto implements Serializable {

	private static final long serialVersionUID = 1399332442638064271L;

	private int age;
	private String firstName;
	private String secondName;
	private int height;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getSecondName() {
		return secondName;
	}

	public void setSecondName(String secondName) {
		this.secondName = secondName;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	@Override
	public String toString() {
		return "SomeDto [age=" + age + ", firstName=" + firstName + ", secondName=" + secondName + ", height=" + height
				+ "]";
	}

}

DtoTestGenerator の main メソッドを実行すると、out フォルダに次のようなテストコードが生成される。実際の出力では、ソースのインデントを考慮していないが、整えた形で掲載する。

package org.some.dto;

import static org.junit.Assert.*;

import org.junit.Test;

public class SomeDtoTest {

	@Test
	public void setAgeでセットした値がgetAgeで取得できること() {

		// Setup
		SomeDto dto = new SomeDto();

		// Exercise
		dto.setAge(0);
		Integer act = dto.getAge();

		// Verify
		assertEquals(Integer.valueOf(0), act);

	}

	@Test
	public void setFirstNameでセットした値がgetFirstNameで取得できること() {

		// Setup
		SomeDto dto = new SomeDto();

		// Exercise
		dto.setFirstName("a");
		String act = dto.getFirstName();

		// Verify
		assertEquals("a", act);

	}

	@Test
	public void setSecondNameでセットした値がgetSecondNameで取得できること() {

		// Setup
		SomeDto dto = new SomeDto();

		// Exercise
		dto.setSecondName("b");
		String act = dto.getSecondName();

		// Verify
		assertEquals("b", act);

	}

	@Test
	public void setHeightでセットした値がgetHeightで取得できること() {

		// Setup
		SomeDto dto = new SomeDto();

		// Exercise
		dto.setHeight(1);
		Integer act = dto.getHeight();

		// Verify
		assertEquals(Integer.valueOf(1), act);

	}

	@Test
	public void toStringでdtoの情報が表示されること() {

		// Setup
		SomeDto dto = new SomeDto();
		dto.setAge(0);
		dto.setFirstName("a");
		dto.setSecondName("b");
		dto.setHeight(1);

		// Exercise
		String act = dto.toString();

		// Verify
		assertEquals("SomeDto [age=0, firstName=a, secondName=b, height=1]", act);

	}

}

getter, setter および toString のテストコードが自動で生成されていることがわかる。

また、工夫した箇所としては、String 型のプロパティが複数ある場合、setter でセットする値は a → b → c ・・・ のように変わっていく。同様に int では 1 → 2 → 3・・・のように変わっていく。

プロジェクトの構成

プロジェクトの構成を簡単に説明する。

ファイルやフォルダの構成は次のようになっている。

f:id:yyama1556:20160924130739p:plain

org.yyama.DtoGenerator がこのプロジェクトの本体であり、main メソッドを実装している。

org.yyama.type 配下に型ごとにクラスを追加していく。DtoTestGenType は abstract なクラスとなっていて、Integer, Long, String の各 Type はこれを継承している。

例えば Date 型に対応したければ DtoTestGenType を継承した DateType を作成する(クラス名は自由)。

プロジェクト直下の out フォルダは生成されたテストコードが格納される場所なのであらかじめ作っておく必要がある。

使い方

例えば以下のように SomeDto プロジェクト配下の SomeDto.java のテストケースを生成したい場合、

f:id:yyama1556:20160924131712p:plain

SomeDto プロジェクトの src フォルダをビルドパスに加える必要がある。

DtoTestGenerator プロジェクトを右クリック→ Properties を選択し、プロパティ画面を表示し、Java Build Path を選択する。

Add Class Folder を選択する。

f:id:yyama1556:20160924132034p:plain

SomeDto プロジェクトの bin フォルダをチェックして OK を押す。

f:id:yyama1556:20160924132332p:plain

あとは対象のクラス名が、DtoTestGenerator.java にベタ書きされているので、必要に応じ修正して main() を実行するだけ。

		// Classを取得
		Class<SomeDto> clazz = SomeDto.class;  // ← テスト対象クラスに応じてここを修正
		String cName = clazz.getSimpleName();

今後実装したい機能

  • 複数 Dto のテストコードを一気に生成
  • パッケージ配下のクラスを自動検索し、XxxDto.java ファイルを見つけて一気に生成
  • Date 型に対応
  • 配列型に対応
  • List型に対応


今日はここまで。でわ。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)