takatama について

Software engineer, working in Tokyo.

WebDriver+JavaScriptでWebアプリのE2Eテスト

Webアプリが正しく動作することを、Webブラウザーを操作して確認する E2E (End-to-End) テスト。テストの記述には様々なプログラミング言語が使えます。

Selenium WebDriver + JavaScript で E2E テストをするやり方が

An Introduction to WebDriver Using the JavaScript Bindings – Tuts+ Code Tutorial

で紹介されています。

この記事は、基本となる WebDriverJS 以外に、7つのクライアントAPIライブラリーを紹介しています。どれも github で公開されていたので、スター数を調べてみました (2014/12/07時点)。

また、テストの際に、期待通りの値になっているかどうかを調べる assert API がライブラリに組み込まれているか、それとも別途 jasmine や mocha, Q といったテストフレームワークが必要かも調べました。

Client API スター数 assert 補足
WebDriverJS N/A 別途 W3Cで標準化しているAPIで書く。JavaでSelenium動かしていた人向け。
WD.js 658 別途 builder pattern (fluent interface) で書く。
WebDriver.io 661 別途 builder patternで書く。WD.jsより短く書ける。
Testium 203 別途 CoffeeScript で書く。
Leadfoot 63 別途 Internで使われてる。WD.jsと似たAPI。
Nightwatch 2,386 組み込み 設定ファイルが必要。拡張コマンドは別ファイルに書く。
DalekJS 481 組み込み Selenium Server まで入った全部入り。Webサイトが派手w。
Webdriver-sync 36 組み込み Java APIに準拠。同期型。

さらに、WebdriverJS, WD.js, WebdriverIO, Nightwatch, Dalek の5つについて、実際にコードを書いてみました。

お題は「Googleで”webdriver”を検索した時のヒット数を標準出力に表示する」です。assert は使いません。

共通の事前準備

Mac を使います。Web ブラウザーは Chrome です。
Homebrew と Cask で node.js と java をインストールします。

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew install node
$ brew brew install brew-cask
$ brew cask install java

さらに Selenium Server と Chrome Driver をインストールします。

$ npm install selenium-standalone chromedriver -g

コードを実行する前に、Selenium Server を起動しておきます。ただし、Dalek の場合は不要です。

$ start-selenium

WebDriverJS

APIはこちら。豊富です。
http://selenium.googlecode.com/git/docs/api/javascript/index.html

インストール

$ npm install selenium-webdriver

コード

webdriverjs.js:

var webdriver = require('selenium-webdriver');
var By = webdriver.By;

//WebブラウザーはChrome
var driver = new webdriver.Builder().
   withCapabilities(webdriver.Capabilities.chrome()).
   build();
var $ = driver.findElement.bind(driver);

//Googleを開く。
driver.get('http://www.google.com');

//検索ボックスにwebdriverと入力する。
$(By.name('q')).sendKeys('webdriver');

//検索ボタンを押す。
$(By.name('btnG')).click();

//ヒット数が表示されるまで待つ。
var timeoutMSec = 2000;
driver.wait(webdriver.until.elementLocated(By.id('resultStats')), timeoutMSec)
.then(function() { //waitした後はthenでつなぐ
    $(By.id('resultStats')).getText().then(function(text) {
        console.log(text);
    });
})
.then(function() {
    driver.quit();
});

実行

$ node webdriverjs.js 
約 615,000 件 (0.11 秒) 

WD.js

sendKeys() など WebDriverJS の名残があります。また、waitForElementByCss()など、APIが若干長めです。

インストール

$ npm install wd

コード

wd.js:

var wd = require('wd');
var browser = wd.promiseChainRemote();
var timeoutMSec = 1000;
browser
    .init({
        browserName: 'chrome'
    })
    .get('http://www.google.com')
    .elementByName('q')
    .sendKeys('webdriver')
    .elementByName('btnG')
    .click()
    .waitForElementByCss('#resultStats', timeoutMSec)
    .text(function(err, text) {
        console.log(text);
    })
    .quit();

実行

$ node wd.js
約 615,000 件 (0.12 秒)

Webdriver.io

今回試した中では、API 名が短くて好きです。

インストール

$ npm install webdriverio

コード

webdriverio.js:

var timeoutMSec = 1000;
var webdriverio = require('webdriverio')
    .remote({
        desiredCapabilities: {
            browserName: 'chrome'
        }
    })
    .init()
    .url('http://www.google.com')
    .setValue('[name="q"]', 'webdriver')
    .click('[name="btnG"]')
    .waitFor('#resultStats', timeoutMSec)
    .getText('#resultStats', function(err, text) {
        console.log(text);
    })
    .end();

