読者です 読者をやめる 読者になる 読者になる

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 のみで比較

EclipseVisual 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プロジェクトへようこそ 使ってます

*2:Java では微妙かな。。