うさぎ組

kyon_mm with software

ソフトウェアテストのイベントまとめ #SWTestAdvent

はじめに

このエントリはソフトウェアテストAdventCalendar2014の1日目の記事です。

http://connpass.com/event/4544/

ソフトウェアテストを勉強してみたいけど、どんな勉強会があるのかわからないなーっていう方は以下を参考に参加してみたりしてください!

平日夜にやっている系

Cafe.Testing http://connpass.com/event/4506/

@rika0618 さんが名古屋で毎月主催している勉強会です。僕も参加していますが、初心者向けにずっとやっているので、これからテストを勉強する人にいいかなって思います。基本的には既存の書籍やWeb上の資料について毎回みんなで質問とか意見交換しあう感じです。

TEF道 http://ameblo.jp/tef-do/

北海道のソフトウェアテストのコミュニティさんが主催している勉強会です。まだ参加したことがないのですが、参加している方達とは知り合いで話を聞いていると楽しそうです。北海道在住の方は参加してみるといいかもしれません。

終日やるハンズオン系

Nagoya.Testing http://togetter.com/li/264151 , http://togetter.com/li/284107 , http://togetter.com/li/469247

kyon_mmが主催しているソフトウェアテストプロセスを実際に一通りやってみるというイベントです。簡単なWebアプリケーションに対してテストの戦略をたてるところから、実施結果の報告まで。不定期開催なのですが、ぜひ今後も継続してやりたいと思っています。

WACATE http://wacate.jp/

毎年夏と冬に行なわれているソフトウェアテストの1泊2日のイベントです。こちらも初心者向けなのでこれから勉強してみたいし、いろんな人と知りあってみたいという方にはいいと思います。

シンポジウム系

JaSST http://jasst.jp/

ソフトウェアテストのシンポジウムです。日本のいろんな地域で行なわれています。基本的には終日講演を聞くスタイルです。東京での開催は2日開催になっています。いろんな方がいらっしゃるし、講演資料がWebにもあがっているので参考になると思います。

SQiP http://juse-sqip.jp/

品質系のシンポジウムです。こちらはまだ参加したことがないのですが、まわりの方の反応をみているととても楽しそうです。いろんな方の事例を聞けるのがいいところかなって思っています。基本東京での開催のようです。

TDD系

TDDBootCamp http://devtesting.jp/tddbc/

TDDの入門者向けのハンズオン勉強会です。不定期に各地で有志によって開催されています。最近は1日開催で終日行なうことが多いようです。

TDDeXchange, Men’s TDD

どちらも僕が主催している勉強会で、前者は「TDDBCの次」で、後者は「TDDについてもっとつっこんで議論したい」をするための勉強会です。どちらも講演とハンズオンのセットです。開催地域も場所も僕の都合ですが、呼ばれれば基本的に行ないます。

Groovyでデバッグするとき

はじめに

G* Advent Calendar2013の投稿になっております。本来はfpigletをつかったGroovyでのモナドの記事になる予定だったのですが、つかえばつかうほど、fpigletがイケていないので、紹介するのをやめました。

それで、これからGroovyをやる人がデバッグなどでなにをしていいかについてすこし書いてみることにしました。

http://qiita.com/advent-calendar/2013/gastah/participants

式のどこで何が生成されているのかわからない

式をassertでくくって実行しましょう。その式のメソッドやプロパティ呼び出し毎の返り値を表示します。いわゆるPowerAssertです。

ちょっと例がよくない(デメテル的にやばい)ですが、次のような感じの表示をしてくれます。

class Test{
  int a = 1
}
class Test2{
  Test t = new Test()
}
assert new Test2().t.a == 3
assert new Test2().t.a == 3
       |           | | |
       |           | 1 false
       |           Test@1580f504
       Test2@4555e4a3

どうも違うオブジェクトが生成されている

対象のオブジェクトのdump()メソッドを呼びだしてprintlnしてみましょう。Class,propertyを表示します。

println new Test2().dump()
<Test2@562390c0 t=Test@38f4596e>