実行

$ node webdriverio.js 
約 615,000 件 (0.12 秒) 

Nightwatch

runner を使って実行するので、出力が綺麗です。
デフォルトのブラウザーが Firefox で、Chrome を使うためには設定ファイルが必要です。
拡張コマンドを置くためのディレクトリが必要です。

インストール

$ npm install nightwatch -g
$ mkdir -p examples/custom-commands

コード

nightwatch.json:

{
  "selenium": {
    "cli_args": {
      "webdriver.chrome.driver": "/usr/local/bin/chromedriver"
    }
  },
  "test_settings" : {
    "default" : {
      "silent": true,
      "desiredCapabilities": {
        "browserName": "chrome"
      }
    }
  }
}

nightwatch.js:

module.exports = {
  "webdriverの検索ヒット数を表示する" : function (browser) {
    var timeoutMSec = 1000;
    browser
      .url("http://www.google.com")
      .setValue('[name="q"]', 'webdriver')
      .click('[name="btnK"]') // FirefoxとChromeでは表示されるボタン名が違います。
      .waitForElementPresent('#resultStats', timeoutMSec)
      .getText('#resultStats', function(res) {
          console.log(res.value);
      })
      .end();
  }
};

実行

$ nightwatch -t nightwatch.js 

[Nightwatch] Test Suite
=======================

Running:  webdriverの検索ヒット数を表示する 

✔  Element <#resultStats> was present after 1038 milliseconds.
約 615,000 件 (0.14 秒) 

OK. 1 total assertions passed. (11.812s)

DalekJS

Selenium server を動かす必要はありません。

インストール

$npm install dalek-cli -g
$npm install dalekjs dalek-browser-chrome --save-dev

コード

waitForElementが動作しないので、waitForを使いました(github)。
標準出力への表示はexecute()とlog.message()を組み合わせて使います。

dalek.js:

module.exports = {
  'webdriverのヒット数を表示する': function (test) {
    var timeoutMSec = 10000;
    test
      .open("http://www.google.com")
      .setValue('[name="q"]', 'webdriver')
      .click('[name="btnG"]')
      //.waitForElement('#resultStats', timeoutMSec)
      .waitFor(function() {
        return Boolean(document.querySelector('#resultStats'));
      }, [], timeoutMSec)
      .execute(function() {
        var result = document.querySelector('#resultStats').innerText;
        this.data('result', result);
      })
      .log.message(function() {
        return test.data('result');
      })
      .done();
  }
};

実行

引数 -b chrome を与えて Chrome で動かします。
デフォルトではヘッドレスブラウザーの PhantomJS で動かします。

$ dalek dalek.js -b chrome
Running tests
Running Browser: Google Chrome
OS: Mac OS X 10.10.1 x86_64
Browser Version: 39.0.2171.71

RUNNING TEST - "webdriverのヒット数を表示する"
▶ OPEN http://www.google.com
▶ SETVALUE [name="q"]
▶ CLICK [name="btnG"]
▶ WAITFOR 
▶ EXECUTE 
☁ [USER] MESSAGE: 約 615,000 件 (0.38 秒) 
✔ 0 Assertions run
✔ TEST - "webdriverのヒット数を表示する" SUCCEEDED

 0/0 assertions passed. Elapsed Time: 4.44 sec 

どれを選ぶか

短い API が好きなので、Webdriver.ioNightwatchですね。すでにテストフレームワークをチームに導入しているかどうかで決める。

(ただ、Nightwatch の対抗馬としてInternも気になります。もうちょっと調べてみよう)

ブックマークレットをChrome拡張機能から実行する方法

ブックマークレットは便利だけれど、インストールが大変。そこで、Chrome拡張機能として作り直してみた。結果的には、2つのファイルを追加すれば実現できた。

「ボタンを押すとスクリプトを実行する」という動作にしたかったので、Page Action として作った。スクリプトを動作させたいページを開くと、アドレスバーの横にアイコンを表示する。そのアイコンをクリックすると、スクリプトを実行する。

(1) manifest.json を作る
ポイントは、permissions に、”tabs”と、スクリプトを注入するページのURLを記載する点。
URLはアスタリスク (*) を使ったパターンを記述することもできる。詳しくは Match Patterns を参照。


