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

Eachの中でassertするときは明記する必要がある #spock

Spockでは通常、thenブロックの中はbool値を返すようにしておけば勝手にアサーションしてくれる。

then:
actual == expect

ただし、イテレーションの中はアサーションしてくれない

then:
actualArray.each {
  it.getName == expectName // falseでもテストNGにならない
}

明示的にassertを記載すればちゃんとアサーションされる。

then:
actualArray.each {
  assert it.getName == expectName
}

Mavenで特定のクラスのテストだけ実行する #maven #java

特定のテストだけ

mvn test -Dtest=red.sukun1899.SampleSpec

クラス名が一意になるなら、パッケージは省略できる

mvn test -Dtest=SampleSpec

複数の場合はカンマでつなぐ

mvn test -Dtest=HogeSpec,FugaSpec

特定のメソッドだけ実行する場合シャープでつなぐ

mvn test -Dtest=SampleSpec#test1

複数メソッドの場合カンマでつなぐ

mvn test -Dtest=SampleSpec#test1,SampleSpec#test2

メソッド名に空白が含まれる場合、ダブルクォートで括る

mvn test -Dtest="SampleSpec#test するよ, SampleSpec#test しちゃうよ"

正規表現っぽいのも使える

mvn test -Dtest="SampleSpec#test*"

TDDっぽくモブプログラミングしてみた #MobProgramming

最近はまっていることがあるんですけど。。と同僚に言ったら「モブプログラミングですか?」と聞かれる程度にはハシャいでおります。

先日はTDDな感じでやってみました。

(結果的にそうなったけれど、そうしようとして始めた感じではなかったかも)

ちょっと複雑な処理があって、パターンから考えたほうがいいかもという話になり、ホワイトボードを使って思考を整理して、テストケースにまで落とし込む。

そしたらまずテストコードを書いてこけるところまで確認してから、あーでもないこうでもないと進めました。

試行錯誤が必要なときに、最初からテストがあると安心感が違います。

ゴールが決まっていることで、出口のない迷路に迷い込んでしまうこともない。

これはTDDのいいところですね。

結構複雑なタスクだったので、本格的なリファクタリングまでは取組めなかったものの、数時間でテストがグリーンになるところまで進めたのは正直驚きがありました。

複雑さに立ち向かうとき、モブプログラミングとTDDの掛け合わせは効果が高そうなのでおすすめです。

モブプログラミング楽しいですよ、モブプロ。

みんなで思考整理をするの図

f:id:su-kun1899:20170402125921p:plain

データ抽出のテストにはモブプログラミングを使うといいかも #MobProgramming

モブプログラミングとは?

この記事では複数人で行われるプログラミングの意です。

ペアプロの延長線上だと考えて下さい。

正確な定義とは異なるかもしれません。

参考までに以前書いた記事です。

su-kun1899.hatenablog.com

データ抽出のテストって?

何らかのデータストアに対して、クエリを発行し、結果を取得するようなUnitTestを想定しています。

MySQLようなRDBMSに、Select文を発行して結果を確認するようなイメージです。

データ抽出のテストの何が問題なの?

データ抽出のテストは実装後のレビューコストが高いです。

データ抽出する処理の実装時に考慮すべきことに例えば下記があると思います。

  • データストアの設計
    • RDBMSでいうER。オブジェクト間のリレーション。仕様的なものも含む
  • データ
    • どんなテーブルに、どんなデータが入っているか
  • クエリの構造
    • JOIN句の類。内部結合か外部結合か。UNIONやソート順などなど
  • パラメータ
    • どんな条件で検索するか。SelectでいうWhere句
  • etc

多くの場合、実装者はこれらを並行で考慮しながらテストを書く必要があります。

そして、主にデータパターンとパラメータの組み合わせでテストの意図が込められていきます。

意図の読み解きが難しい

データパターンやパラメータの場合、コードから意図を読み解くことは一般的に難しいと思います。

レビュワーも当然前述の項目を並行で考えなければならないからです。

ケースは思い浮かんでも、どこで実施しているかを読み解くのは困難です。

DbSetupのようにテストデータの可視性を高めるライブラリもありますが、限界はあります。

そのため、後からコードレビューを行う際に、どうしてもコストが高くなってしまうのです。

なぜモブプログラミングがよいの?

モブプログラミングではリアルタイムでレビューを行います。

そのため、ドライバーが意図を説明しながら、ナビゲーターが意図を理解しながら同時進行で進めることができます。

なので、実装とレビューでフェーズを分ける場合に比べて効率が格段に上がると思います。

僕らはさらに、着手前にチームメンバーで想定されるテストケースの洗い出しをしました。

