Eclipse + Xtend で JUnit 用の AssertExtension 作ってみた
.NET だと Chaining Assertion - Home を良く使ってるので、Xtend でも似たような感じに書けるの作ってみました。
OdaShinsuke/xtendjunit · GitHub
Xtend だと、拡張メソッドが使えるので
actual.is(expected)
という形で大体出来るようにしています。
賛否両論ありそうですが、使いやすさ優先で equals を override していない型の場合は、Lang - Home の EqualsBuilder.reflectionEquals 使って比較しています。
override している/していない のチェックは結構適当で
Class.getDeclaredMethod("equals", Object.class)
でやってます。List や Array の要素に対しても対応してます。
一部のプロパティのみで比較するように、
def static void is(T actual, T expected, Function2<T, T, Boolean> predicate)
も用意しています。
(new Hoge => [id = 1 name = "aaa"]).is( new Hoge => [id = 1 name = "bbb"] ) [e, a| e.id == a.id] // id のみで比較
Eclipse が Visual Studio より優れてる箇所が1つあって、
「テストの失敗が ComparisonFailure の時は、比較用の Window が出て違う箇所に色付けてくれる」
という機能があります。
通常の assertEquals 等の場合、文字列 の assert の時のみ ComparisonFailure を返すのですが、xtendjunit では 全部 ComparisonFailure で返すようにしています。
通常の assertEquals で比較すると、
@Test def void basicConfirmMessage() { val actual = new NoOverrideEquals => [id = 1 name = "bbb"] val expected = new NoOverrideEquals => [id = 1 name = "ddd"] assertEquals("message", expected, actual) }
こんな感じで表示されます。
xtendjunit の is で比較すると、
@Test def void confirmMessage_List() { val actual = #[ new NoOverrideEquals => [id = 1 name = "aaa"], new NoOverrideEquals => [id = 2 name = "bbb"], new NoOverrideEquals => [id = 3 name = "ccc"] ] val expected = #[ new NoOverrideEquals => [id = 1 name = "aaa"], new NoOverrideEquals => [id = 2 name = "ddd"], new NoOverrideEquals => [id = 3 name = "ccc"] ] actual.is("message", expected) }
ここまでは似たような感じですが
ダブルクリックすると Result Comparison ウィンドウが立ち上がります。
これは、toString の結果を表示しているので、ちゃんと toString を実装しとけば綺麗に出ます。
最後に DBUtils + SQL Server 2014 を使った Dao のテストを書いてみました。*1
package sample import com.microsoft.sqlserver.jdbc.SQLServerDataSource import java.util.List import org.apache.commons.dbutils.QueryRunner import org.apache.commons.dbutils.ResultSetHandler import org.apache.commons.dbutils.handlers.BeanListHandler import org.eclipse.xtext.xbase.lib.util.ToStringHelper class Dao { def List<Entity> findEntities() { val dataSource = new SQLServerDataSource => [ serverName = "localhost\\MSSQL2014" databaseName = "database1" user = "hoge" password = "hoge" ] new QueryRunner().query(dataSource.connection, "select [id], [name] from [Hoge] ", new BeanListHandler(Entity) as ResultSetHandler<List<Entity>>) } } class Entity { @Property int id @Property String name override toString() { new ToStringHelper().toString(this) } }
package sample import static extension xtendjunit.AssertExtensions.* import org.junit.Test class DaoTest { @Test def void findEntities() { val dao = new Dao dao.findEntities.is(#[ new Entity =>[ id = 1 name = "aaa" ], new Entity =>[ id = 2 name = "bbb" ], new Entity =>[ id = 3 name = "ccc" ], new Entity =>[ id = 4 name = "ddd" ] ]) } }
Xtend で使うならそんな悪くないんじゃないかなーと思ってます。*2
*1:普段は Doma - Domaプロジェクトへようこそ 使ってます