{
"manifest_version": 2,
"name": "Name of this extension",
"version": "0.1", // 新しい拡張を公開するたびに上げていく
"description": "Description of this extension",
"icons": {
"128": "icon128.png" // chrome://extensions に表示されるアイコン。128×128
},
"page_action": {
"default_icon": "icon128.png", // アドレスバーに表示されるアイコン。19×19, 38×38 を準備しておくべき?
"default_title": "Tooltip for the page action icon"
},
"permissions": [
"tabs",
"https://www.google.com/maps/preview" // スクリプトを実行したいURLを記載していく
],
"background": {
"scripts": ["background.js"]
}
}

view raw

manifest.json

hosted with ❤ by GitHub

(2) background.js を作る
ポイントは2つ。
1. Page Action のアイコンを表示したいURLの正規表現を記述する。正規表現と、上記 (1) のアスタリスク記法は異なるので注意。
2. 実行したいスクリプト (ブックマークレット) のファイル名、ここでは execute.js を記述する。別ファイルにせずに、直接記述することもできる (file ではなく code にする)。


var urlRegExp = new RegExp('^https?://www.google.com/maps/preview'); // アドレスバーの横にアイコンを表示するときのURL正規表現
function showIcon(tabId, changeInfo, tab) {
if (tab.url.match(urlRegExp)) {
chrome.pageAction.show(tabId);
}
}
chrome.tabs.onUpdated.addListener(showIcon);
chrome.pageAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(tab.id, {
"file": "execute.js" //実行したいスクリプトのファイル名 (execute.js)
}, function () {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
}
});
});

view raw

background.js

hosted with ❤ by GitHub

ここまで準備ができれば、Chrome単体で拡張機能を作って試すことができる。ただ、簡単にインストールできるようにするためには、Chromeウェブストアで公開する必要がある。

(3) Chromeウェブストアで公開する
まだ公開していないので、できたら報告します。
ダッシュボードにアクセスして、拡張機能を登録。ポイントは2つ。
1. 開発者登録に $5 必要。一度払えば、ずっと使えるらしい。
2. ローカルのChromeで作った.crxではなく、素の zip で固めた .zip ファイルを登録する。Chromeウェブストア側で秘密鍵を発行して署名してくれるらしい。

参考:

Cent OS 5.9 に rbenv で Ruby, bundler をインストール

Cent OS 5.9 に rbenv を使って Ruby と bundler をインストールした。

(1) git のインストール
$ sudo yum install git
$ git –version
git version 1.8.2.1

(2) rbenv, ruby-build のインストール
$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv

rbenv パスを bash に教えるため、以下の2行を追加
$ vi ~/.bashrc
export PATH=”$HOME/.rbenv/bin:$PATH”
eval “$(rbenv init -)”

.bashrc を反映
$ source ~/.bashrc

ruby-build をインストール
$ git clone git://github.com/sstephenson/ruby-build.git
$ cd ruby-build
$ sudo ./install.sh

(3) ruby のインストール
$ sudo yum install -y readline readline-devel zlib zlib-devel openssl-devel g++ gcc-c++

インストール可能なバージョン一覧を表示
$ rbenv install -l

バージョンを指定してインストール
$ rbenv install 1.9.3-p448

デフォルトで利用するバージョンを指定
$ rbenv global 1.9.3-p448
$ rbenv rehash
$ ruby -v
1.9.3-p448

(4) bundler のインストール
$ rbenv exec gem install bundler

bundler を実行するときは rbenv exec bundle として実行
$ rbenv exec bundle -v
Bundler version 1.3.5

これで rails とか入れたらいい。

参考
CentOS 5.8 に ruby 1.9.3 と Rails 3.3.2 をインストール
http://krakenbeal.blogspot.jp/2012/03/centos-58-ruby-193-rails-332.html

Rails開発環境の構築(rbenvでRuby導入からBundler、Rails導入まで) – Qiita [キータ]
http://qiita.com/emadurandal/items/a60886152a4c99ce1017

Cent OS 5.9 に yum を使って Python 2.6 をインストール

Cent OS 5.9 に Python 2.6 をインストールして、easy_install-2.6 と pip を使えるようにした。
楽するポイントは、EPEL パッケージから yum でインストールする点(EPEL使うと、標準パッケージでは発生しない問題が起きるかもしれません。個人の責任でご利用ください)。

(1) EPEL パッケージを導入

自分が使っている OS を調べる。

$ cat /etc/redhat-release
CentOS release 5.9 (Final)

