Tumblrの新しいエリア。なんかスゴイ無駄にしようとしてくれているが、キーボードショートカットが効かないとか……つらいだけになってる。
つ ありがた迷惑
almost home

if i look back, i am lost

shark vs the universe
KIROKAZE
"I'm Dorothy Gale from Kansas"
TVSTRANGERTHINGS

occasionally subtle
Monterey Bay Aquarium

@theartofmadeline

Kaledo Art

Andulka
Jules of Nature

Product Placement
trying on a metaphor

#extradirty
Cosimo Galluzzi

seen from United States
seen from United States
seen from United States

seen from United States
seen from Türkiye
seen from China
seen from Canada
seen from Australia

seen from United States
seen from United States
seen from Netherlands

seen from Japan
seen from Belarus
seen from United States

seen from Canada
seen from Türkiye

seen from Canada
seen from France

seen from United States
seen from Malaysia
@niwaringo
Tumblrの新しいエリア。なんかスゴイ無駄にしようとしてくれているが、キーボードショートカットが効かないとか……つらいだけになってる。
つ ありがた迷惑

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Sauce Labsが1,500万ドル調達したらしい。めでたい
同時上限数を超えずにKarmaでSauceLabsのテストをする方法
JavaScriptのテストランナーとしてKarmaは非常に便利です。クロスブラウザのテスト環境としてSauce Labsは非常に素晴らしいです。
この二つが組み合わされば最高なんですが、多くのブラウザでテストしようとするとエラーが発生します。
Having many browsers fails · Issue #40 · karma-runner/karma-sauce-launcher
Sauce Labsには同時接続上限数が設定(OpenSauceなら3とか)されているのですが、Karmaの並列処理がこの上限数を超えてアクセスするとエラーになります。そして、Karmaには接続上限を制限する機能がありません…… Issueとして上がっているのでそのうち修正される事を期待しますが!!
前提条件
まず、Karmaを使ったSauce Labsでのテストについてまとめます。
KarmaでSauce Labsのテストをするにはkarma-sauce-launcherというプラグインを利用します。
karma-runner/karma-sauce-launcher
で、公式の説明によると、このプラグインはcustomLaunchersに複数のブラウザをセットして、browsersでブラウザを複数一括で指定するという方法です。
module.exports = function(config) { // Example set of browsers to run on Sauce Labs // Check out https://saucelabs.com/platforms for all browser/platform combos var customLaunchers = { sl_chrome: { base: 'SauceLabs', browserName: 'chrome', platform: 'Windows 7', version: '35' }, sl_firefox: { base: 'SauceLabs', browserName: 'firefox', version: '30' }, sl_ios_safari: { base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.9', version: '7.1' }, sl_ie_11: { base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 8.1', version: '11' } }; config.set({ // The rest of your karma config is here // ... sauceLabs: { testName: 'Web App Unit Tests' }, customLaunchers: customLaunchers, browsers: Object.keys(customLaunchers), reporters: ['dots', 'saucelabs'] singleRun: true }); };
こんな感じ。
発生する状況
設定ファイルをみると、browsersはObject.keys(customLaunchers)となっているので、customLaunchersのkeyを配列で設定しています。で、これが一斉に並列実行されるためSauce Labsの同時接続上限を超えてしまってエラーになるという塩梅のようです。
解決策
スマートな解決作が思いつかず…… chlid prosessでコマンドを順番に実行するという方法を取りました。
具体的には、まず、別ファイルでブラウザの一覧をセットします。(saucebrowsers.js)
そのうえで、実行用のファイルを用意して(saucebrowsers.js)、その中で再帰的に1ブラウザ毎にプロセスを実行します。プロセス内で使うブラウザの名称はprocess.env.sauce_browser_nameのようにしておきます。
その上で、karma.conf.js側では、process.env.sauce_browser_nameを受け取ってbrowsersで指定します。
こうしておいて、
node saucerunner.js
として実行すれば同時接続上限にかからずにテストすることが出来ました。
こんな感じです。Karmaが治るまではコレでいきます。
protractorを使ったe2eでのcookieテスト
最近ちょこちょことcookieのライブラリを作っていて困ったのがcookieのテストです。
やりたい事は、
アプリではなくライブラリのcookieのテスト
saucelabsでマルチブラウザのテストを自動化したい
という2点でした。
cookieの仕様上オプション部分のテストが困難
cookieはname,valueという必須要素に加えて、domain,path,expires,secure等のオプション要素を持っています。
そして、このオプション要素はJavaScriptから設定できるのですが、取得する事ができません。
例えば、
document.cookie = 'name=value; domain=.google.com; path=/'
と設定する事は出来ても、
document.cookie // -> name=value
取得できるのはname,とvalueのみです。
このため、Karmaのようなテストランナーでは正しくオプションを設定できているのか?というテストをすることが出来ません。
Seleniumを使ったCookieのテスト
そのためオプションを含めたテストをする場合は、Seleniumを使うことにしました。
selenium-server-standaloneをローカルで立ち上げてWebDriverを使ってテストする事でcookieのオプションを含めた確認をする事ができます。
利用するjavascriptファイルを読み込むhtmlファイルを作成して、そこにWebDriverを使ってアクセスして確認します。
protractorというe2eテストフレームワーク
WebDriverを使ったテストする時にオススメしたいテストフレームワークは「protractor」です。 protractorはangular.js用に作られたテストフレームワークですが、angular.jsを使わない場合でも非常にオススメです。browser.ignoreSynchronization = true;とする必要がありますが :|
webdriver周りのサポートが手厚い
protractor一番のおすすめポイントはWebDriver周りのサポートが非常に手厚い事です。
WebDriverを使う時はstandalone serverをダウンロードして、それを立ち上げて……等など心が折れるフラグがここかしこに散りばめられています。
これが、protractorを使うと、
npm i -D protractor
でインストールして、
./node_modules/protractor/bin/webdriver-manager update
とするとstandalone serverをダウンロードしてきてくれます。
あとは、
./node_modules/protractor/bin/webdriver-manager start
でサーバーをスタートして
./node_modules/protractor/bin/protractor /path/to/configfile
でテストを実施できます。上記のWebDriver周りを全てprotractorのエコシステムを利用することが可能になります。
promiseをいい感じにしてくれる
WebDriverJS のAPIは基本的にはpromiseで構築されていて、control flowというのでいい感じにしてくれます。protractorはこの流れにそって非常にテストが書きやすくなっています。
そんため、
it('read', function() { browser.executeScript(function() { document.cookie = 'name=value'; }); var cookie = browser.executeScript(function() { return tongs.cookie('name'); }); // console.log(cookie) <= promiseが帰ってくる expect(cookie).toEqual('value'); });
のように書いても、promiseをいい感じに処理してテストしくれます。注意すべきは実体はpromiseなので、上記でいうとconsole.log(cookie)などとすると、return tongs.cookie('name')の戻り値ではなく、promiseが戻ってきます。
saucelabsサポート
設定ファイルにsaucelabsの情報を記載しておけば、saucelabsを使ったテストを実施してくれます。
sauceUser: ***, sauceKey: ***,
並行処理もいい感じにキュー管理してくれているっぽい? karmaは並行処理が多すぎて途中でエラーになっていたけれどprotractorではそのような事は起きませんでした。
IEとSafariはselenium経由でexpiresが取れない
今回、一番ハマったのがココ。IEとSafariのドライバーはexpiresが取れないようです。
Issue 3456 - selenium - Expiry date for Cookie not returned for InternetExplorerDriver - Browser automation framework - Google Project Hosting
ココに気づかずに、実機ではエラーが出ないのに……と悶々と調査・コードの書き変えをしていました。
結論としては、テスト内でchromeとfirefoxの分岐を入れて、chromeとfirefoxだけでoptionのテストをするようにしました。
var optionExec = function(callback) { browser.getCapabilities().then(function(s) { if (s.caps_.browserName.match(/chrome|firefox/)) { callback(); } }); }; optionExec(function() { // set cookie and get Date it('expires(date)', function() { var date = browser.executeScript(function() { var tom = new Date(); tom.setDate(tom.getDate() + 1); tongs.cookie('name', 'value', {expires: tom}); return Math.floor(+tom / 1000); }); browser.manage().getCookie('name').then(function(cookie) { expect(date).toEqual(Math.floor(cookie.expiry)); }); }); });
色々とありましたが、今はe2eでcookieのテストを自動化できているので満足です。
.github.ioでcookieがセットできない不思議
実害があるわけではないのですが、素朴な疑問を。
JavaScript経由でcookieをセットしたい場合は、
document.cookie = "name=value; domain=.google.co.jp"
みたいな形でセットしますよね。
サブドメインをまたがってcookieを読み書きしたい場合は、上記のようにdomain=***みたいな形でドメインを指定します。
www.google.co.jpなどでも.google.co.jpで指定すると、
このような形でcookieがセットされます。
が、github.ioの場合は、
document.cookie = "name=value; domain=.github.io"
のように指定してもcookieが保存されません……
こうやっても
入らない……
他のioドメインの場合(http://www.sample.io/)
こうやると、
入るんですよね。
ん〜。JavaScriptからのcookieのセットってブラウザレベルの話だからと思ったけれどChromeでもFirefoxでも同じなんですよね……
github-pagesを使ってcookieにまつわるE2Eテストをやろうとしていた時に気づいた不思議です。理由が分からない。
ご存じの方がいたらご教授下さい。

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Karma+ChromeでTravisCIする
TravisCIでKarmaを使ったテストをする時にハマったのでメモ。
結論としては、
.travis.ymlにCHROME_BIN・DISPLAYをセット、かつsh -e /etc/init.d/xvfb startを実行
karma.conf.jsにTravisCI用の設定を追記
npm testを使いたくない場合はscriptを直接書けば大丈夫
という事です。
TravisCI用のKarma設定でハマった理由
公式だと、PhantomJS使う方法かFirefox使う方法が載っている。
Karma - Travis CI
説明ではpackage.jsonにscript.test書いて、devDependenciesとかに必要なモノを書いておけば、npm installはTravisの方でいい感じにしてくれるよ!って書いてある。
が、そのままコピペするとPhantomJS、Firefoxが無いって怒られる。まあ、devDependenciesにPhantomJSとか書けば解決しそうではあるが、このためだけにPhantomJS入れたくない……
公式のした方にTravisでブラウザのようなGUIアプリケーションを動かすヘルプにリンクがある事に気がつくも、それだけでは完全な解決には至らなかった……
Travis CI: GUI & Headless browser testing
.travis.ymlとkarma.conf.jsの修正
Github Issueを漁ると解決作が載っていた。
Chrome not captured when running tests on Travis · Issue #1144 · karma-runner/karma
ココに.travis.ymlとkarma.conf.jsのサンプルが載っているので、これを使えば動く。
.travis.ymlには
language: node_js node_js: - "0.10" script: node_modules/karma/bin/karma start karma.conf.js --single-run # Google Chrome # # https://github.com/travis-ci/travis-ci/issues/272#issuecomment-14402117 # http://stackoverflow.com/questions/19255976/how-to-make-travis-execute-angular-tests-on-chrome-please-set-env-variable-chr # before_install: - export CHROME_BIN=chromium-browser - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start
のようにbefore_installで環境変数をセットしてxvfbをセットして、scriptでkarmaを--single-runでスタートさせる。
SeeSS/.travis.yml at master · MrOrz/SeeSS
karma.conf.jsでは、
customLaunchers: { Chrome_travis_ci: { base: 'Chrome', flags: ['--no-sandbox'] } },
のようにcustomLaunchersで--no-sandboxのフラグをしてして、
if(process.env.TRAVIS){ configuration.browsers = ['Chrome_travis_ci']; // configuration.reporters = configuration.reporters.concat(['coverage', 'coveralls']); // configuration.coverageReporter = { // type : 'lcovonly', // dir : 'coverage/' // }; }
とprocess.env.TRAVIS な場合にブラウザを設定したものにする、という処理を追加する。(設定オブジェクト外でif分岐を入れるので、一度設定オブジェクトを定義してから、 config.setする事に注意が必要)
上記で無事npm testをtravisCI用にすることもなくkarmaを使う事ができる。
JavaScriptでcookieを扱うライブラリをつくりました
年末年始にcookieを扱うライブラリを作ってみました。
モチベーションとしては、
browserifyを使ってみたかった
cookieを使う時は主にjQuery.cookieを使っていたけれど、jQueryを使う事自体が減ってきた。
npmに公開してみたかった
当たりです。
tongs
作った物はコチラです。
使い方は上記ページに書いていますが、
tongs().cookie('name', 'value'); tongs().cookie('name');
みたいな書き方が出来るようになっています。
内部構造
作ったモチベーションの大きな1つがbrowserifyを使うことだったので、内部的に(無駄に)requireを使う仕様になっています。 (だからサイズ的には太っていますが、、、、)
構造としては、tongs.model.jsが、cookieのモデルとして値の保持やsave,remove等のメソッドを持っています。
tongs.collection.jsが、cookieのモデルをコレクションする役割になって、eachとかtoJSON等のメソッドを持ちます。
それらまとめいい感じのラップするために、tongs.jsがあり、Tongsというクラスを作りつつ、ブラウザで使う場合は毎回 new でインスタンスを作るとかハードル高そうなので、globalにtongsというTongsのインスタンスを返すやつを作っています。
ToDo
手元環境でしかテストできていないので、テストブラウザを増やす(saucelabs使ってみたいだけ……)
内部的にarray.prototype.eachなどを使っているので、IE9以下動かないはずなので、この辺りを対応する*
Node.jsのサーバーサイドで使う事を対処したい
あたりを考えています。
browserifyを使ってみて
requireしか使っていないですが、スゴイ便利。ファイルを分けて書く事ができるし、テストでも対象をrequireできるのは嬉しい。今後は積極的に活用していきたい。
実は書いている時はcookerという名前で書いていたんですが、npm登録の段になってcookerが登録できない事をしり、cookiecookerという名前にしたものの長すぎるなと思い、最終的にはtongsにしたというバタバタをやりましたが、一旦一区切りという事で公開しました。。
ご意見等あればgithub等でお伝え下さい :)
ユニバーサルアナリティクスで現在ページのトラッカーオブジェクトを確認したい
Googleアナリティクスで今のページのトラッカーオブジェクトをざっくり確認したい事があります。
そんな時に手軽に確認するために、コンソール欄に貼り付けるようのJavaScriptを書いた。
動作としてはこんな感じ。
ソースはこんな感じ。
個人的には結構重宝している。
npmでパッケージ名だけlsしたい
npmでグローバルにインストールされているパッケージを調べたい時は
npm -g ls
なんかで調べる事ができるのですが、
のように依存関係があるものも表示されて、肝心のパッケージ名がわかりにくい……
ローカルにインストールしたパッケージであればpackage.jsonみればいいのですが、グローバルだと困ってしまっていました。
で、困ったときのStack Overflowを見ると
npm ls -g --depth=0
のように--depth=0をつけると良いと教えてもらいました。
はい、スッキリとパッケージ名だけ表示されるようになりました。
何となくですが、最近jQueryの話題を聞かない気がしてるなーと思っていました。
ですので、Googleトレンドで調べてみました。
jQueryの検索需要は減っているかとおもいきや横ばいですね。
代わりにangularが伸長してきているのかと思って比較してみると……
あかん。全然勝負になってない。ノイズが入る事覚悟の上で『angular.js』ではなく『angular』と検索しても数が全然違いましたね。
ただ、SimilarWebでPVの参考値を見てみると、jquery.comに比べてangularjs.orgの方が多い。
jquery.com Traffic Statistics by SimilarWeb
jQueryは公式情報を見るのではなくググりながら使われている。angularはまだ新しい事もありまずは公式情報で概要を見られることが多いというようなことですかね。

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
monitorEvents!なにこれ!!スゴイ!!!
最近Google+を眺めていると面白い事が多い。今日はこんなモノを見つけた。
Chrome Developer Toolsには、monitorEventsというメソッドがあるんですね。デベロッパーツールを開いて、
monitorEvents(window, "click")
のように打ち込むと、画面でどこをクリックしたのか等がコンソールに出力されます。面白い!!
モニターできるイベントは、mouse・key・touch・controlがあるようです。今すぐなにかというわけではないですが、覚えておくと役に立つ時が来るかも!?
ちなみに、2011年のブログで言及されていたりするのでかなり昔からあったんですね……
Command Line API Reference - Google Chrome
Chrome Developer Tools – monitorEvents - Brian Grinstead
angular.jsのためのテスト準備(ユニットテスト、E2E)
angular.jsのチュートリアルにはテストもきちんと含まれているが、キューピー3分間クッキングなみに出来上がった状態で提示されてくる。そのため、なんとなくわかった気になるが実際よく分かっていないという状態に陥りがちである。
どうなっているかをすこしは理解したいと思い、angular.jsでのテスト環境を一から構築してみる。
ユニットテスト Karma
ユニットテストはKarmaを使うのが楽そうである。公式のチュートリアルなどもKarmaが前提になっている。まあ、Karma自体が「angularのために」からスタートしているので相性がいい、かつ情報が豊富なのは当然なので使わない手はないと思う。
ここでは、Karma・mocha・chaiの構成を取る。基本的な設定は以前のポストをご参考頂ければ。CLIが分離したKarma0.12でmocha,chaiの環境を整える | niwaringo() {Tumblr}
angular.js特有の注意点は以下。
angular-mocks.jsのインストール
依存解決等のためにangular-mocks.jsが必要になる。bowerなどを使って事前にインストールしておく。
$ bower install angular-mocks -D
karma.conf.jsの注意点
angular.jsを一番最初に読み込む
bower_components以下全てのJSファイル読み込みなどとしておくと、angularが読み込む前にangular-mocksが読み込まれてエラーになるという悲しい自体に遭遇したりする。そのため一番はじめにangular.jsを読み込んでおく。
files: [ 'bower_components/angular/angular.js', 'bower_components/**/*.js', 'app/js/*.js', 'test/unit/**/*_spec.js' ],
minファイルの除外
ちなみにbowerでインストールした場合は、minファイルも一緒にインストールされる事が多いためminファイルは除外しておくと良さそうである。angular特有ではないが、、、、
exclude: [ 'bower_components/**/*.min.js' ],
テストファイルでの注意点
angularはDIが非常に特徴的である。テストの時にコレを解決するためにmoduleでテストしたいモジュールを呼び出して、injectを使って依存を解決するという形を取る。module、injectはangular-mocksがグローバルに追加される。
describe('PhoneListCtrl', function(){ beforeEach(module('phonecatApp')); it('should create "phones" model with 3 phones', inject(function($controller) { var scope = {}, ctrl = $controller('PhoneListCtrl', {$scope:scope}); expect(scope.phones).to.have.length(3); })); });
上記テストコードはチュートリアルで紹介されているコード。(expectはchaiにしていますが)
ユニットテストはangular-mocksを使って依存を解決すれば基本問題はなさそうである。angular-mocksは他にも色々便利そうなのできちんと調べたほうが良さそう……そのうち。
E2Eテスト
E2Eテストは、angular.jsのために開発された「protractor」というテストフレームワークがある。昔はKarma自体にE2Eの仕組みが組み込まれていたが分離されて、ユニットテストはKarma、E2Eテストはprotractorという役割分担になっているようである。protractorは現在かなり活発に開発が進められているので「あれ?」と思ったらアップデートすると解決することが多い :P
protractorのインストール
公式ではグローバルになっているが、とりあえずはローカルで様子見を。
$ npm install protractor -D
standalone selenium server と chromedriverのダウンロード
protractorはWebDriverJSが土台になっているため、seleniumのstandalone severが必要になる。(chromeだけでテストする場合はchromedriverだけでも良い)
以下のコマンドでselenium-server-standaloneとchromedriverの両方をダウンロードしてくれる。
./node_modules/protractor/bin/webdriver-manager update
設定ファイルの作成
protractorは、Karma同様に設定ファイルを指定してテストを実行する。そのためひな形をコピーして設定ファイルを作成する。
cp ./node_modules/protractor/referenceConf.js referenceConf.js
設定ファイルにはかなり丁寧なコメントが書かれている。何点かピックアップしてみると、
クロムだけでテストするならchromeDriverだけでseleniumSeverJarは指定しなくてもよい
SauceLabsがサポートされている
テストのための引数とかも設定可能 --params.login.user 'Joe'
Mochaはベータサポート :(
mocha, chaiを使うための設定
ベータ版のようだが、基本的にはmocha・chaiが使える。
mocha, chai, chai-as-promisedのインストール
mochaはグローバルでのインストールが必要っぽい。あと、protractorはpromiseが各所で使われているのでchai-as-promisedが推奨されている。
npm install -g mocha npm install chai npm install chai-as-promised
設定ファイルの変更
設定ファイルのframeworkをmochaにする。デフォルトはjasmine。確かKarma自体にE2Eが合った時はオレオレ仕様だったので一般的なフレームワークが使えるのはかなりありがたい。
framework: 'mocha',
mochaのオプションを設定
mochaOpts: { ui: 'bdd', reporter: 'spec' },
reporterをspecにしておいた(デフォルトはlist)
テストファイル
公式で紹介されているプラスαでこんな形になる。
/*jshint -W079 */ var chai = require('chai'); var chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); var expect = chai.expect; describe('angularjs homepage', function() { it('should greet the named user', function() { browser.get('http://www.angularjs.org'); element(by.model('yourName')).sendKeys('Julie'); var greeting = element(by.binding('yourName')); expect(greeting.getText()).to.eventually.equal('Hello Julie!'); }); });
chai, chai-as-promisedを読み込んで設定しておき、expectをchaiのものに上書きをしておく。なお、jshintを使っている場合はexpectの上書きは警告がでるとおもうので、冒頭で無視するように/*jshint -W079 */を記述しておく。
expectはeventuallyを挟んでpromiseに対応しておく。
protractor/docs/using-mocha.md at master · angular/protractor
JSLint Error Explanations - Redefinition of '{a}'
* * *
angular.js自体が非常に大きなライブラリで様々な物を含んでいるが、エコシステムとしてテスト環境も整備されている。好みの問題だが身を委ねてしまうと非常に楽になる。
CLIが分離したKarma0.12でmocha,chaiの環境を整える
前回、Kamr0.10.9でKamaとmochaの環境を整えた。しかし、その後Karmaはローカルインストールを推奨してグローバルで使うためのCLI部分をkarma-cliとして分離している模様。
ということでKarma0.12移行では、Karmaのインストール先はグローバルではなくローカルだけ。テストの実行は、'./node_modules/karma/bin/karma start' のようにローカルを指定して実行する。という形に変わっています。
Karma0.12でmocha,chaiの環境を整える
Karma0.12でmochaとchaiを使ってテストをする環境を整えます。テストに利用するスクリプトは前回と変わらず以下で。
ディレクトリ構成
hello.js
var hello = function() { return "hello"; };
hello.test.js
describe("karma and mocha testing", function() { it ("return hello", function() { expect(hello()).to.equal("hello"); }); });
/ ├ hello.js └ hello.test.js
Karmaをローカルインストール
まずはKarmaのインストール。グローバルではなくローカルです。
$ npm install karma --save-dev
これでKarmaのインストールは完了です。
./node_modules/karma/bin/karma init
この状態でinitコマンドでkarma.conf.jsを作ります。
$ ./node_modules/karma/bin/karma init
ローカルのkarmaコマンドを使って設定ファイル(karma.conf.js)を作成します。。上記コマンドを実行すると対話型で設定ファイルの作成が進みます。テストフレームワークはmochaでブラウザはChrome、そしてJavaScriptファイルはとりあえず*.jsで指定すると以下のように進みます。
Which testing framework do you want to use ? Press tab to list possible options. Enter to move to the next question. > mocha Do you want to use Require.js ? This will add Require.js plugin. Press tab to list possible options. Enter to move to the next question. > no Do you want to capture any browsers automatically ? Press tab to list possible options. Enter empty string to move to the next question. > Chrome > What is the location of your source and test files ? You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js". Enter empty string to move to the next question. > *.js > Should any of the files included by the previous patterns be excluded ? You can use glob patterns, eg. "**/*.swp". Enter empty string to move to the next question. > Do you want Karma to watch all the files and run the tests on change ? Press tab to list possible options. > yes
テストフレームワークにmochaを指定してブラウザにChromeを指定すると、mocha・karma-mocha、そしてkarma-chrome-launcherがインストールされます。これには少しビックリしました。念のためkarma/lib/init.jsを見ると、'karma-' + フレームワーク名のパッケージをインストールするように書いてありますね。
karma-chaiをインストール
アサーションとしてはchai(expect)を使うので、karma-chaiをインストール。
$ npm install karma-chai --save-dev
そして、karma.conf.jsのフレームワークにchaiを追加。
$ npm install karma-chai --save-dev
テストの実行
これで環境が整いましたので、
$ ./node_modules/karma/bin/karma start
とすると
INFO [karma]: Karma v0.12.14 server started at http://localhost:9876/ INFO [launcher]: Starting browser Chrome INFO [Chrome 34.0.1847 (Mac OS X 10.9.2)]: Connected on socket hogehoge with id 00000 Chrome 34.0.1847 (Mac OS X 10.9.2): Executed 1 of 1 SUCCESS (0.013 secs / 0 secs)
としてテストが無事実行されます。
npm testにショートカットを
./node_modules/karma/bin/karma startはタイプするには長い。まあ、履歴からたどればいいだけだけど出来ればショートカットが欲しい。かといってショートカットだけのためにkarma-cliを入れるのも億劫。という事でnpm testでテストが実行されるようにpackage.jsonに
"scripts": { "test": "./node_modules/karma/bin/karma start" },
を追加します。この状態で
$ npm test
とすれば無事Karmaが動きます。
参考サイト
小さくKarmaとmochaでテスト環境を整える。 | niwaringo() {Tumblr}
Karma - Installation
CLIでJavaScriptのテストを実行する時にHTML fixtureを利用する方法。Karma + mocha + chai
やりたい事
[test/fixtures/sample.html] <div id="my-fixture">DOMのテスト</div>
などというテストファイルを用意しておき、
[test/sample.spec.js] var $fixtures = $('#my-fixture'); expect($fixtures.length).to.eql(1);
のようにテストファイルでそれを使ってのテスト。要は、DOM部分を別ファイルに切り出した状態でテストをしたい。
Karmaなら標準でできるよ
Karmaのv0.10から標準でhtml2js preprocessorというのが有効化されているらしい。これは何かというと、htmlファイルの内容をwindow.__html__に文字列として格納してくれるという機能。上の例でいくと
window.__html__ = { 'test/fixtures/sample.html': '<div id="fixtures">fixtures!!</div>' }
となる。これを利用すれば以下のようなテストが可能になる。
describe("fixtureを利用したテスト", function() { it("#my-fixtureをjQueryオブジェクトとして利用できる", function() { document.body.innerHTML = __html__["test/fixtures/sample.html"]; var $fixtures = $('#fixtures'); expect($fixtures.length).to.eql(1); }); });
__html__["test/fixtures/sample.html"]にファイルの文字列が入っているので、document.body.innerHTMLでHTMLファイルとしている。こうしておけば $('#fixtures')としてjQueryで扱うことも可能になる。便利!
documentはグローバルなので、念の為にbeforeで初期化して、afterでリセットしておくほうが良さそうですね。
describe("fixtureを利用したテスト", function() { before(function() { document.body.innerHTML = __html__["test/fixtures/sample.html"]; }); after(function() { document.body.innerHTML = ""; }); it("#my-fixtureをjQueryオブジェクトとして利用できる", function() { var $fixtures = $('#fixtures'); expect($fixtures.length).to.eql(1); }); });
ちなみに上記の前提は、
files: [ 'test/fixtures/*.html', 'lib/**/*.js', 'src/*.js', 'test/*.spec.js' ]
のようにkarma.conf.js側でfileで指定している必要があります。
参考にしたサイト
What is the way for fixtures in karma v0.10.1? - Google グループ
karma-runner/karma-html2js-preprocessor · GitHub
Karma -v 0.10移行は標準で有効化されているので別途インストールの必要はありません。
velesin/jasmine-jquery · GitHub
Jasmineならこの素敵プラグインを使っている人が多そうですね
badunk/js-fixtures · GitHub
jasmine-jqueryをforkしてjasmine依存をなくしたライブラリもあるようです。
小さくKarmaとmochaでテスト環境を整える。
流行りにのって(遅い!)Angular.jsを試してみようと思ったのですが、Angularの前に気になって仕方がないことがあります。
「Karmaが便利なんだろうけどさっぱりわからん」
公式のチュートリアルではKarmaがすべて「下ごしらえ完成した状態」になって提供されます。動いてくれているのですが、なぜこう動いてくれているのかさっぱり分からなくて何となく気持ち悪い。 Karmaについて調べようとしたのですが、以外と情報が少ない。公式ではいきなり動画だったり :(
ということで、小さくKarmaとmochaでテスト環境を整える事を目的としたメモ・備忘を文章で残します。
ファイル構成
hello.js
var hello = function() { return "hello"; };
hello.test.js
describe("karma and mocha testing", function() { it ("return hello", function() { expect(hello()).to.equal("hello"); }); });
という二つのファイルを用意しています。 hello.jsというファイルで定義したhelloという関数をhello.test.jsというファイルでテストする。ディレクトリとかは特に作らずやります。小さくスタートするのが目的だから
* * *
/ ├ hello.js └ hello.test.js
* * *
のようになっている事を想定します。
Karmaのグローバルインストール
まずはKarmaをグローバルでインストールします。
$ npm install -g karma $ karma --version Karma version: 0.10.9
これを書いている時は0.10.9がインストールされます。
karma.conf.jsの作成
Karmaの動作にはkarma.conf.jsという設定ファイルが必要です。これは直接ファイルを作成してもよいですし、コマンドからウィザードで作成する事も可能です。今回はウィザードを利用します。
$ karma init
ウィザードを始めるには上記コマンドを叩きます。すると、Karmaの設定フィアルである「karma.conf.js」の作成ウィザードにはいります。
Which testing framework do you want to use ? Press tab to list possible options. Enter to move to the next question. > mocha
はじめにテストフレームワークを聞かれるからmochaを選択します。 気をつけたいのはタブで切り替えるという事です。 説明書きにも書いていますが、、、私はちゃんと読まずに必死に文字を消そうとしていました。
WARN [init]: Missing "karma-mocha" plugin. npm install karma-mocha --save-dev
このような注意をされますが、ここはひとまず無視して先に進めます。
Do you want to use Require.js ? This will add Require.js plugin. Press tab to list possible options. Enter to move to the next question. > no
Require.jsを使うかきかれるのでnoを選択。
Do you want to capture a browser automatically ? Press tab to list possible options. Enter empty string to move to the next question. > Chrome >
KarmaはブラウザでJSを実行してそれをキャプチャしてくれる仕組みです。そのためのブラウザを選択します。 複数選べるようですが、ここはChromeだけで先に進みます。
Chromeを選んでエンター。空白のままでもう一度エンター
What is the location of your source and test files ? You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js". Enter empty string to move to the next question. > *.js >
JS(テストファイル含む)ファイルどこにおいてんの?って聞かれますので、今回は*.js って返答しておきます。小さく始める事が目的なので、ディレクトリとか作成せずにまずは動作することを目的としますので。
*.js でエンター。空白のままでもう一度エンター。
Should any of the files included by the previous patterns be excluded ? You can use glob patterns, eg. "**/*.swp". Enter empty string to move to the next question. >
除外するやつは?って聞かれるので、とりあえず空白のままエンター。
Do you want Karma to watch all the files and run the tests on change ? Press tab to list possible options. > yes
ファイルが変更されたら自動的にKarmaでテストする?って聞かれる。watchして欲しいのでyesです。
yesでエンター
とするとkarma.conf.jsが作成される。作成されたkarma.conf.jsはウィザードで設定した物の他にポートなどがコメントつきで記載されているので時間がある時に読みたいと思います。
* * *
ここまでで、 / ├ hello.js ├ hello.test.js └ karma.conf.js
のようになっているはずです。
* * *
失敗するのは分かっていますが、この状態でkarma startをしてみましょう。
No provider for "framework:mocha"! (Resolving: framework:mocha)
mocha使えるようにしてから出直して来いと言われます。
karma-mocha, karma-chaiのインストール
ウィザードの時にmochaを選択すると、
WARN [init]: Missing "karma-mocha" plugin. npm install karma-mocha --save-dev
と注意されましたよね。この注意にしたがったkarma-mochaをインストールします。
npm install karma-mocha --save-dev
ここでもう一度karma startをしてみます。
Chromeが立ち上がって成功したかとおもいきや…………惜しい。もう一つエラーが出ています。
ReferenceError: expect is not defined
expectなんてしらない。expect等のアサーションをmocha自身が持っていないからですね。 最後の仕上げとしてexpectのためにkarma-chaiをインストールします。
$npm install karma-chai --save-dev
インストール後に、karma.conf.jsを開いて、frameworksの所にchaiを追加しましょう。
frameworks: ['mocha', 'chai'],
* * *
ここまでで、 / ├ hello.js ├ hello.test.js ├ karma.conf.js └ node_modules/
のようになっているはずです。
* * *
最後にもう一度
$karma start
今度は成功します。今回はここまで。
ところで、buster.jsはいつVer1がでますでしょうか?

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Chaiのexpectを使うとJSHintに怒られるようになったのでオプションを見なおした。
最近テストフレームワークをQUnitからMocha+Chaiに乗り換えようとしています。理由は特に無いです。何となくです。ただ、年末にセールになっていたから買ったBackbone.js TestingもMocha+Chaiだったのは大きいです。
そこで出会った問題。テストをChaiのExpectで書いているとJSHintがお怒りになるのです。
expect(helloSpy.called).to.be.false;
のようなコードを書くと、Expected an assignment or function call and instead saw an expressionと言ってお怒りの模様。
直訳すると、代入か関数コールの予定じゃないの?式じゃなくて。というエラーですね。まあ、式で終わっているのが問題だと。イメージですが、
var hoge = expect(helloSpy.called).to.be.false;
のような代入か、
expect(helloSpy.called).to.be.false();
のような関数呼び出しじゃないの?ってお怒りされているという事ですよね。
ChaiのIssueに解決策が書いてます。
で、これはChaiのIssueでも上がっていますね。 Allow writing JSLint/JSHint friendly tests · Issue #41 · chaijs/chai
In case anyone else looks at this, the problem can be resolved for jshint by configuring it with the "expr" option.
JSHintのexprオプションをtrueにすれば解決するみたいですね。
ということで、.jshintrcに
"expr" : true,
を追加して無事解決。
ES5以降ではこの式のの書き方で問題なし
ちなみに上記Issueで読んでいくと、Chaiのコミッターのdomenicさんが
There's nothing wrong with expression statements with side effects. They may not have been common in ES3, the 1999 version of the language, but in ES5, the 2009 version, they're quite normal, due to the existence of getters.
とES5なら普通の書き方だよ。っておっしゃってますね。ES5とかちゃんと読んで理解できていないんですが、MDNの「ゲッタとセッタの定義」を見てもこの書き方が許容されるべきことはわかりますね。
ゲッタとセッタの定義 - JavaScript | MDN
js> o = new Object; [object Object] js> o = {a:7, get b() {return this.a+1; }, set c(x) {this.a = x/2}}; [object Object] js> o.a 7 js> o.b 8 js> o.c = 50 js> o.a 25
深いところまできちんと理解出来ていませんが、新しいフレームワークとか使い出すとこういうのに出会えていいですね。
参考サイト
JSHint 2.0 公開(翻訳) | 黒くないすべてのものはカラスではない
A Node in Nodes - JSHintで気軽なコーディングを
MDNページでのコンソール出力がおちゃめだった
こんなの