『JUnit実践入門』写経・実践会 in 横浜 #6 (特別編)
http://connpass.com/event/2270/
2013/05/12 『JUnit実践入門』写経・実践会 in 横浜 #6 (特別編) #junitbook
http://togetter.com/li/490112
はじめに
テスト駆動開発を継続する
テストの価値は失敗することにあるというのは、現在の状況と目的が一致している状態から変化があったことを分かりやすくしたものだと思いました。
アサーションを分かりやすく一つづつ実施することで、どの状態が意図している目的で、どうして目的に合致しなかったのか見つけやすくなるのかなと思います。
大きなオブジェクトの状態を確認しようとするとアサーションの行が増えますし、本当に確認したいことが埋もれてしまっては、元も子もないと思います。
設計を見なおしたり、リファクタリングをする際に、目的の状態になっていることを確認するためのテストを書き、その状態を維持しつつ小さく分かりやすいテストにしていくことが重要なことだと感じました。
そういった小さいテストを継続的に積み上げることで、ひとつの変更が影響する範囲を視覚的に捉えることが可能になるのではないかなと、思います。
小さいテストであれば、わざと目的通りのRedにした場合でも、意図している動作であるか確認しやすいのではと思いました。
ハンズオン 後半は、
@shuji_w6e さんの「受け入れテストの自動化とユースケース駆動開発 -Pre Cucumber Boot Camp-」と「cucumber + selenium」による受け入れテストのハンズオンでした。
元々はmavenとeclipseを対象にしたプロジェクトでしたが、IntelliJ IDEAとGradleでやってみようと思い、前日にGradle 1.6の
Build Setup Plugin を利用してbuild.gradleを作っておきました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply {
plugin 'java'
plugin 'war'
plugin 'jetty'
}
apply plugin: 'maven'
apply {
plugin 'idea'
}
group = 'junitbook'
version = '0.0.1-SNAPSHOT'
description = "Book store"
sourceCompatibility = 1.7
targetCompatibility = 1.7
repositories {
mavenCentral()
maven {
url 'http://download.eclipse.org/rt/eclipselink/maven.repo'
}
}
dependencies {
compile group: 'org.slf4j', name: 'slf4j-jdk14', version: '1.7.5'
compile group: 'org.tuckey', name: 'urlrewritefilter', version: '4.0.4'
compile group: 'org.eclipse.persistence', name: 'eclipselink', version: '2.4.1'
compile group: 'org.springframework', name: 'spring-webmvc', version: '3.2.2.RELEASE'
compile group: 'org.springframework', name: 'spring-tx', version: '3.2.2.RELEASE'
compile group: 'org.springframework', name: 'spring-orm', version: '3.2.2.RELEASE'
compile group: 'aopalliance', name: 'aopalliance', version: '1.0'
compile group: 'cglib', name: 'cglib', version: '2.2'
compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.6.10'
compile group: 'org.hibernate', name: 'hibernate-validator', version: '5.0.0.Final'
compile group: 'org.thymeleaf', name: 'thymeleaf-spring3', version: '2.0.16'
compile group: 'com.h2database', name: 'h2', version: '1.3.171'
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'org.springframework', name: 'spring-test', version: '3.2.2.RELEASE'
testCompile group: 'org.dbunit', name: 'dbunit', version: '2.4.9'
providedCompile group: 'javax.servlet', name: 'servlet-api', version: '2.5'
providedCompile group: 'javax.servlet.jsp', name: 'jsp-api', version: '2.1'
testCompile 'org.seleniumhq.selenium:selenium-chrome-driver:2.31.0'
testCompile 'info.cukes:cucumber-java:1.1.3'
testCompile 'info.cukes:cucumber-junit:1.1.3'
}
buildscript {
ext {
h2Version = '1.3.171'
}
repositories {
mavenCentral()
}
dependencies {
classpath "com.h2database:h2:$h2Version"
}
}
ext {
databaseDir = "${projectDir}/h2/database"
h2Args = ['-baseDir', "${databaseDir}"]
databaseName = 'bookstore'
databaseSchemas = ['dev', 'ut']
}
task h2Start(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'org.h2.tools.Server'
args = h2Args
}
[jettyRun, jettyRunWar]*.with {
reload = 'automatic'
additionalRuntimeJars = sourceSets.main.runtimeClasspath
// httpPort = 9000
}
def h2TcpServerStart = { args ->
org.h2.tools.Server.createTcpServer(args as String[]).start()
}
def server
[jettyRun, jettyRunWar]*.doFirst { server = h2TcpServerStart(h2Args) }
[jettyRun, jettyRunWar]*.doLast { server.stop() }
task bookstoreInit {
doFirst {
mkdir databaseDir
}
server = h2TcpServerStart(h2Args)
def runSqlScript = { File script, schema = '' ->
def url = "jdbc:h2:${server.URL}/${databaseName};${ schema ? "SCHEMA=${schema}" : '' }"
// println url
org.h2.tools.RunScript.execute(url, "sa", "", script.path, 'UTF-8', false)
}
runSqlScript file('db_schema/initdb.sql')
databaseSchemas.each { schema ->
runSqlScript file('db_schema/setup.sql'), schema
}
}
無事、IntelliJ IDEAでもcucumberを使えるようになりました。
また、h2databaseやjettyについてもtaskを追加しておいたお陰で、コマンドを実行するだけで起動や初期化が出来るようになりました。
途中でフィーチャファイルの補完が効いてないのかなと思いました。
が、IntelliJ IDEAを12.1.2から12.1.3に上げて見たところ、シンタックスハイライトとコードジャンプも出来るようになりました。
さすがJetBrains様です。
なんとか、ハンズオンの進行に付いていくことが出来ましたし、seleniumの残念な箇所も体験することが出来ました。
前回のBDDにてイマイチ使い所が分からなかったcucumberも、seleniumと組み合わせることでどうやって使ったら良いのか体験することが出来たのは良かったと思いました。
おわりに 懇親会では、
@enum さんも参加して下さり、とても楽しい充実した時間でした。
今回のハンズオンは、プレと冠していましたがとても実践的でスタートラインまで連れて行ってもらえる内容でした。
今後は、どうやってシナリオを書いて行ったら良いのかなど、教えていただいた書籍を参考にやってみようと思います。
また、Groovyでは
Geb があるので、これとSpockを組み合わせることで、seleniumの残念な箇所をカバーしてくれて、なおかつシナリオもコードで書けるようになるので、同じ課題を挑戦してみたいと思います。
講師の
@irof さん、著者の
@shuji_w6e さん、主催の
@shinyaa31 さん、参加者の皆さん、会場の横浜タネマキさん、ありがとうございました。
残りの章も少なくなって来ましたが、次回もよろしくお願いします。