$ uname -a
Linux bstakatama01 2.6.18-274.18.1.el5 #1 SMP Thu Feb 9 12:45:44 EST 2012 x86_64 x86_64 x86_64 GNU/Linux

CentOS 5.x で 64 bit なことが分かったので、CentOS 外部レポジトリの追加(EPEL)を参考に、rpm を wget し rpm をインストール。

$ wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/5/x86_64/epel-release-5-4.noarch.rpm
$ sudo rpm -ivh epel-release-5-4.noarch.rpm

(2) Python2.6, easy_install-2.6 を yum でインストール

EPEL パッケージから Python26 と、python26-distribute をインストール。*-distribute を入れると、easy_install-2.6 が使えるようになる。

$ yum install python26 python26-distribute --enablerepo=epel
$ which easy_install-2.6
/usr/bin/easy_install-2.6

(3) pip をインストール

easy_install-2.6 で pip をインストール

$ sudo easy_install-2.6 pip

これで、easy_install-2.6 や pip を使ってパッケージをインストールできるようになる。

参考

CentOS 外部レポジトリの追加(EPEL)
http://www.tooyama.org/yum-addrepo-epel.html

jsdo.itでenchant.jsを動かす

enchant.jsを使ったゲーム作り実習をやったので、その時のメモを公開。
jsdo.it で作ると、スマフォで動かすのが楽。
ちなみに私はスマフォ用に「シュシュっと手裏剣」を作りました。

(1) jsdo.it でアカウントを作る
http://jsdo.it/ で好きなサービスを使ってログイン。アカウント名はログイン後に決める。

(2) Hello World
画面に文字を表示しよう! by shi3z – code.9leap.net
http://code.9leap.net/codes/show/203
をコピペして動かしてみる。

手順:
1. Start coding を押下。
2. JavaScript タブを選択。
3. + Add Library を押下。
Major Library から enchant.js v0.6.2 – js を選択し、Add ボタンを押下。
4. 9leapのサンプルから main.js をコピペ。
5. Save ボタンを押下。実行結果を確認。

もし正しく動作しない場合は、JavaScript コンソールを確認。

(3) Start 画面追加
jsdo.it 上の別コードをインポートして、Start 画面を表示してみる。

手順:
1. JavaScript タブを選択。
2. + Add Library を押下。
Input URL に 9leap / nineleap.enchant を入力し、Add ボタンを押下。
3. ソースコードを修正。
// game = new Game();
game = new enchant.nineleap.Game();

(4) 画像を表示
スプライトを表示しよう by shi3z – code.9leap.net
http://code.9leap.net/codes/show/202
をコピペ+修正して動かしてみる。画像ファイルのURLを指定する必要がある。
使える素材は
Image Materials | enchant.js – A simple JavaScript framework for creating games and apps.
http://enchantjs.com/ja/image-materials/
を参照。商用利用でなければ、画像を改変して使うのも自由 (by @enchantjs_jaさん)。

手順:
1.
// var game = new Game(320, 320);
var game = new enchant.nineleap.Game(320, 320);

2.
// game.preload(‘chara1.gif’); // chara1.gifを読み込む
var chara1 = ‘http://enchantjs.com/images/materials/chara1.png’;
game.preload(chara1); // chara1.gifを読み込む

3.
// bear.image = game.assets[‘chara1.gif’]; // chara1.gifの中にある
bear.image = game.assets[chara1]; // chara1.gifの中にある

(5) 操作パッド
十字キーは Pad, アナログの操作キーは APad。
ソースコードは http://jsdo.it/takatama/Tn9F/ を参照のこと。

手順:
1. JavaScript タブを選択。
2. + Add Library を押下。
Input URL に 9leap / ui.enchant と入力し Add ボタンを押下。
3. ソースコードを入力。

var pad = new enchant.ui.Pad();
pad.moveTo(10, 220);
game.rootScene.addChild(pad);

bear.addEventListener('enterframe', function () {
    var input = game.input;
    //キーに応じて移動
    if (input.left) {
        this.x -= 4;
    }
    if (input.right) {
        this.x += 4;
    }
    if (input.up) {
        this.y -= 4;
    }
    if (input.down) {
        this.y += 4;
    }
    if (game.frame %4 === 0) {
        this.frame = 2- this.frame;
    }
});

var apad = new enchant.ui.APad();
apad.moveTo(120, 220);
game.rootScene.addChild(apad);

bear.addEventListener('enterframe', function () {
    if (apad.isTouched) {
        this.x += apad.vx*4;
        this.y += apad.vy*4;
    }
});