作業を進めていく中で、実はいらなかったケースなどが出てきたりして、とても効果的だったと思います。

まとめ

性質上、コードから意図の読み取りが難しくなるような場合は、モブプログラミングをおすすめします。

モブプログラミング楽しいですよ、モブプロ。

みんなでテストケースを洗い出すの図

f:id:su-kun1899:20170330005933p:plain

最良の日だったかもしれない #ちら裏 #ポエム

転職して、一年ちょっとが経ったにもかかわらず、モヤモヤしながらもがき苦しんでるわけですが、今日は入社してから一番いい日だったかもしれない。

何があった

とあるモジュールがSVNで構成管理をしているんだけれど、GitHubに移行することになった。

自分は直接関わっていないんだけれど、部署の中では比較的Git/GitHubに慣れているということで、その会議に呼ばれた。

アジェンダとしては主にプルリクのレビュー運用・ルールについて。

その会議で、モデレータしてたメンバーと僕は同じチームで数ヶ月一緒に開発作業をしていた。

一緒にやっていたプロジェクトは正直直接的な成果を上げていたとはいえなくて、今は別チームになってしまっている状況。

でその人が、プルリクのレビューの議論をしている時にこんなことを言った。

“レビューはコードの正しさを見るだけじゃなくて、それもあるけど、質問とかいろいろなやり取りがあっていいので色んな人に見てもらいたい”

このセリフがとてもうれしくて。

自分は入社してから、チームで開発するということ、一緒に作るということ、ということを伝えたいと思っていて。

届く範囲で、伝え続けてきたつもりで。

チームに何かを与えたか、組織に何かを与えたか、誰かの何かを変えたか、それはわからないけれども。

彼には何かが伝わっていたかもしれない。

一緒に開発してた期間に意味はあったのかもしれない。

今の会社に僕の存在価値があるかどうかは分からないけど、少なくとも僕にとっては意味のある何かが、ここでも少しはできたと初めて実感できたよ。

ネストしたオブジェクトでAutoMappingを使う #mybatis

MybatisのネストしたresultMapの自動マッピングはデフォルトPARTIALになっている。

つまり、ネストしたオブジェクトのauto-mappingは効かないということ。

これだといちいちマッピングを定義してやらなきゃいけないのでとてもつらいのだが、設定を変えなくても、個別にresltMapを定義してやることで、auto-mappingを使える。

対象のマッパークラス

public class Company {
  private long id;
  private String name;
  private List<Section> sections; // 部署リスト

  // アクセサは省略
}

public class Section {
  private long id;
  private String name;
  private Member representative; // 代表者

  // アクセサは省略
}

public class Member {
  private long id;
  private String name;

  // アクセサは省略
}

SQLのイメージ

SELECT
    company.id    AS id
  , company.name  AS name
  , section.id    AS section_id
  , section.name  AS section_name
  , member.id     AS representative_id
  , member.name   AS representative_name
FROM
  company
  inner join
  section
    on company.id = section.company_id
  inner join
  member
    on section.representative_id = member.id

これはNG

<resultMap id="companyMap" autoMapping="true" type="Company">
    <id property="id" column="id"/>
    <collection property="sections" autoMapping="true" columnPrefix="section_" ofType="Section">
        <id property="id" column="id"/>
        <association property="representative" columnPrefix="representative_" javaType="Member" autoMapping="true">
            <id property="id" column="id"/>
        </association>
    </collection>
</resultMap>

これはOK

<resultMap id="companyMap" autoMapping="true" type="Company">
    <id property="id" column="id"/>
    <collection property="sections" autoMapping="true" columnPrefix="section_" ofType="Section">
        <id property="id" column="id"/>
        <association property="representative" columnPrefix="representative_" resultMap="memberMap">
    </collection>
</resultMap>
<resultMap id="memberMap" type="Member" autoMapping="true">
    <id property="id" column="id"/>
</resultMap>

SQLと紐付け

<select id="getCompany" resultMap="companyMap">
  <!-- ここにSQLを書く -->
</select>

参考

意見 #ちら裏 #ポエム

自分を信じよう

自分の知識・経験をフル稼働させて出した答えを信じ、大切にしたほうがよい。

他人の方が優秀かもしれないが、自分ではない。

もっとも信頼できるのは自分自身であるべきだ。

自分を疑おう

自分の出した答えを疑ったほうがよい。

世の中には知らないことがたくさんあるし、自分よりも優秀な人もたくさんいる。

なにより、ほとんどの場合正解なんてそもそも存在しないのだ。

よりよい答えを、常に謙虚に探し続けなければならない。