「Jasmine」、「Node.js」、「jasmine-node」、「Jenkins」でJavaScriptをテストしてみた。
Javascriptのテストを「Jasmine」を使って実行して、Jenkinsで使ったみたメモです。
動きはしましたがあくまでNode.js用のjavascriptでないと動かないという結果になってしまっています。(方法はあると思いますが。。。)
それでも良い方は続きどうぞ。
また、Karmaを使用したテストではテスト対象のコードをそのまま実行する事ができました。
そのうちこちらもまとめますのでよかったらどうぞ。
目次
以下の順に時系列でダラダラ書いています。
- Jasmineインストール
- JavaScriptのコードをJasmineを使ってテスト
- Node.jsのインストール
- jasmine-nodeのインストール
- jenkinsインストール
- jenkinsでテスト
環境
OS | Windows7 Professional 32bit |
CPU | Core2 Duo 2.93GHz |
メモリ | 4GB |
Jasmine | 2.0.0 |
Node.js | v0.10.25 |
jasmine-node | 1.14.3 |
概要
きっかけ
お仕事で作っているアプリケーションでjsファイルを追加することになったのでテストやってみようって思った。
追加するjsには1つの関数しかないので、スモールスタートとしてはいいかなと。
アプリケーションの規模、用途を考えるとjsファイルが肥大化する事なんて考えられないのでお試しで導入もいいかなと。
今の会社はやりたいと言えば何でもOKだからほんと嬉しいし、楽しい!
Jasmineの選択理由
凄い人に聞いたらJasmineを勧められたため。
(他のフレームワークとの違い、メリットなどはよくわかりません。)
Jasmineとは
JasmineはJavascriptコードをテストするための振舞い駆動開発フレームワークです。他のJavascriptフレームワークに依存しませんし、DOMも必要としません。簡単にテストを書くことができるように、きれいで分かりやすい構文を持っています。
Jasmine: Behavior-Driven JavaScript
準備
モジュール取得
さっきからリンクを張っている日本語訳のページだとダウンロードページのリンクがおかしいので、公式のここの一番下の「Downloads」からダウンロードページに飛びます。
で、どうせなら最新版ということで「jasmine-standalone-2.0.0.zip」を落としました。
- https://github.com/pivotal/jasmine/tree/master/dist
- 2.0のzip選択してView Rawをクリックすると落ちてきます。
解凍
取得したモジュールを解凍
JASMINE-STANDALONE-2.0.0 ├MIT.LICENSE ├SpecRunner.html ├lib │└jasmine-2.0.0 │ ├boot.js │ ├console.js │ ├jasmine-html.js │ ├jasmine.css │ ├jasmine.js │ └jasmine_favicon.png ├spec │├PlayerSpec.js │└SpecHelper.js └src ├Player.js └Song.js
- SpecRunner.html : これを開いた時にテストが実行されて、結果が表示されます。
- lib/jasmine-2.0.0配下 : Jasmine本体
- spec配下 : テストファイル
- src配下 : テスト対象のファイル
本体のみかと思ったらサンプル一式入ってました。
Jasmine実行
サンプル実行
↑でも書きましたが、SpecRunner.htmlを開いたら実行されて結果が表示されます。
5個のテストケースを実行して失敗は0件と表示されているはず。
当然テストは全部成功していますし、テストコードもテスト対象のコードも見てないので正直よくわからない。
実践
サンプルを見てみたらなんとなくわかったけど、サンプル内で文字列比較とかないので失敗のケース作るのがめんどくさい。
なので、いきなりコード書いて、試してみる。
- テスト対象コード
function Hoge(a,b) { return a + b }
- テストコード
- ファイル名に「spec.js」をつける必要あり。
describe("Hogeクラス", function() { it("数字足し算", function() { expect(Hoge(1,2)).toEqual(3); }); it("文字列足し算", function() { expect(Hoge("a","b")).toEqual("ab"); }); it("テスト失敗", function() { expect(Hoge(1,2)).toEqual(5); }); });
- SpecRunner.htmlをコピーしてテスト対象とテストコードを追加。
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Jasmine Spec Runner v2.0.0</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png"> <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css"> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script> <!-- include source files here... --> <script type="text/javascript" src="src/Player.js"></script> <script type="text/javascript" src="src/Song.js"></script> <!-- include spec files here... --> <script type="text/javascript" src="spec/SpecHelper.js"></script> <script type="text/javascript" src="spec/PlayerSpec.js"></script> <!-- 追加メインコード --> <script type="text/javascript" src="src/Sample.js"></script> <!-- 追加テストコード --> <script type="text/javascript" src="spec/SampleSpec.js"></script> </head> <body> </body> </html>
で、適切な場所に保存してSpecRunner.htmlをコピーしたファイルを開くといい感じの結果。
結果画面
どうやらこんな感じらしい。
- 一番上はバージョン。
- 一番上の右に実行時間表示(テスト実行に時間がかかる場合には実行中とかは出ない。。。)
- 緑の●は成功で赤の×は失敗。
- 数を増やしたら単純に増えただけだった。。。
- バーが赤くなっていたら失敗しているテストケースがある
- Spec Listをクリックすると成功時と同じテストケース一覧を表示
- 最下部はテスト失敗時のスタックトレースを表示
ここまで参考にしたURL
Jenkinsとの連携(前書)
ユニットテストはJenkinsで行っているため、htmlでテスト出来てもしょうがない。
ということで、JasmineをJenkinsで動かすための手順を調べてました。
- JavaScriptなので、JavaScriptを動作させるエンジンが必要。
- で、ブラウザ、Node.js、PhantomJSなどがある。
- これらの環境で動作させるためにkarma、jasmine-nodeなどを使用する。(Node.jsの場合は直で動かすことができそうだけど、そう簡単にいかないのかしら?)
- Jenkinsにプラグイン入れてPATH指定したらできるんじゃないか。とか簡単に考えてたけど結構大変っぽい。
- 手間は手間だけど、こういうのは最初作っちゃえばなんとかなるさということで作る。
- ブラウザは起動が遅い上にバージョンとかに依存しそう、という事でボツ。
- Node.jsは少し触ったことがあって、他は全く知らないのでjasmine-nodeを使用してNode.js上で動作させる事に決定。
node.jsインストール
Node.js
私はWindowsなので、「Install」クリックしてインストーラでインストール。
「ダウンロード」からexeも落とせますが、インストーラの方がいいとどっかで見た気がするので大人しくインストーラ実行。
インストールできたらコマンドプロンプト開いてバージョン確認。
$ node -v v0.10.25
jasmine-nodeインストール
JasmineのテストをNode.jsで動作させるために「jasmine-node」をインストール。
npm install -g jasmine-node
npmはNode.jsのパッケージ管理ツールで、「node.exe」と同じPATHにあるのでNode.jsのバージョン表示されていれば動作するはず。
インストールできたらコマンドプロンプト開いてバージョン確認。
$ jasmine-node --version 1.14.3
jasmine-nodeでテスト実行
とりあえず実行
早速↑で作ったコードを動かしてみる。
$ jasmine-node ./spec/SampleSpec.js FFF Failures: 1) Hogeクラス 数字足し算 Message: ReferenceError: Hoge is not defined Stacktrace: ReferenceError: Hoge is not defined at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:5:12) 2) Hogeクラス 文字列足し算 Message: ReferenceError: Hoge is not defined Stacktrace: ReferenceError: Hoge is not defined at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:8:12) 3) Hogeクラス テスト失敗 Message: ReferenceError: Hoge is not defined Stacktrace: ReferenceError: Hoge is not defined at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:11:12) Finished in 0.024 seconds 3 tests, 3 assertions, 3 failures, 0 skipped
っということでテストする関数がないよって事で失敗。(1行目に出力されている「FFF」はHTMLでいう●らしい。)
そりゃ、テスト対象のjsを指定してないので当たり前。
Node.jsの機能?でexports、requireがあるので、これを行うことで紐付けます。
- テスト対象クラス
function Hoge(a,b) { return a + b } exports.Hoge = Hoge;
- テストクラス
- requireで指定するファイルPATHはテストクラスからの相対PATHです。(ここで設定するとわかるけど、jenkinsに設定後だとworkspaceからと勘違いしてしまったので一応。)
var Hoge = require('../src/Sample.js').Hoge; describe("Hogeクラス", function() { it("数字足し算", function() { expect(Hoge(1,2)).toEqual(3); }); it("文字列足し算", function() { expect(Hoge("a","b")).toEqual("ab"); }); it("テスト失敗", function() { expect(Hoge(1,2)).toEqual(5); }); });
再実行
上記の設定後に再実行。
$ jasmine-node ./spec/SampleSpec.js ..F Failures: 1) Hogeクラス テスト失敗 Message: Expected 3 to equal 5. Stacktrace: Error: Expected 3 to equal 5. at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:11:23) Finished in 0.076 seconds 3 tests, 3 assertions, 1 failure, 0 skipped
正しく実行されて、1件のテスト失敗がわかります。
Jenkinsインストール & 起動
いきなり動いているJenkinsでやるのもどうかと思うのでローカルにJenkins導入。
- モジュール取得
- コマンドプロンプト開く
- 「java -jar jenkins.war」
- ブラウザで「http://localhost:8080/」確認
Jenkins設定
Job作成
- 新規ジョブ作成
- ジョブ名適当に入力
- 「フリースタイル・プロジェクトのビルド」選択
- OK
設定といきたいけどファイル配置
本来はバージョン管理システムから取得する所だけど、この段階ではそんなものないので手動でworkspaceに配置。
- 私の環境だと↓
- 「C:\Users\${ユーザ名}\.jenkins\jobs\${ジョブ名}\workspace\」
- 私は以下のように配置しました。
C:\Users\${ユーザ名}\.jenkins\jobs\${ジョブ名}\workspace └test ├lib │└jasmine-2.0.0 │ ├boot.js │ ├console.js │ ├jasmine-html.js │ ├jasmine.css │ ├jasmine.js │ └jasmine_favicon.png ├spec │└SampleSpec.js └src └Sample.js
ジョブの設定 & 実行
- ビルド部の「ビルド手順の追加」
- 「Windowsバッチコマンドの実行」を追加
- コマンド
jasmine-node test\spec\SampleSpec.js
- 保存
- ビルド実行
- 以下の感じで出力されればOK(日本語が化けているのは気にしない。。。)
ユーザーanonymousが実行 ビルドします。 ワークスペース: C:\Users\yamap\.jenkins\jobs\Sample\workspace [workspace] $ cmd /c call C:\Users\YAMAP\AppData\Local\Temp\hudson5171352823916894994.bat C:\Users\yamap\.jenkins\jobs\Sample\workspace>jasmine-node test\spec\SampleSpec.js ..F Failures: 1) Hoge繧ッ繝ゥ繧ケ 繝�繧ケ繝亥、ア謨� Message: Expected 3 to equal 5. Stacktrace: Error: Expected 3 to equal 5. at null.<anonymous> (C:\Users\yamap\.jenkins\jobs\Sample\workspace\test\spec\SampleSpec.js:15:23) Finished in 0.022 seconds 3 tests, 3 assertions, 1 failure, 0 skipped Build step 'Windowsバッチコマンドの実行' marked build as failure Finished: FAILURE
レポート出力
コンソールに出力されてもどうしようもないのでJUnit形式でレポート出力を行う。
- 設定変更
- コマンド
jasmine-node test\spec\SampleSpec.js --junitreport --output "reports"
-
- ビルド後の処理に「JUnitテスト結果の集計」を追加
reports\*
- 保存
- ジョブ実行(相変わらずコンソール上では日本語が化ける。。。)
ユーザーanonymousが実行 ビルドします。 ワークスペース: C:\Users\yamap\.jenkins\jobs\Sample\workspace [workspace] $ cmd /c call C:\Users\YAMASH~1\AppData\Local\Temp\hudson941930116661068781.bat C:\Users\yamap\.jenkins\jobs\Sample\workspace>jasmine-node test\spec\SampleSpec.js --junitreport --output "reports" ..F Failures: 1) Hoge繧ッ繝ゥ繧ケ 繝�繧ケ繝亥、ア謨� Message: Expected 3 to equal 5. Stacktrace: Error: Expected 3 to equal 5. at null.<anonymous> (C:\Users\yamap\.jenkins\jobs\Sample\workspace\test\spec\SampleSpec.js:11:23) Finished in 0.028 seconds 3 tests, 3 assertions, 1 failure, 0 skipped Build step 'Windowsバッチコマンドの実行' marked build as failure テスト結果を保存中 Finished: FAILURE
- テスト結果が出力されていればOK
問題
- Jenkinsのコンソール上で日本語を正しく表示させたい(レポートは化けてないので別に問題はないですが。)
- 以前別のプラグインでハマったんだけど解決策は忘れたw
- そもそもテスト対象コードに手を入れたくない。
- Node.js以外の環境だとexportsメソッドが定義されていないので動かない。(jasmine付属のHTMLでの実行も同じ理由でNG。)
- 色々試したけどNode.jsで動作させるのでexportは書く必要があるっぽい(別のファイルから指定できると思うけど方法がみつからず。)
GebのグループIDは0.9.0で変更されている
GebのグループIDは0.9.0で以下のように変更されています。(2014/04/17時点での最新版は0.9.2)
リリースノートがどこにあるのかわかりませんでしたが、0.9.0のマニュアルの記述が変更されています。
dependencies { test "org.gebish:geb-spock:0.9.0" } plugins { test ":spock:0.7" test ":geb:0.9.0" }
dependencies { test "org.codehaus.geb:geb-spock:0.7.2" } plugins { test ":spock:0.5-groovy-1.7" test ":geb:0.7.2" }
Gebは参考にする記事が少ない事もあって、大体の記事では「org.codehaus.geb」と書いてあります。
これから触る方は注意が必要!!
selectが実用的じゃない位遅いし。。。
Mapの初期化でKeyをGStringにした場合、getメソッドを使用しないと値を取得できない。
表題の通り。
Mapの初期化時には変数名を直接指定できないので、GStringで対応していたらハマった。
- っというか、元々はcollectEntriesイジっててハマったのでcollectEntriesがおかしいって記事まで書いてた。。。
環境
$ groovy -version Groovy Version: 2.2.2 JVM: 1.8.0 Vendor: Oracle Corporation OS: Windows 7
- 2.3.0-beta-2でも発生しました。
現象
言葉で説明は下手くそなのでコードで。
def key1 = "a" // 変数は直接指定できない(文字列のKeyとして処理される) def map1 = [key1:"a"] assert map1 == ["key1":"a"] // GStringは別のKeyとして認識される def map2 = ["${key1}":"a"] assert map2 != ["a":"a"] assert map2 == ["${'a'}":"a"] assert map2.keySet()[0].class == org.codehaus.groovy.runtime.GStringImpl // StringとGStringの型 def key2 = "${key1}" assert key1.class == java.lang.String assert key2.class == org.codehaus.groovy.runtime.GStringImpl // containsKeyはGStringで格納されているとの事。 assert !map2.containsKey(key1) assert map2.containsKey(key2) // StringでもGStringでも取得できない assert map2[(key1)] == null assert map2[(key2)] == null assert map2.(key1) == null assert map2.(key2) == null // 直接getメソッドを呼ぶと取得が可能 assert map2.get("a") == null assert map2.get("${'a'}") == "a"
つまり、GStringを使用してMapを初期化するとStringではなくてGStringとして格納されるため、Stringで取得しようとしてもダメ。
では、GStringで指定しても[]の呼び出しは(getAtメソッド)Groovyがいい感じにStringに変換してくれているようなのでこれもダメ。
Javaメソッドのgetを直接呼ぶことでGStringをそのまま渡せるので習得ができます。
初期化以外の処理では、GStringはStringに変換されて格納されるため、格納時にも取得時にも問題は発生しません。
def key1 = "a" def key2 = "${key1}" // 初期化以外では変数はそのまま指定可能 // GStringもStringに変換されて格納される。 def map3 = [:] map3[key1] = "a" map3[key2] = "b" assert map3.size() == 1 assert map3[key1] == "b" assert map3[key2] == "b" assert map3.keySet()[0].class == java.lang.String assert map3.get(key1) == "b" assert map3.get(key2) == null
正直この挙動はどうなんでしょう。。。?
回避策
変数使いたいだけなら()を使用する事で回避可能。
文字列の結合が必要ならば「as String」でStringに変換する。
def key1 = "a" def map4 = [(key1):"a"] assert map4 == ["a":"a"] assert map4 != ["${'a'}":"a"] assert map4[key1] == "a" assert map4[key2] == "a" def map5 = [("${key1}_${key2}" as String):"a"] assert map5 == ["a_a":"a"] assert map5 != ["${'a_a'}":"a"] assert map5["a_a"] == "a" assert map5["${'a_a'}"] == "a"
参考
ここまで色々回り道して調べたんですが、下書き書いてからもう一回ググったらふもさん(id:fumokmm)のblogが出てきた。
5年前に調べてくれてるじゃないですかーやだー
しかも、id:uehajさんがJIRAまで調べてくれてるじゃないですかー
Groovyでマップのキーに文字列を指定する際の注意点 - No Programming, No Life
5年前でなおってないなら仕様ですね。
これわかりづらいと思うんですが。。。
GebでSelect要素の選択が遅い
追記(2014/04/17)
解決しました。
id:kyon_mmさんがコメントで指摘くださいました。
0.9.0で修正されているらしいのでバージョンを上げればよし。
具体的には「@Grab("org.codehaus.geb:geb-core:*")」を「@Grab("org.gebish:geb-core:0.9.2")」と変更すればOK。
詳しくは別記事にも書いたので興味のある方は↓
概要
SeleniumのGroovyのラッパーであるGebを使っていたのですが、Select要素を設定すると物凄く遅い。
っというか、使い物にならないくらい遅い!!
下記のコードを実行すると、Seleniumを直で使用した場合は500ミリ秒程度ですが、Gebの方は8000ミリ秒程度もかかります。
環境
OS | Windows7 Professional 32bit |
CPU | Core2 Duo 2.93GHz |
メモリ | 4GB |
Groovy Version | 2.2.2 |
Java Version | 1.8.0 |
firefox | 27.0.1 |
HTML
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <select id="year"> <option value='-'>-</option> <option value='1900'>1900</option> <option value='1901'>1901</option> <-- 中略 --> <option value='2013'>2013</option> <option value='2014'>2014</option> </select> <select id="month"> <option value='-'>-</option> <option value='01'>01</option> <option value='02'>02</option> <-- 中略 --> <option value='11'>11</option> <option value='12'>12</option> </select> <select id="day"> <option value='-'>-</option> <option value='01'>01</option> <option value='02'>02</option> <-- 中略 --> <option value='30'>30</option> <option value='31'>31</option> </select> </body> </html>
コード
@Grapes([ @Grab("org.seleniumhq.selenium:selenium-java:*"), @Grab("org.seleniumhq.selenium:selenium-support:*"), @Grab("org.seleniumhq.selenium:selenium-firefox-driver:*"), @Grab("org.codehaus.geb:geb-core:*"), ]) import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.By import org.openqa.selenium.support.ui.Select import geb.Browser import geb.Configuration println "start" def driver = new FirefoxDriver() driver.get("http://jsbin.com/sucumuqu/2/") def now = new Date() def year = new Select(driver.findElement(By.id("year"))) year.selectByVisibleText("1950") def month = new Select(driver.findElement(By.id("month"))) month.selectByVisibleText("08") def day = new Select(driver.findElement(By.id("day"))) day.selectByVisibleText("15") println "${new Date().time - now.time}" driver.quit(); Configuration conf = new Configuration() conf.baseUrl = "." conf.driver = new FirefoxDriver() Browser.drive(conf) { go "http://jsbin.com/sucumuqu/2/" now = new Date() $("#year").value("1950") $("#month").value("08") $("#day").value("15") println "${new Date().time - now.time}" quit() } println "end"
しょうがないので、driverを取得して直接操作するとほぼ同じ時間で処理が完了する。(当たり前)
@Grapes([ @Grab("org.seleniumhq.selenium:selenium-java:*"), @Grab("org.seleniumhq.selenium:selenium-support:*"), @Grab("org.seleniumhq.selenium:selenium-firefox-driver:*"), @Grab("org.codehaus.geb:geb-core:*"), ]) import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.By import org.openqa.selenium.support.ui.Select import geb.Browser import geb.Configuration println "start" def driver1 = new FirefoxDriver() driver1.get("http://jsbin.com/sucumuqu/2/") def now = new Date() def year = new Select(driver1.findElement(By.id("year"))) year.selectByVisibleText("1950") def month = new Select(driver1.findElement(By.id("month"))) month.selectByVisibleText("08") def day = new Select(driver1.findElement(By.id("day"))) day.selectByVisibleText("15") println "${new Date().time - now.time}" driver1.quit(); Configuration conf = new Configuration() conf.baseUrl = "." conf.driver = new FirefoxDriver() Browser.drive(conf) { go "http://jsbin.com/sucumuqu/2/" now = new Date() year = new Select(driver.findElement(By.id("year"))); year.selectByVisibleText("1950"); month = new Select(driver.findElement(By.id("month"))); month.selectByVisibleText("08"); day = new Select(driver.findElement(By.id("day"))); day.selectByVisibleText("15"); println "${new Date().time - now.time}" quit() } println "end"
セレクタが遅い?ただ、テキストボックスやラジオだとそこまで遅いとは感じないのでセレクトボックス特有の原因かな?
ソース読めっていう話なんだけど。。。
「祝☆Java 8 Launch」に行ってきた #JJUG
3/18にリリースされたJava SE 8を勉強するためにJJUGの勉強会に参加してきました。
- 概要
- Togetter
何回かOracleに来てますが、2部屋ぶちぬきでしかもテーブルなしというのははじめてでした。
っと思ったら、MAX300人はOracle初だったらしいです。
最初にまとめ
メモが長くなってしまったので、最初にまとめ。
祝 Java SE 8 正式リリース
13:00〜13:30 祝 Java SE 8 正式リリース 寺田 佳央(@yoshioterada) 日本オラクル Java エバンジェリスト 2011 年 7 月に Java SE 7 がリリースされ、ついにJava SE 8 が正式にリリースされました。Java SE 8 では目玉機能である Project Lambda の他、JavaFX の統合、新規 JavaScript エンジンの提供など、50 を超える機能が追加もしくは改善されています。 本セッションは Java SE 8 の概要をわかりやすくご紹介します。
- テクニカルの話はない。
- 今日の話で出てこない話をする。
- 135枚のスライドは全部紹介できないので、blogに書くのでそっちを見てくれ。
- JavaSE 7を出す時に全部ひっくるめて出すか、段階的にリリースしていくか。
- 段階的にリリースしていくことに決定。
- SE7 2011年7月28日リリース
- 会場にいる方の現在使用Javaバージョンの調査。
- 7が圧倒的。
- 1.4の人も何人か。
- 2012年7月17日
- JigsawはJavaSE9へ持ち越し。
- 2013の年始から中旬までOracleのトップ判断で、セキュリティ脆弱性対応に集中。
- スケジュールをずらしても構わないとの事。
- 2014年4月26日
- 2014/03/18にリリース決定。
- JSR-337 : Java SE8
- JavaSE8にすることのメリットは多くある。
- クラスファイルのフォーマットなども変わってる。
- パフォーマンスを上げるための機能、既存のライブラリにも修正が。
- メモリの使用量も減っているらしい。
- 新機能を使用しなくても、メリットはたくさんある。
- Compactプロファイル。(ファイルサイズが異る。)
- 各APIにどのプロファイルで利用可能か記載されている。
- 参考資料
- Java7のサポートも来年4月に変わっている。
今後のJava関連イベント
5月のJava祭り
- Java Day Tokyo開催決定
- 2014/5/22
- Java Day Tokyo 申し込み開始
- 2014/04/02
- JJUG CCC Spring
- ベルサール西新宿
- 2014/05/18
- Raspberry Pi ハンズオン
- 2014/05/23
まとめ
新機能だけじゃなくて、色々加わってる。
楽になってるし、早くもなっている。
徹底解説!Project Lambdaのすべて リターンズ
13:30〜14:20 徹底解説!Project Lambdaのすべて リターンズ 発表者:吉田 真也(@bitter_fox) 立命館大学 立命館コンピュータクラブ Java 8 における最大級のプロジェクトであるProject Lambda で導入された言語特徴のすべてを解説します。また、Project Lambda で導入されたStream API も解説します。 なぜその特徴を導入しなければいけないかや他の特徴とどのように関連しているのかについても説明しますので、より広い視野でProject Lambda を理解することができます。 Project Lambda のそれぞれの特徴と全体像を理解できるセッションです。
- Lambdaの開発者にツッコミを入れたりしてるらしい。
- 大学生。立命館大学。
- アップデートには2種類ある
- エボリューション
- レボリューション
- 日本語的には進化と革命
- Jdk5以来、レボリューションは10年ぶり2004年ぶり。
- ラムダは、並列処理を容易に書けるように増強。
- ライブラリ、言語
- マルチコアCPU
- クロック数はそのまま、コア数を増やす。並列処理。
- 並列プログラミングをしないと、性能を活かすことが出来ない。
- 並列処理
- Java5で大きな粒度 簡単
- Java7で小さな粒度 やや難
- 全てプログラマが欠かないといけないから難しい。
- Java7で小さな粒度 やや難
- 処理を分けるだけで5行(匿名クラスを使用)
- 言語的に解決する必要がある。
- ラムダ式の導入
- 言語的に解決する必要がある。
- ライブラリの増強
- 度公開されたインターフェイス
- 変更を加えにくい → デフォルト実装
- 全体像、ラムダの全体で7個。
ラムダ式・メソッド参照
実質的にfinal
交差型キャスト
- キャスト式に交差型を。
- T extends
- 型合成される
- ぶっちゃけ使わないwww
- APIでも使用してるクラスは5個
デフォルト実装
コアライブラリ
- StreamAPI
- Optional
- JCF
- IO
- And more
- StreamAPI
- イテレーションが外に晒されている
- for,while文
- StremAPI
- 並列化が簡単に行える。
- java.util.stream
- ソースから生成される。
- 中間操作と終端操作でデータを弄る。
- 並列化が容易
IntStream.rangeClose(0,10).forEach(i -> System.out.println(i)); // 偶数のみ表示 IntStream.rangeClose(0,10).filter(i->i%2==0).forEach(...) // Personのリストから名前を出力 // map persons.stream().map(p-> p.getName()).forEach(....) // Personのリストから名前のリスト persons.stream().map(Person::getName).collect(p-> )
まとめ
- 元々はマルチコア対応
- 結果としては汎用的な仕様に
- よりスマートなコードへ
null書いたら負け!Java8コーディング作法
14:30〜15:20 null書いたら負け!Java8コーディング作法 発表者:きしだ なおき(@kis) 負けだよ。
- null書いたら負け!
- Streamはコーディング規約で禁止でもいい
- Date and Timeはよくわからない
だが、nullお前だけはダメ。
- java.util.Optional
- 値を持つか持たないかを判別。
- nullのある世界とない世界の分離
- nullを使っていいところ悪いところ
- 良い
- ローカル変数
- 微妙
- 引数
- 悪い
- フィールド
- 戻り値
- nullを外に漏らさなければOK
覚えて欲しいのは
nullを返すメソッドを書いたら負け。
Java8の他の作法
- Streamでの注意
- メソッド参照とラムダの使い分け
- 遅延実行を活かす
- Mapを活用する
- 制御構造を自作する
- Streamでの注意
- 副作用に気をつける
- メソッドの中でメソッドの外に影響を与えない
- 副作用を使う基準
- 中間操作×
- 終端操作
- reduce △
- forEach ○
- 遅延実行を活かす
- 値が使われる可能性の低い引数の構築に時間がかかる時
logger.debug(bigObject.toString()); logger.fine(()->bigObject.toString());
-
- Optional
- Optional#orElseGet
- Optional#orElseThrow
- 使う可能性が低い時はラムダにしとけば、使うときにのみ実行してくれる?
- Optional
- Mapを活用する
- Map>
- 追加
- Map#computelfAbsent
- Mapが空だった時にその値を突っ込んで返してくれる?
- 削除
- Map#computerlfPresent
- メモ化
- Map#computelfAbsent
- 値があればその値、なければ計算を行って結果をMapに格納しつつ返す。
- 制御構造を自作する
- カスタムwith
- カスタム分岐
- カスタムマッチ
- カスタムループ
- メソッド参照とラムダの使い分け
- メソッド参照は引数を隠す。
- 読み解くにはコンテキスト理解が必要。
- メソッドに渡すためのメソッド○
- 引数一つのメソッド△
- 引数複数のメソッド×
Brand new Date and Time API
15:30〜16:20 Brand new Date and Time API 発表者:蓮沼 賢志(@khasunuma) JSR 310 オブザーバー Java Community Process (JCP) では、2007 年から Java の日付と時刻の扱いを改善する JSR 310 “Date and Time API” を開始し、7 年の歳月を経て Java SE 8 の標準 API として結実しました。これまでの Date や Calendar とは全く異なる思想で開発された最新の日付・時刻 API を今日から活用して頂けるよう、このセッションがお手伝いを致します。
JavaFX – GUI by Illusion
16:30〜17:20 JavaFX – GUI by Illusion 発表者:櫻庭 祐一(@skrb) Java in the Box Java SE 8 では、Swing に代わり JavaFX が標準の GUI ライブラリとなります。 JavaFX は、XML で GUI の構造を記述し、CSS で見た目を、Java でロジックを記述するようになります。また、組み込みブラウザやチャートなど多くの機能が提供されています。 本セッションでは、JavaFX の基本から、Swing からのマイグレーション、JavaFX 8の新機能などを、デモを交えて紹介します。
- 今までJavaに無かったエフェクトを入れるよということでJavaFX
- "%jre%\lib\calendars.properties"に和暦とかを追加することができる。
- JavaFXって何
- Swingからの移行
- JavaFX 8の新機能
- JavaFXって何
- SceanBuilder
- EclipseはeFXclipseで連携できるらしい。
- Browser
- 3行
WebView view=new WebView(); WebEngine engine = view.getEngine(); engine.load("http://www.google.com");
- Media
- 標準的な形式は大体動く
- Effect
- 一通りできる
- Animation
- 当たり前のように動く
- Touch Gesture
- 1行で回転!1行でズーム!
- robovmっというの使えばIOSで動作するように変換できるらしい。
- Swingからの移行
- 構造は殆ど同じ、
- ただ、FXMLでかけるよ!
- 各クラスに関してもJを除いたり、似た名前であります。
- 属性とかも殆どそのまま使える。
- TableやTreeに関しては考え方が変わってるので鬼門になるかも。
- JavaFX8
- 3Dを簡単に説明
- FXは新しいGUIライブラリなんだよ
- FXML-CSS-Javaで書ける
- いろいろ新しいのが入ったよ。
- Swingから簡単に移行できるよ。
- JavaFX8は色々すごいよ!
- OpenJDKでも動く。
from old Java to modern Java – reloaded
17:30〜18:20 from old Java to modern Java – reloaded 発表者:谷本 心(@cero_t) Acroquest Technology Java SE 8がリリースされるというニュースを目にしても「どうせ仕事では使えないし」と冷ややかに見ていませんか? 確かに開発の現場では、様々な制約のために古いバージョンのJavaを使わざるを得ないことがあります。しかしだからと言って学ばないままでいると、いざ新しいバージョンのJavaを使おうという時に、ついつい古いAPIを使ってしまったり、古い慣習に従って書いてしまうことになるでしょう。 このセッションでは、JavaのAPIや慣習について、古い時代のものからJava8までの歴史を振り返りながら、イマドキの書き方を紹介します。
- 仕事でJava8を使おうと思った時に何を気をつければいいのか。
- 老害にならないためのJava8入門。
- ラムダで欠かれたコードをレビューした時に読みにくいと言わないように勉強しなければならない。
- finallyでCloseするのは古い定石(〜Java6
- tryの中で開く。(〜Java7
- FilesとかPathクラスとか使わないとダメだよね。
- try-with-resourcesとFilesとPathで操作する。(Java7〜
Files.lines(Paths.get(fileName)).forEach(s-> lines.add("<" + s + ">"));
- forやwhileをみたらStream APIへの置換えを考える。
- ラムダでmapとcollectはよく使う。(Streamはここから始める)
- 何でもかんでもLambdaにすればいいわけじゃない。
- 「ラムダ禁止」でググる。
- ラムダのAPIをもっと便利に使うことができる。
まとめ
自分たちの標準としてどうすれば読みやすくするかチームで考えよう!
Java本格入門(仮)鋭意執筆中!
Raspberry Pi on Java ショートアップデート
18:20〜18:30 Raspberry Pi on Java ショートアップデート 発表者:太田 昌文(@masafumiohta) Japanese Raspberry Pi Users Group 昨年度のリリースからRaspberry PiにOracle Javaが標準パッケージとしてインストールされるようになりました!Raspberry Pi Foundation FounderであるEben UptonもPythonの他JavaもRaspberry Piで使えるプログラミング言語として注目をしております。ここではごく簡単にRaspberry Piのご紹介とJava Embedded on Raspberry Piのアップデートについてお話しいたします。
コマンドプロンプトの代わりにckw + NYAOSを使ってみた。
コマンドプロンプトの代わりになるコンソールckwとUnixライクのコマンドを使えるNYAOSをつかってみました。
コマンドプロンプトでls、pwdがないとか、コピペが云々とか、横幅が、見栄えが、とか思う所があるならば使ってみるとよいかも。
インストールと設定
ckw ├ChangeLog.txt ├ckw.cfg ├ckw.exe ├licence.txt ├nyaos.exe ├nyaos_en.txt ├nyaos_ja.txt ├ReadMe.txt ├_nya └_nya.d ├cmdsource.lua ├compatible.ny ├exever.lua ├fc.lua ├forvimshell.lua ├gpath.lua ├gui_cd.lua ├ln.lua ├lnk.lua ├lslua.lua ├mount.lua ├quote_eval.lua ├quote_luaexp.lua ├readme.txt ├which.lua └opt ├auto_cd.lua ├browse.lua └vz.ny
- ckw.cfgを編集
Ckw*title: ckw[cmd] Ckw*exec: cmd.exe
の箇所を↓に編集。
Ckw*title: ckw[nyaos] Ckw*exec: nyaos.exe
- 配色を変えたい場合には適当に色を変更。私は↓を参考にしました。
Windowsのコマンドプロンプトをフリーソフトで便利にする - ナレッジエース
- _nyaを編集
_nyaの最下部に下記を追記(パスは適当に変更してください。)
option savehist "C:\tools\ckw\.history"
- 適当な箇所にckwディレクトリを配置
サクラエディタで新規ファイルをUTF-8で開く方法。
サクラエディタで新規ファイルを開く際にデフォルトだと「SJIS」で開こうとするので、保存時に変えるのがめんどくさい。
なので、デフォルトで変更したい。
どこかで設定できるだろうけど、設定項目多いのでグーグル先生で検索。
バージョン2.0.4.0 以降であれば
設定(O) > タイプ別設定(Y) > 「支援」タブ > 「デフォルトの文字コード」
サクラエディタを開いた時の文字コードをUTF-8にする方法 - 零弐壱蜂
で UTF-8 へ変更が可能です。
バージョンは2.1.0.0なのにない。
念のため最新版の2.1.1.1にしてみたけどない。
何か不具合でもあって消された?
なので、マクロ組みました。
新規時と、空のファイルはUTF-8で開きます。
if (ExpandParameter('$F') == '(無題)' || GetLineCount(0) == 0) { FileReopenUTF8(0); }
独自関数とか知らないので↓を参考にしました。
マクロの設定は↓参照。