(6) スマフォで操作する
URLを jsdo.it から jsrun.it に変更して、スマフォのブラウザーからアクセス。
例えば http://jsdo.it/takatama/Tn9F/ なら http://jsrun.it/takatama/Tn9F/ にすればよい。

(7) End画面を追加
上記(3)でStart画面を追加済みなら、ゲーム終了時に、game.end(score, message); を呼び出せば良い。

(8) Clear画面を追加
ちょっとした工夫が必要。Gameをnewする前後にソースコードを追記する。

enchant.nineleap.assets.push('http://wise9.github.com/enchant.js/images/clear.png');
var game = new enchant.nineleap.Game();
game.clear = function(score, message) {
    this.endScene = new SplashScene();
    this.endScene.image = this.assets['http://wise9.github.com/enchant.js/images/clear.png'];
    this.end(score, message);
};

青空文庫をKindleで読むためのRubyスクリプト

青空文庫を Kindle で読むには「Kindleストア>本>無料本」で探すのが一番簡単。Kindle ストアで見つからなければ、手元の Mac で mobi ファイルを作る。下準備に手間がかかるけれど、新着の小説をいち早く Kindle で読めるようになる。

動作環境:

$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.7.5
BuildVersion: 11G63

手順

0. 前準備(ツールの入手)
1. 青空文庫からXHTMLを入手
2. mobiに変換し確認

0. 前準備(ツールの入手)

(1) Rubyスクリプト aozora2kindle.rb を github からインストール

$git clone https://github.com/takatama/aozora2mobi-ruby.git

(2) RubyでXHTMLを操作するためにHTMLパーサー nokogiri をインストール

Nokogiri
http://nokogiri.org/tutorials/installing_nokogiri.html

の手順に従うんだけれど、少々面倒。

(3) KindleGenと、Kindleプレビューツールを以下からインストール。いずれも無料。

Amazon.co.jp:Kindle ダイレクト・パブリッシング:ヘルプ
https://kdp.amazon.co.jp/self-publishing/help?topicId=A3IWA2TQYMZ5J6

KindleGenは、XHTMLファイルからmobiファイルを作るコマンドラインツール。zipを解凍したディレクトリを適切な場所に移動してから、

$cd aozora2kindle-ruby
$ln -s (解凍したディレクトリ)/kindlegen .

としておくと便利。

Kindleプレビューツールはできたmobiファイルを確認するためのGUI。「アプリケーション」フォルダに移動しておく。

1. 青空文庫からXHTMLを入手

青空文庫のXHTMLへのURLを探す。例えば、坊ちゃんの場合は、次のURLになる。

http://www.aozora.gr.jp/cards/000148/files/752_14964.html

このURLをaozora2kindle.rbに渡して実行。

$cd aozora2kindle-ruby
$ruby aozora2kindle.rb http://www.aozora.gr.jp/cards/000148/files/752_14964.html

すると、752_14964.htmlが作成される。あわせて、mobi ファイルに変換するための下準備として、(1) XHTMLファイルが参照するCSSファイルの入手、(2) CSSファイルが参照する画像の入手、(3) CSSファイルでの縦書き指定、(4) XHTMLファイルが参照する画像の入手、をそれぞれ実施している。

2. mobiに変換し確認

KindleGenを使って、下ごしらえしたXHTMLファイルをmobiファイルに変換する。

$./kindlegen 752_14964.html

Kindleプレビューツールを使って、できたmobiファイルを確認する。mobiファイルをKindleに送信すれば持ち運べるようになる。

書籍「プレゼンテーション・パターン」で紹介されているTEDへのリンク集

聴き手にとって「価値あるプレゼンテーション」とは何だろう?

書籍「プレゼンテーション・パターン」では、価値あるプレゼンとは「聴き手が新しい発想や発見を生み出すきっかけを得ること」とし、それを実現するための33のポイント(パターン)を平易にまとめている。

ともするとおざなりになってしまうプレゼンの準備だが、この本はいいガイド役になりそうだ。「何のためのプレゼンなの?」という問いを、何度も自分に投げかけ、最後まで手を抜かずに磨き上げられるようになる。

無料の「カタログ版」も公開されているが、書籍だと直線的に全てのパターンを学べるため、パターン間のつながりをより理解しやすい。

書籍では、それぞれのパターンの好例としてTEDのプレゼンを紹介している。アクセスしやすいよう、TEDへのリンクを抜き出してまとめてみた。

No.7 メリハリ Dramatic Modulation 変化に富むリズムで、時間展開をデザインする。

