Tag Archives: アノテーション

[Annotations][TestNG]アノテーションを使用した簡単テストフレームワーク「TestNG」

最近SAStrutsをよく使用するため、アノテーション機能も使用する機会が多くなった。
その中でもTestNGというテスト用フレームワークは、すごく使いやすい。

■Eclipseにプラグインとして追加
以下のURLに書いてあるようにプラグインの追加を行なう。
http://testng.org/doc/download.html

Eclipseの再起動後、プロジェクトを作成。
プロジェクトを右クリック→プロパティ→Javaビルドパス→ライブラリへ移動
外部Jarの追加で「testng-jdk15.jar」を追加で完了

■テストされるクラスの作成
テストされるクラスを作成する。
ポイントは3点。
1.コンストラクタで引数を受け取ること。
2.コンストラクタで受け取った値を引数なしでreturnする。
3.引数とコンストラクタで受け取った値を結合してreturnする。

Sample.java

public class Sample {
	private String value;

	public Sample(String value) {
		this.value = value;
	}

	public String str() {
		return this.value;
	}

	public String str(String str) {
		return str + "_" + this.value;
	}
}

■テストクラスの作成
テスト用クラスを作成する。
今回は、引数なしのメソッドと引数ありのメソッドの2種類を作成するが、
ひとまず、引数なしのメソッドだけテストするクラスを作成する。

SampleTest.java

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

/* これ重要 */
import static org.testng.Assert.*;

public class SampleTest {
	private Sample sample;

	/** BeforeClassを定義するとテスト処理の前にこのメソッドが呼ばれる */
	@BeforeClass
	public void init() {
		this.sample = new Sample("test value");
	}

	/** 引数なしのテスト処理 */
	@Test
	public void sysout() {
		String result = this.sample.str();

		/* resultがnullではないか */
		assertNotNull(result);
		/* resultが第2引数と一致しているか */
		assertEquals(result, "test value");
	}
}

■テスト実行、確認
前項で作成したテストクラスを右クリック→実行(Run As)→TestNG Testをクリック
コンソールに実行結果がでているがひとまず無視。

プロジェクト名を右クリック→更新(Refresh)をクリック
すると、「test-output」と「temp-testng-customsuite.xml」が勝手に出力されているはず。

「test-output」は、テスト結果をHTMLとして出力してくれるため、
非常に便利。

それと「temp-testng-customsuite.xml」は、
テストを実行する際の設定ファイルになる。

■引数を渡したテストクラスの作成
先ほど作成したSample.javaの引数ありメソッドをテストする。
アノテーションParametersが2箇所入ってる。
このParametersは次項で設定ファイルに追記する。

SampleTest.java

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

/* これ重要 */
import static org.testng.Assert.*;

public class SampleTest {
	private Sample sample;

	/** BeforeClassを定義するとテスト処理の前にこのメソッドが呼ばれる */
	@BeforeClass
	@Parameters("const-value")
	public void init(String constValue) {
		this.sample = new Sample(constValue);
	}

	/** 引数なしのテスト処理 */
	@Test
	public void sysout() {
		String result = this.sample.str();

		/* resultがnullではないか */
		assertNotNull(result);
		/* resultが第2引数と一致しているか */
		assertEquals(result, "test value");
	}

	/** 引数ありのテスト処理 */
	@Test
	@Parameters("test-value")
	public void sysout(String str) {
		String result = this.sample.str(str);

		/* resultがnullではないか */
		assertNotNull(result);
	}
}

■設定ファイルを編集
解説も面倒になってきたので、設定ファイルを見て
あとは本家サイトで記述方法を学んでください。

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="LoginSample">
	<!-- テストクラス内で使用するパラメータ系を定義する -->
	<parameter name="const-value" value="test value" />
	<parameter name="test-value" value="XXXXXXX" />

	<!-- nameは必須項目。通常パッケージ名などでカテゴリ分けする -->
	<test name="defaultPackage">
		<classes>
			<!-- テストするクラスを指定 -->
			<class name="SampleTest" />
		</classes>
	</test>
</suite>

[SAStruts]S2JDBCでJOINのやり方をいつも忘れるからメモ

SAStrutsでJOINを行なう際、どう書くか毎回忘れてしまう。

単純なテストを以下に記す。



■データベースのスキーマ

CREATE DATABASE db_test;
USE db_test;

CREATE TABLE channels (
	channel_id INTEGER NOT NULL AUTO_INCREMENT
	, title TEXT NOT NULL
	, PRIMARY KEY (channel_id)
);

CREATE TABLE items (
	item_id INTEGER NOT NULL AUTO_INCREMENT
	, title TEXT NOT NULL
	, url VARCHAR(255) NOT NULL
	, channel_id INTEGER NOT NULL
	, PRIMARY KEY (item_id)
	, UNIQUE (url)
);