ここで、t=Test@38f4596eのようになっているのは、TestクラスがtoString()を実装していないためです。TestクラスがtoString()を実装するといい感じに表示してくれます。そしてGroovyでは@Canonicalというアノテーションをclassに指定すると、toString, equals, hashCodeを自動で生成してくれます。

@Canonical
class Test{
  int a = 1
  int b = 2
}
@Canonical
class Test2{
  Test t = new Test()
}
println new Test2().dump()
<Test2@1ec41 t=Test(1, 2)>

MissingMethodException

次のようなコードを実行するとMissingMethodExceptionが発生します。

class Test{
}

new Test().clone("ほげ")
groovy.lang.MissingMethodException:
No signature of method: Test.clone() is applicable for argument types: (java.lang.String) values: [ほげ]
Possible solutions: collect(), find(), any(), collect(groovy.lang.Closure), getAt(java.lang.String), sleep(long)

意味的には次のような感じです。

groovy.lang.MissingMethodException
次のシグネチャに適合するメソッドはありません。: org.kyonmm.Test.clone()  引数の型が (java.lang.String) 値が: [ほげ]
次のメソッドなら呼べます。: collect(), any(), find(), collect(groovy.lang.Closure), print(java.lang.Object), use([Ljava.lang.Object;)

IntelliJ IDEAというIDEを使っている場合には、ある変数において初期化時にObject型以外であればあるていどはメソッド補完、プロパティ補完が効くのでぜひ活用してください。

ただ、初期化で型が決まらない場合やローカル変数をこえているとObjectとしか判定されない場面もあります。このときにどのようなプロパティやメソッドを呼びだせばいいのかわからないときは、そもそも「動的型付けとして設計のバランスが崩れている」という可能性もありますが、それは置いといて、調べなければいけない場面はたくさんあります。

そのときはメソッド一覧やプロパティ一覧を取得しましょう。metaClass.methodsやpropertiesを実行すると、Listで取得できます。

class Test{
}

new Test().metaClass.methods.each{println it}


public boolean java.lang.Object.equals(java.lang.Object)
public final native java.lang.Class java.lang.Object.getClass()
public native int java.lang.Object.hashCode()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public java.lang.String java.lang.Object.toString()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public static void Test.__$swapInit()
public groovy.lang.MetaClass Test.getMetaClass()
public java.lang.Object Test.getProperty(java.lang.String)
public java.lang.Object Test.invokeMethod(java.lang.String,java.lang.Object)
public void Test.setMetaClass(groovy.lang.MetaClass)
public void Test.setProperty(java.lang.String,java.lang.Object)

同様にプロパティもつぎのようにとれます。

class Test{
  int a = 0
  String s = "test"
}

new Test().properties.each{println it}
class=class Test
a=0
s=test

IDE起動しないでデバッグしてみる

groovy-debug-transformというライブラリをつかうと、printlnでのデバッグ作業がやりやすくなります。

https://github.com/timyates/groovy-debug-transform

使い方は上のリポジトリからcloneしてきてビルドをします。そのjarを自分のプロジェクトのライブラリに追加します。

git clone git@github.com:timyates/groovy-debug-transform.git
cd groovy-debug-transform
gradlew jar

使い方はデバッグしたいメソッドにDebugアノテーションをつけて、そのメソッドを実行するだけです。実行すると、メソッド内で実行される式が随時printlnされます。次のようなイメージです。

import com.bloidonia.groovy.ast.debug.Debug

class Test1 {
  int a
  @Debug
  def run(x) {
    def y = x + 11
    a * y
  }

}
println new Test1(a:1).run(10)
Wed Dec 11 10:04:18 JST 2013 (line 007) EXPRESSION: (y = (x + 11))
Wed Dec 11 10:04:19 JST 2013 (line 008) RETURN    : (a * y)
21

Debugアノテーションを指定したrunメソッドの処理がprintlnされています。実装が結構面白いので読んでみるといいですよ。

F#のなんかすごいところ

本記事はF#AdventCalendar(http://connpass.com/event/3935 )の13日の金曜日カレンダーです。昨日は@rika0618さんの「 match式だけがパターンマッチだと思うなよ」で、明日は@haxeさんの「F#とOCaml」です。

続きを読む...

GroovyのMOPについて

はじめに

これはMOP Advent Calendar2013の記事になります。何度かGroovyのMOPについては発表しているのですが、ブログでも書いておきたかったので参加しました。

http://qiita.com/advent-calendar/2013/mop

続きを読む...

現在時刻のテストをする 1/3 まずはCucumber-groovy #gadvent

はじめに

3回にかけてGroovyによるATDDを紹介します。お題は時刻によって挨拶文が変わるというものです。この連載?はG* Advent Calendar2013の投稿になっております。 また内容自体は本来はシステムテスト自動化カンファレンスでDEMOする内容でした。プロダクトコードをF# でつくったはいいものの、説明だったり動かす環境だったり、スクリプトのローカル依存具合がひどくってまだ公開できる段階にありません。。。(すいません)連載が終わる頃にはGroovy版で作りなおすか、F#の環境依存を解決するかで公開したいです。

http://qiita.com/advent-calendar/2013/gastah/participants

Cucumberとはなにか

BDDのなかでもScenarioBDDと呼ばれるテスティングフレームワークです。もとはRubyで実装されているものでしたが、cucumber-jvmとしてJava版をつくってくれた方がいらっしゃいます。

ファイル構成について

.
├── build.gradle #Gradleスクリプト
└── src
    ├── main
    │   └── groovy
    └── test
        ├── groovy #テストコードを置く場所
        │   └── feature
        │       └── Sample.groovy #テストコード
        └── resources #フィーチャを置く場所
            └── feature
                └── Sample.feature #フィーチャファイル

パッケージとしてfeatureを使っていますが、もちろんパッケージなしでもいいですし、もっと違う名前でも大丈夫です。(制限はない)

Gradleスクリプトの記述について

次のようにbuild.gradleファイルをプロジェクトルートで書いて gradle idea とするとライブラリのダウンロードとIntelliJ IDEAプロジェクトファイルを作成してくれます。

apply plugin:"groovy"
apply plugin:"idea"

repositories{
    mavenCentral()
}

dependencies{
    compile "org.codehaus.groovy:groovy-all:2.2.1"
    testCompile "junit:junit:4.11"
    testCompile "info.cukes:cucumber-junit:1.1.5"
    testCompile "info.cukes:cucumber-groovy:1.1.5"
}

フィーチャファイルの記述について

テーブルに日本語を使うとIntelliJのコードフォーマッタが微妙になるのですが、とりあえず日本語でサンプルにします。

# language: ja
# 機能: というラベルに対してはこのフィーチャファイルの内容を書く

機能: トップページに挨拶を表示する。挨拶の内容は時間帯によって変わる。
  システムが正常に動作しているときのトップページには常に表示しておく。
  デフォルトでは日本語の挨拶を表示するが、各地域の言語にも対応する。
  対応する言語については以下で示す。

    # シナリオとシナリオテンプレートを使う。
    # パラメタライズしたいときはシナリオテンプレートを使う。
    # given, when, thenが前提, もし, ならばに対応している。
    # and, butがかつ, しかしに対応している。
    # exampleが例に対応している。
    # パラメタライズしたい変数は<変数名>とする

  シナリオテンプレート:挨拶を表示するときに時間帯に着目する
    前提 <ある時間帯> の適当な時刻にアクセスする
    もし トップページを開いたなら
    ならば <特定の挨拶文> と挨拶を返す
  例:
    | ある時間帯 | 特定の挨拶文 |
    | 朝     | おはよう   |
    | 昼     | こんにちは  |
    | 夜     | こんばんは  |


  # : などの文字列はエスケープする必要がある。

  シナリオテンプレート:挨拶を表示するときに時間帯の境界に着目する
    前提 <時>\:<分>\:<秒> ちょっきりにアクセスする
    もし トップページを開いたなら
    ならば <特定の挨拶文> と挨拶を返す
  例:
    | 時  | 分  | 秒  | 特定の挨拶文 |
    | 05 | 59 | 59 | こんばんは  |
    | 06 | 00 | 00 | おはよう   |
    | 11 | 59 | 59 | おはよう   |
    | 12 | 00 | 00 | こんにちは  |
    | 17 | 59 | 59 | こんにちは  |
    | 18 | 00 | 00 | こんばんは  |

  シナリオテンプレート:挨拶を表示するときにクライアントの時刻に着目する
    前提 サーバーの時刻が <サーバー時刻> で クライアントの時刻が <クライアント時刻> ちょっきりにアクセスする
    もし トップページを開いたなら
    ならば <特定の挨拶文> と挨拶を返す
  例:
    | サーバー時刻   | クライアント時刻 | 特定の挨拶文 |
    | 05:59:59       | 05:59:59 | こんばんは  |
    | 06:00:00       | 05:59:59 | こんばんは  |
    | 05:59:59       | 06:00:00 | おはよう   |
    | 06:00:00       | 06:00:00 | おはよう   |
    | 11:59:59       | 11:59:59 | おはよう   |
    | 12:00:00       | 11:59:59 | おはよう   |
    | 11:59:59       | 12:00:00 | こんにちは  |
    | 12:00:00       | 12:00:00 | こんにちは  |
    | 17:59:59       | 17:59:59 | こんにちは  |
    | 18:00:00       | 17:59:59 | こんにちは  |
    | 17:59:59       | 18:00:00 | こんばんは  |
    | 18:00:00       | 18:00:00 | こんばんは  |

テストコードファイルの記述について

package feature

import cucumber.api.groovy.Hooks //フィーチャーファイルとの接合をやってくれる
import cucumber.api.groovy.JA //どの言語で書きたいか

this.metaClass.mixin(Hooks) // このスクリプトファイルにmixinする
this.metaClass.mixin(JA)    // このスクリプトファイルにmixinする

            // featureファイルの該当行と正規表現マッチして適合する定義を実行する。
// 基本的には普通のGroovyとして書ける

前提(~'^(.+) の適当な時刻にアクセスする$') {
    println it
}
前提(~'^(.+)\\:(.+)\\:(.+) ちょっきりにアクセスする$') {h,m,s ->
    println "$h:$m:$s"
}
前提(~'^サーバーの時刻が (.+) で クライアントの時刻が (.+) ちょっきりにアクセスする'){h,m ->
    println "$h, $m"
}
もし(~'^トップページを開いたなら$') {->
    println "top page"
}
ならば(~'^(.+)と挨拶を返す$') {
    assert true
}
前提(~'^クライアントの時刻が (.+) (.+) (.+)ちょっきりにアクセスする$') {h,m,s ->
    println "$h:$m:$s"

}

実行

これでresouces配下を選択してRun Allとするとフィーチャファイルにある対応するメソッドがそれぞれ実行されます。(上記サンプルはわざと失敗するようになっています。そこがCucumberを次回DISるためのネタだったりする。)

で進めかたとか、本当のテストは次回に

次回は

  • どうやってATDDをすすめていくのか
  • APIを実際にAsyncHttpClientで書いてみる

というところまでやります。

IntelliJ IDEAをインストールしたら設定してること(Java/Groovy編)

IntelliJ + Groovyでテストコードを書く毎日ですが、これらを設定しないと仕事にならない系ものをまとめてみました。各項目の「keyword」にあるものをIntelliJのメニューバーにあるHelp -> Find Actionで出てくる検索ボックスにいれると「この設定だよね?」って検索結果がでるので、それをクリックすれば一発で設定画面にとべます。

続きを読む...

Men’s TDD 名古屋本店を開業しました。 #MensTDD

概要

Men’s TBCやMen’s non-noとは無関係です。ただモテエンジニアはMen’s TDDに通っているという噂があるようです。名古屋本店では今回はTDDについての発表とハンズオンを行いました。TDDの歴史や暗黒面について、そして実際に困る部分についての質疑応答をいくつかできました。夕食のときには参加者のテストコードを盛大にDISりました。勉強になったと言ってくれたのでよかったと信じています。

続きを読む...