「メリハリ」をつけて語るのがうまい人に、ダニエル・ピンクがいます。さすがに副大統領(アル・ゴア)のスピーチライターをしていただけあって、とても印象に残る語り方をします。彼のTEDトーク「やる気に関する驚きの科学」などを見ると、「強弱」や「スピード」と「間」、「繰り返し」をどのように入れると効果的かを学ぶことができます。(「プレゼンテーション・パターン」p.44)

No.8 驚きの展開 Unexpected Evolution ときには、聴き手の予想の外側へ。

さらに、プレゼンテーションの最後に、意外性を入れることもできます。「実は…」というかたちで、ある種のオチをつけるという終わり方です。ただし、ここでも内容や印象を損ねるような意外性は御法度です。これまで聴き手がプレゼンテーションを聴いてきたことを台無しにしてしまうからです。そうではなく、プレゼンテーションの内容を強化するように入れることが大切なのです。この好例としては、グレアム・ヒルのTEDトーク「モノは少なく、幸せは大きく」があります。実際は見ていただきたいので具体的には書きませんが、最後のシーンで「実は、この箱は…」と意外性を組み込んでいます。プレゼンテーションの内容を損なわずに強化し、とても印象的になっています。(「プレゼンテーション・パターン」p.47-48)

No.12 魅力のちょい足し Slite Enchantment ちょっとした魔法で、世界がまったく変わって見える。

過去の自分についてのエピソードに「笑い」や「弱さ」を加えて「魅力のちょい足し」をしているものにエリック・ウィテカーのTEDトーク「バーチャル合唱団2000人の声」があります。どのようなものかは実際に見ていただくのが一番ですが、この講演の後半には、「こだわり抜いたつくり込み」も登場するので、その部分もぜ味わってみてください。(「プレゼンテーション・パターン」p.63-64)

No.13 イメージの架け橋 Imagination Bridge 喩えや例をつかってわかりやすく。

ここで一つ、「イメージの架け橋」を見事に行っている実例を紹介しましょう。ハンス・ロスリングのTEDトーク「増え続ける世界人口」です。この講演で彼は、人口の規模を「箱」(衣装ケース)を使ってわかりやすく説明しました。一つの箱を十億人とし、その数を増やすことで人口成長を表し、位置を変えることで経済発展の度合いを示しました。さらに、経済の成熟度をイメージしやすくするために、車や飛行機の模型も持ち出します。こおように、人口規模や経済発展というつかみどころのない概念を、わかりやすいメタファーや具体例を用いることで、誰にとっても理解しやすいものにしました。まさに聴き手との間に「イメージの架け橋」つくっているのです。彼の魅せ方が巧みなのは、最初に「箱」という身近なものを用いて大づかみのイメージを持ってもらった後に、アニメーションによって世界人口の変化の動きを感じてもらうという構成になっている点です。わかりやすい静的(スタティック)なイメージから始めて、動的(ダイナミック)なイメージへと進めていく点など、実に巧みです。(「プレゼンテーション・パターン」p.71-72)

No.14 リアリティの演出 Reality Sharing つかみきれない「感覚」を届ける。

「リアリティの演出」の例に、デレク・シヴァーズのTEDトーク「ムーブメントの起こし方」があります。彼はリーダーとフォロワーの関係という話を、一つの映像を見せながら語っていきます。三分間のトークのなかで文字は一切登場せず、映像だけを使って、とても実感しやすいプレゼンテーションになっています。(「プレゼンテーション・パターン」p.75)

もう一つ、デブ・ロイのTEDトーク「はじめて言えたとき」も「リアリティの演出」がふんだんに行われています。この講演で取り上げられている彼の研究は、その発想もアプローチもかなりユニークで突き抜けています。突き抜けているがゆえに、研究手法や研究成果の説明を聴くだけでは、なかなかイメージすることができません。彼のプレゼンテーションがすばらしいのは、魅せ方にも相当こだわり、リアルに感じてもらうための工夫をふんだんにしていることです。たとえば、部屋のあちこちにビデオカメラを設置したという「説明」だけでなく、その録画映像をすべて概観できるようにして見せたり、部屋のどの部分でどの言葉が多く発せられたのかというランドスケープ(地形)を、実際の映像や音声とともに見せたりと、かなりイメージしやすくなるように表現してくれています。(「プレゼンテーション・パターン」p.75-76)

No.20 きっかけスイッチ Boot Switch 次の行動に移すためのきっかけづくり。

