退職しました

本日4/1をもって株式会社HOGEDRIVENを退職しました。

HOGEDRIVENでは並行プログラミング(焼肉)、ORマッパー(フグ)、暗号(焼肉)、Java 8のラムダ(ステーキ)など、様々な技術を経験させて貰いすごく感謝しています(ごちそうさまでした)。

しかし、HOGEDRIVENは「しゃぶしゃぶ」「ローストチキン」「シシケバブ」など、これからも肉料理に力を入れて行くようで、魚料理にも挑戦したいという私の思いとは目指す方向が異なるため、退職という道を選択しました。

今後の事はまだ何も決まっていませんが、ベタなところではマグロ、カニ、あるいは捨てる所が無いと言われるアンコウあたりに興味があるので、機会を見つけてチャレンジして行きたいと思います。

今後とも宜しくお願いただきます。

Java8でBDDっぽくテストを書けるかもしれないアイデア

JasmineでJavaScriptのテスト書いたりJava8のラムダに思いを馳せていたらなんとなく思いつきました。 ラムダにインスタンスイニシャライザを組み合わせたらこんな感じでテストが書けそうです。

package app;

public class CalcSpec extends Specs {{

    it("1 足す 2 は 3", () -> {
        expect(() -> 1 + 2).toEqual(3);
    });

    it("1 割る 0 は例外", () -> {
        expect(() -> 1 / 0).toThrow(ArithmeticException.class);
    });

}}

うむ、Jasmineぽい。 まあ実はBDDぽいとかよく分かっていませんが。

itメソッドを呼ぶと第一引数のテスト名をkey、第二引数のRunnableのようなオブジェクトをvalueとするマップに突っ込みます。 このマップのひとつのEntryがひとつのテストになります。 itメソッドはスーパークラスのSpecsに定義されています。 そのSpecs自体に@RunWithが注釈しており、テストはSpecRunnerというテストランナーで実行されます。 SpecRunnerはSpecsに集められたテストを実行します。

などと文章にしても伝えられる気がまったく無いのでSpecsとSpecRunnerのコード晒します。

Specsはこんな感じ。

package app;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import org.junit.Assert;
import org.junit.runner.RunWith;

@RunWith(SpecRunner.class)
public class Specs {

    public Map<String, Spec> specs = new LinkedHashMap<>();

    protected void it(String name, Spec spec) {
        specs.put(name, spec);
    }

    protected <T> Expect<T> expect(Callable<T> c) {
        return new Expect<>(c);
    }

    public interface Spec {

        void run() throws Exception;
    }

    public static class Expect<T> {

        private final Callable<T> c;

        public Expect(Callable<T> c) {
            this.c = c;
        }

        public void toEqual(T value) throws Exception {
            Assert.assertEquals(value, c.call());
        }

        public void toThrow(Class<? extends Exception> exceptionClass) throws Exception {
            try {
                c.call();
                Assert.fail();
            } catch (Exception e) {
                if (!exceptionClass.isAssignableFrom(e.getClass())) {
                    Assert.fail();
                }
            }
        }
    }
}

SpecRunnerはこんな感じ。

package app;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;

public class SpecRunner extends Runner {

    private final Specs spec;

    public SpecRunner(Class<Specs> specClass) throws InstantiationException, IllegalAccessException {
        spec = specClass.newInstance();
    }

    @Override
    public Description getDescription() {
        Description desc = Description.createSuiteDescription(spec.getClass());
        for (String name : spec.specs.keySet()) {
            desc.addChild(Description.createSuiteDescription(name));
        }
        return desc;
    }

    @Override
    public void run(RunNotifier notifier) {
        for (String name : spec.specs.keySet()) {
            Description desc = Description.createSuiteDescription(name);
            notifier.fireTestStarted(desc);
            try {
                spec.specs.get(name).run();
            } catch (Exception ex) {
                Failure f = new Failure(desc, ex);
                notifier.fireTestFailure(f);
            } finally {
                notifier.fireTestFinished(desc);
            }
        }
    }
}

これらのコードを、Java8に対応しているNetBeansの開発版を使用して試してみました。

../../../_images/test-result.png

いい感じで実行できました。

というわけで、ふわっとした思いつきをサクッと試してみただけですが、なかなかJava8の可能性を感じれた気がします。 テスティングフレームワークに限らずね、色々出てきてくれそうですね。

楽しみだ。はよこいJava8。

ギットハブにも置いたよ