INSERT INTO channels (title) VALUES("情報考学 Passion For The Future");
INSERT INTO channels (title) VALUES("RwJ");

INSERT INTO items (title,url,channel_id) VALUES("無趣味のすすめ","http://www.ringolab.com/note/daiya/2009/07/post-1021.html",1);
INSERT INTO items (title,url,channel_id) VALUES("アイデア・スイッチ 次々と発想を生み出す装置","http://www.ringolab.com/note/daiya/2009/07/post-1023.html",1);
INSERT INTO items (title,url,channel_id) VALUES("ベガーズ・イン・スペイン","http://www.ringolab.com/note/daiya/2009/07/post-1022.html",1);
INSERT INTO items (title,url,channel_id) VALUES("psコマンドはオプションに「-」がいらないみたい","http://blog.mikuriya.biz/archives/310",2);
INSERT INTO items (title,url,channel_id) VALUES("[SAStruts]Tomcat起動時に初回のみ呼び出す独自のクラスでデータベース接続","http://blog.mikuriya.biz/archives/171",2);
INSERT INTO items (title,url,channel_id) VALUES("[PHP]フレームワーク「CakePHP」のインストールと設定","http://blog.mikuriya.biz/archives/7",2);




■jdbc.diconを編集

今回は、MySQLを使用するので、そのあたりを編集する。

<components namespace="jdbc">
	...

	<component name="xaDataSource"
		class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
		<property name="driverClassName">
			"com.mysql.jdbc.Driver"
		</property>
		<property name="URL">
			"jdbc:mysql://localhost:3306/db_test"
		</property>
		<property name="user">"root"</property>
		<property name="password">""</property>
	</component>
	...
</components>




■channelsテーブルのクラス

package biz.mikuriya.entity;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "channels")
public class Channel {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public int channelId;

	public String title;

	@OneToMany(mappedBy = "parent") // Itemに定義する変数名がparentになる
	public List<Item> childs;
}




■itemsテーブルのクラス

package biz.mikuriya.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "items")
public class Item {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public int itemId;

	public String title;

	public String url;

	public int channelId;

	@ManyToOne
	@JoinColumn(name = "channel_id")
	public Channel parent; // Channel.itemsのmappedByの値と変数名を合わせる
}




■動作テスト用実行クラス

package biz.mikuriya;

import java.util.List;

import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

import biz.mikuriya.entity.Channel;
import biz.mikuriya.entity.Item;

public class DBTest {
	private JdbcManager jdbcManager;

	/**
	 * データベース接続
	 */
	public DBTest() {
		SingletonS2ContainerFactory.init();
		S2Container container = SingletonS2ContainerFactory.getContainer();
		this.jdbcManager = (JdbcManager) container
				.getComponent(JdbcManager.class);
	}

	/**
	 * 普通にSELECT
	 */
	public void selectChannel() {
		System.out.println("CHANNELS************************************");

		List<Channel> channels = this.jdbcManager.from(Channel.class)
				.getResultList();

		for (Channel channel : channels) {
			System.out.println("\t" + channel.channelId + "\t" + channel.title);
			System.out.println("\t--------");
		}
	}

	/**
	 * 普通にSELECT
	 */
	public void selectItem() {
		System.out.println("ITEMS************************************");

		List<Item> items = this.jdbcManager.from(Item.class).getResultList();

		for (Item item : items) {
			System.out.println("\t" + item.itemId + "\t" + item.channelId
					+ "\t" + item.title + "\t" + item.url);
			System.out.println("\t--------");
		}
	}

	/**
	 * 一対多の構造で取得する場合
	 */
	public void joinOneToMany() {
		System.out.println("JOIN************************************");

		List<Channel> channels = this.jdbcManager.from(Channel.class)
				.innerJoin("childs").getResultList(); // JOINには、変数名を指定する

		for (Channel channel : channels) {
			System.out.println("\t" + channel.channelId + "\t" + channel.title);

			for (Item item : channel.childs) {
				System.out.println("\t\t" + item.itemId + "\t" + item.channelId
						+ "\t" + item.title + "\t" + item.url);
				System.out.println("\t\t--------");
			}

			System.out.println("\t--------");
		}
	}

	/**
	 * 一対一の構造で取得する場合
	 */
	public void joinOneToOne() {
		System.out.println("JOIN************************************");

		List<Item> items = this.jdbcManager.from(Item.class)
				.innerJoin("parent").getResultList(); // JOINには、変数名を指定する

		for (Item item : items) {
			System.out.println("\t" + item.itemId + "\t" + item.channelId
					+ "\t" + item.title + "\t" + item.url + "\t"
					+ item.parent.channelId + "\t" + item.parent.title);
			System.out.println("\t--------");
		}
	}

	public static void main(String[] args) {
		DBTest test = new DBTest();

		test.selectChannel();
		test.selectItem();

		test.joinOneToMany();
		test.joinOneToOne();
	}
}