「きっかけスイッチ」の例として取り上げたいのは、ミック・エベリングのTEDトーク「体の不自由なアーティストに自由を与える発明」です。彼の話は、身体が不自由になったアーティストが再びアートを始められる装置の開発に成功したという、とても素敵な実話です。しかし、彼はこのプレゼンテーションを自分のプロジェクトの紹介では終わらせませんでした。最後のシーンで、聴き手に「不可能に思えることに出会ったら、それを可能にしよう」(If you see something that’s not possible, make it possible.)と語りかけます。そして「今でないとしたら、いつなんだ?自分がやらなければ、誰がやるんだ?」(If not now, then when? If not me, then who?)と自分に問いかけるようにしてほしい、と訴えかけます。これが彼の「メインメッセージ」です。この締めくくりによって、それまで語ってきた話が「世界のどこかで起きた素敵な実話」ではなくなり、「不可能に思えることを可能にした」事例の一つになりました。プレゼンテーションの最後にこのような捉え直しをすることで、聴き手の「きっかけスイッチ」を押したのです。(「プレゼンテーション・パターン」p99-100)

No.25 キャスト魂 Presentership 立ち振る舞いもプレゼンテーションの一部である。

このような「キャスト魂」を感じさせてくれるのが、スーザン・ケインのTEDトーク「内向的な人のパワー」です。彼女曰く、彼女自身が「内向的」なのですが、「キャスト魂」をしっかり持って、見事に講演をしています。(「プレゼンテーション・パターン」p.124)

No.28 世界への導き World Invitation 徹底した世界観が聞き手の感動を生む。

「世界への導き」の好例に、ジル・ボルティ・テイラーのTEDトーク「脳卒中を語る」があります。脳の研究者である彼女は、ある時自分が脳卒中になってしまいます。そのときの珍しい体験について、彼女は「キャスト魂」がこもった圧巻の「ストーリーテリング」によって語ってくれます。プレゼンテーションの冒頭で、日常的な話と科学者であることを印象づけて、入りやすい「入口」をつくっています。その後は、彼女の体験した「世界」へと聴き手を導いていきます。とても引き込まれるプレゼンテーションなので、まだ見たことがない方はぜひ見てみてください。(「プレゼンテーション・パターン」p.136)

Google Analyticsを使ったコホート分析で施策の有効性を検証する

サービスを成長させるためには、機能追加や削除、デザイン変更、広告など、様々な施策によって新たなユーザーを集客する必要がある。ある施策によって集客したユーザーの集団(コホート)の動向を時系列で分析する「コホート分析」により、その施策の有効性を検証することができる。

例えば、獲得ユーザーを月ごとに分け、再訪問者数をプロットしている(How to do Cohort Analysis in Google Analyticsより引用)。獲得した次の月になると、再訪問者は大幅に下がる様子がわかる。9月と11月の獲得ユーザーで比べると、11月の方が月を再訪問者数を保持できており、改善効果が見て取れる。

以下では、Google Analyticsを使い「初訪問した時期」でコホート分析するための具体的な手続きを紹介する。

(1) トラッキングコードの設置

Google Analyticsのトラッキングコードが以下だとして、

<script type="mce-text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
    _gaq.push(['_trackPageview']);
    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
     })();
</script>

次のようなコードを追加して、ユーザーの初訪問日をyyyymmdd形式でカスタム変数に保存する。具体的には、2013年3月28日に初訪問していたユーザーは、カスタム変数名「FirstVisit」に、値「20130328」を保存する。

<script type="mce-text/javascript">
    var _gaq = _gaq || [];

    try {
        var f = function (d) {
            return d.getFullYear() + ("0" + (d.getMonth() + 1)).slice(-2) + ("0" + d.getDate()).slice(-2);
        };
        var c = document.cookie;
        var i = c.indexOf('__utma');
        var s = null;
        if (i < 0) {
            s = f(new Date());
        } else {
            var utma = c.substring(i, c.indexOf(';', i));
            if (utma) {
                var v = utma.split('.');
                if (v[2]) {
		    var date = new Date();
                    date.setTime(v[2] * 1000);
                    s = f(date);
                }
            }
        }
        if(s) {
            _gaq.push(['_setCustomVar', 1, 'FirstVisit', s, 1]);
        }
    } catch (e) {
    }

    _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
    _gaq.push(['_trackPageview']);
    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
     })();
</script>

trackPageviewを実行するより前に、setCustomVarを実行する点に注意する(Recommended Practiceを参照のこと)。

(2) アドバンスセグメントを使った分析

Google Analyticsの左側ペインで、ユーザー>カスタム>カスタム変数、を選択し、カスタム変数 FirstVisit が取得できていることを確認する。もし、取得できていない場合は、Google Analyticsで閲覧している日付に間違いがないか、埋め込んだトラッキングコードに間違いがないか(正しく実行できていれば、__utmvというクッキーが作成されている)などを見直す。

スクリーンショット 2013-03-28 17.00.43

以下、「2013年3月に初訪問した人」の集団について分析するため、「FirstVisit の値が 201303 になっている人」を抽出するカスタムセグメントを作る。

右側ペインの上部の「アドバンスセグメント」を選択し、右下の「新しいカスタムセグメント」を押下する。

スクリーンショット 2013-03-30 1.49.18

下図のように「カスタム変数(キー1)」は「FirstVisit」と「完全一致」、さらに、「カスタム変数(値01)」は、「201303」と「前方一致」させる。

スクリーンショット 2013-03-30 1.50.34

これで、2013年3月に初訪問した人たちが、サイトにどれだけ再訪問し、どう利用しているかを把握できるようになる。

スクリーンショット 2013-03-30 1.58.36

参考にしたサイト:

アクセス分析の有意性を高めるためにKISSmetricsがコホート分析を導入 | TechCrunch Japan
http://jp.techcrunch.com/2011/09/24/20110923kissmetrics-helps-you-hone-in-on-stats-that-actually-matter-with-cohort-reports/

How to do Cohort Analysis in Google Analytics | Jonathon Balogh
http://jonathonbalogh.com/2012/04/01/how-to-do-cohort-analysis-in-google-analytics/

How to do Cohort Analysis in Google Analytics | Jonathon Balogh
http://jonathonbalogh.com/2012/04/01/how-to-do-cohort-analysis-in-google-analytics/

Google Analyticsで、新規訪問の日を記録するには? – QA@IT
http://qa.atmarkit.co.jp/q/2274

Custom Variables – Web Tracking (ga.js) – Google Analytics — Google Developers
https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingCustomVariables

カスタム変数を作るコードは、Gistにもあげておいた。

try {
var f = function (d) {
return d.getFullYear() + ("0" + (d.getMonth() + 1)).slice(-2) + ("0" + d.getDate()).slice(-2);
};
var c = document.cookie;
var i = c.indexOf('__utma');
var s = null;
if (i < 0) {
s = f(new Date());
} else {
var utma = c.substring(i, c.indexOf(';', i));
if (utma) {
var v = utma.split('.');
if (v[2]) {
var date = new Date();
date.setTime(v[2] * 1000);
s = f(date);
}
}
}
if(s) {
_gaq.push(['_setCustomVar', 1, 'FirstVisit', s, 1]);
}
} catch (e) {
}
view raw ga-cohort.js hosted with ❤ by GitHub

jsdo.itでProcessingを動かす

メディアアートのためのプログラミング言語ProcessingProcessing.jsを使うことで、作った作品をJavaScriptのコミュニティサイトjsdo.itに公開することができる。

jsdo.itでの手順は次の通り。

(1) jsdo.itで新しいコードを書き始める(Start Coding)

スクリーンショット 2013-03-21 13.14.10

(2) JavaScriptのライブラリ追加(Add Library)

スクリーンショット 2013-03-21 13.16.46

(3) Processing.js v1.4.0 – js を選択して Add

(4) HTMLタブに以下のテンプレートを記述

<script type="application/processing" data-processing-target="pjs">
//Processing code is here
</script>
<canvas id="pjs"> </canvas>

(5) //Processing code is here のところに、Processingのコードを記述

このやり方では、JavaScriptタブにはコードを書かない。

Built with Processing[Ver. 1.x対応版] -デザイン/アートのためのプログラミング入門 3-6-4 力をためる、をベースに作ったコードを jsdo.it で公開してみた。

力をためる – jsdo.it
スクリーンショット 2013-03-21 13.03.26

Built with Processingはとても丁寧な解説で、プログラミング自体の入門書としてもオススメ。小学校4年生の娘もこの本(の前半)を使って自習していて、思い通りに動いたときには喜びに身悶えしてる。

JavaScript Development Tools – JavaScript開発の効率アップ

id:Layzie さんの発表「JavaScript Development Tools – JavaScript開発の効率アップ」がためになったので、プレイリストを作ってみました。(xx:xx) をクリックすると、該当する動画に飛びます。

Layzieさんによる発表への補足記事はこちらです。