dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

ES2015時代のJavaScriptテストツールまとめ

最近になって JavaScript を勉強中です。
ES2015 と React にもちょっとずつ慣れてきましたが、テストについては Karma とか mocha とか名前は聞くけど何が何なのかよくわかってなかったので、軽く整理してみます。


JavaScript テストツールの大まかなカテゴリ

JavaScript のテストツールは、だいたい以下のようなカテゴリに分類することができます。

  1. アサーションライブラリ
  2. テストフレームワーク(テスティングフレームワーク
  3. テストランナー

以下、それぞれについての説明と、代表的なライブラリを見ていきます。
★は個人的にこれを使おうかなと思ったやつです。


1. アサーションライブラリ

テストの一番重要な部分である、「A は B である(assert A === B)」を検証する(ためのメソッドを提供する)ライブラリ。
代表的なものとして、以下があります。

Node.js の標準 assert

Node.js 自体にも assert モジュール があるようです。

expect.js
  • Redux の examples のテストで使われているのはこれ
  • メソッドとしては expect() のみ
chai
  • mocha の Introduction で使われているのはこれ
  • メソッドとしては should(), expect(), assert() がある
power-assert
  • テスト界隈で有名な t_wada さんが開発したライブラリ
  • 厳密に言うとアサーションライブラリではないらしい
  • メソッドとしては assert() のみ
  • Node の assert と比べ、テスト結果として出力される情報がわかりやすい
  • 参考:5minで分かるpower-assert


2. テストフレームワーク

テストを実行するためのツール。
テストフレームワークに従った書き方でテストを書き、実行するとテスト結果を確認することができる。

代表的なものは以下。

mocha
  • Redux の examples のテストで使われているのはこれ
  • テストスイートに相当するものを describe で、テストメソッドに相当するものを it で書く
  • サンプル
import { expect } from 'chai';
import add from './my-add-function';

describe('add() の機能', () => {
  it('1 + 1 は 2 になる', () => {
    expect(add(1, 1)).to.equal(2);
  });

  it('負の数も扱うことができる', () => {
    expect(add(-1, 1)).to.equal(0);
  });
});
Jasmine


3. テストランナー

先ほどのテストフレームワークだけでもテストを実行することが可能ですが、
テストランナーを使うと様々なブラウザ環境でテストを実行させたり、テスト結果やカバレッジを見やすい形式で出力することができるそうな。

代表的なものは以下。

Karma
testem
  • 名前だけ聞いた。現在も流行っているのかどうか不明


番外編

上記の3カテゴリにはあてはまりませんが、それ以外に有名なライブラリをいくつか。
これらはいずれも以下の記事で紹介されており、一通り読むとどんなものか知ることができます。React のテストの書き方を学ぶ上でも大変良い記事です。

Sinon.js
(React 限定)Enzyme


まとめと TODO

調べる前はなんでいろんなものを組み合わせて使う必要があるのかわかってませんでしたが、それぞれ役割が異なるんですね。

各ツールについてはなんとなく理解できたので、
次は実際に karma + mocha + power-assert という組み合わせで、ES2015 で書いた React/Redux アプリのテストを書いてみようと思います。

リファレンス

AsciiDocによる継続的ドキュメント開発〜1.インストールと基本的な使い方

はじめに

ドキュメントを書くための言語としておそらく今一番ポピュラーなのは Markdown だと思いますが、
かっちりした仕様書やユーザーマニュアルなど、より本格的なドキュメント作成にはやや機能不足と感じることがあります。

私も以前、ドキュメントを Gitbook で作れないか検討したことがあったんですが
表を書くのがめんどくさかったり、図のキャプションなどに対応していなかったことから断念しました。

そこで、今回は Markdown よりも表現力の高い言語として知られる AsciiDoc を試してみます。
AsciiDoc は O'reilly でも採用されているほか、Pro GitJavaScript Promise の本 などの非常に完成度の高い技術ドキュメントが AsciiDoc で書かれています。

(参考記事)
テクニカルライティングの未来を先取り ー Asciidoc フォーマットと GitHub を使って技術書 Pro Git を共同執筆 — Japanese Official — Medium
JavaScript Promiseの本を書きました | Web Scratch

やりたいことは色々とあるんですが、まずはインストールと基本的な使い方を学ぶところまでやってみます。

参考書籍

この書籍を読みながら勉強中です。
本屋でざっと流し読みした感じ、AsciiDoc で書いたドキュメントを GitHub で管理したり、校正ツールや CI を導入したりと
自分のやりたいことがそのものずばりって感じです。


インストール

Asciidoctor という AsciiDoc の Ruby 実装をインストールします。 AsciiDoc のリポジトリ を見ると HTML などに変換するプロセッサーも用意されているようですが、
実際に AsciiDoc を HTML や pdf に変換するためのプロセッサーは Asciidoctor の方が一般的のようです。

ブログを書いた時点での Ruby のバージョンは以下です。

$ ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin14]
$ gem -v
2.4.5.1
$ bundle -v
Bundler version 1.12.5

インストール方法は、普通に

$ gem install asciidoctor

を実行するか、または Gemfile を用意し

source 'https://rubygems.org'
gem 'asciidoctor'

と記述した後、

$ bundle install

を実行します。

$ bundle install
Fetching gem metadata from https://rubygems.org/
Fetching version metadata from https://rubygems.org/
Resolving dependencies...
Installing asciidoctor 1.5.4
Using bundler 1.12.5
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.

インストールすると asciidoctor というコマンドが実行可能になります。


基本的な使い方:HTML, pdf, epub の作成

さっそく何かドキュメントを書いてみます。
拡張子は .adoc または .asciidoc にします。

= はじめての AsciiDoc ドキュメント

これは AsciiDoc で書かれたドキュメントです。

== セクション

``=`` から始まる行はセクションの見出しになります。 +
``==``, ``===``, ... のように `=` を重ねるとレベルが1つ下がります。

== テーブル(表)

.テーブル見出し

|=======================
|Col 1|Col 2      |Col 3
|1    |Item 1     |a
|2    |Item 2     |b
|3    |Item 3     |c
|=======================

CSV 形式で書くこともできます。

[format="csv"]
|======
1,2,3,4
a,b,c,d
A,B,C,D
|======

== ソースコード

[source, javascript]
----
export default class MyComponent extends React.Component {
    render() {
        <div>Hello, World!</div>
    }
}
----
HTML への変換

HTML への変換は、asciidoctor コマンドを実行するだけです。

$ ls
sample-doc.adoc
$ asciidoctor sample-doc.adoc
$ ls
sample-doc.adoc sample-doc.html

生成した HTML はこちら。

f:id:dackdive:20160614013736p:plain

デフォルトのスタイルでもイイ感じですが、ソースコードが色付け(シンタックスハイライト)されてませんね。

ソースコードシンタックスハイライト

http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#source-code を読むと、
ファイルの先頭で source-highlighter という変数を定義する必要があるようです。
また、シンタックスハイライト用のプラグインをいくつかの選択肢の中から選んでインストールする必要があります。

今回は coderay を選択します。

$ gem install coderay

でインストールした後、.adoc ファイルの先頭に以下を追記します。

:source-highlighter: coderay

この状態で HTML に変換すると、シンタックスハイライトが有効になります。

pdf への変換

HTML 以外の形式への変換は、別途プラグインをインストールする必要があります。
Converters の項を参照)

pdf については asciidoctor-pdf をインストールします。

$ gem install asciidoctor-pdf

コマンドが asciidoctor-pdf になること以外は HTML の時と変わりません。

$ ls
sample-doc.adoc sample-doc.html
$ asciidoctor-pdf sample-doc.adoc
$ ls
sample-doc.adoc sample-doc.html sample-doc.pdf

生成した pdf がこれです。

f:id:dackdive:20160614023314p:plain

フォントなど、スタイルで気に入らない部分があるかもしれませんが CSS で調整可能のようです。これについてはまた今度。

epub への変換

epub については asciidoctor-epub3 をインストールします。
参考:How to Convert AsciiDoc to EPUB3 with Asciidoctor | Asciidoctor

まだ試せてないので今後の課題として。


(おまけ)エディタの設定

最後に、AsciiDoc を書きやすくするためにエディタも設定しておきます。
Atom の場合、公式ドキュメント
http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/#atom
にあるように、以下2つのプラグインをインストールすると良さそう。

asciidoc-preview を入れると(Mac の場合)cmd + Shift + A でプレビューを表示させることができます。便利。

f:id:dackdive:20160614204519p:plain

一方、私は普段 Vim を使ってるんですが、Markdown ではできたプレビュー機能を提供するプラグインは見つからず。

参考:[vim]vimでmarkdownをリアルタイムプレビューできるようにする - dackdive's blog


触ってみた感想

Markdown ではネックだった表が CSV 形式で書けたり、ちょっと調べた感じだと図のキャプションに対応していたりと
Markdown では対応できなかったところをカバーしてくれそうな印象。

ただ、以前 Gitbook 調査していて gitbook-cli を使ったときは

$ gitbook serve

みたいなコマンドでローカルサーバーが立ち上がり、以後、ファイルの変更を検知して常に最新の HTML を表示することができていたんですが
Asciidoctor 単独だとそういった機能は提供していないので、gulp タスクなり Makefile なりでそのあたりも自分で作る必要がありそうです。


今後の予定

今後、こういったことをできるようにしていきたいです。

  • epub 形式に変換する
  • ローカルでドキュメントを書くときはローカルサーバーを起動し、自動で HTML 変換する
  • RedPen や textlint などの文法チェックツールを使用する
  • Travis CI などの CI ツールで GitHub にコミット時に自動的に文法チェックを実行する
  • CI の一環で、最新のドキュメントの HTML 版が常にどこかにデプロイされるようにする

とりあえず、今後も色々と機能追加していくと思うので、コードを GitHub に上げておきます。

[git]複数のcommitをまとめてcherry-pickする

ちょいメモ。

別ブランチのコミットを他のブランチにも適用するときに便利な cherry-pick コマンドですが、
複数のコミットをまとめて cherry-pick してしまいたい時がたまにあります。

そんなとき

$ git cherry-pick [cherry-pick の始点となるコミット]..[cherry-pick の終点となるコミット]

というように、A..B という指定のしかたでコミット A からコミット B までの一連のコミットを cherry-pick することが可能です。

が、注意点として、始点となるコミットは 実際に cherry-pick したいコミットの1つ前 を選ぶ必要があります。

以下、例。

$ git branch -a
* master

$ git log
commit 63ca256a5f806c8b237c3ff5c872debc0be12359
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:22:35 2016 +0900

    first commit

$ git checkout -b foo

# 略: foo ブランチ上でコミットを進める

$ git log
commit 738b8de617497b37bc47c06ce9fa9f676c256b61
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:23:39 2016 +0900

    commit 3

commit bee000f8a765367fe489302b064f856b2e1b259a
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:23:12 2016 +0900

    commit 2

commit d4baa931f1d2c3259c45109b880b9222a592c61f
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:22:59 2016 +0900

    commit 1

commit 63ca256a5f806c8b237c3ff5c872debc0be12359
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:22:35 2016 +0900

    first commit

$ git checkout master

# commit 1 ~ commit 3 までを master に cherry-pick したい
# 1) 始点に commit 1 を指定した場合
# conflict する...
$ git cherry-pick d4baa931f1d2c3259c45109b880b9222a592c61f..738b8de617497b37bc47c06ce9fa9f676c256b61
error: could not apply bee000f... commit 2
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

# 2) 始点に commit 1 の1つ前を指定した場合
# 正常に cherry-pick できる
$ git cherry-pick 63ca256a5f806c8b237c3ff5c872debc0be12359..738b8de617497b37bc47c06ce9fa9f676c256b61
[master 2326872] commit 1
 Date: Mon Jun 6 17:22:59 2016 +0900
 1 file changed, 1 insertion(+)
[master 85d0cd2] commit 2
 Date: Mon Jun 6 17:23:12 2016 +0900
 1 file changed, 1 insertion(+)
[master 3299797] commit 3
 Date: Mon Jun 6 17:23:39 2016 +0900
 1 file changed, 1 insertion(+)

$ git log
commit 3299797bf2964b6c728eb268255e34eee5877dd0
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:23:39 2016 +0900

    commit 3

commit 85d0cd22f4d962b8b6c670dd0894874049437343
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:23:12 2016 +0900

    commit 2

commit 2326872f0c80c9b2dd83200ba039aba0ceef9b9f
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:22:59 2016 +0900

    commit 1

commit 63ca256a5f806c8b237c3ff5c872debc0be12359
Author: zaki-yama <xxx@gmail.com>
Date:   Mon Jun 6 17:22:35 2016 +0900

    first commit

Summer '16 開発者向けWebセミナー のメモ

Summer '16 開発者向けWebセミナー | Salesforce Developers

割とちゃんと観た。

UI の新機能(Lightning Experience)

  • ホーム画面のカスタマイズ
  • Lightning App Builder で作ったページが(ようやく)LEX とモバイル両方で使用可能 f:id:dackdive:20160603154909p:plain

  • オブジェクトの日付項目からカレンダーの予定を作成可能

  • レポートのフィルタリング

Apps の新機能(Sales, Service, Mobile, Wave)

Sales Cloud

  • 取引先責任者と複数の取引先の関連づけを許可
    • Contact.Account.Id ができなくなり、AccountContactRelation が追加(連結オブジェクト?)
    • データモデル変更になるのつらい...
  • Lightning ボイス(日本ではまだ)

Wave

  • CSVExcel 形式でのダウンロード
  • SAQL、集計関数の拡張

Mobile

  • オフライン機能(公開パイロット)
    • S1 for Android 9.0 で提供、S1 for iOS(予定)

Identity とセキュリティの機能拡張

  • テンポラリ認証コードの生成
    • 2要素認証を利用するユーザがデバイスを忘れたりしたときに、一時的に認証コードを発行
    • このコードを生成するだけの PermissionSet が追加
  • ユーザ切り替えの簡素化(LEX のみ)
    • 設定項目あり(セッション)

一般的な開発の新機能

  • Lightning プロセスビルダー
    • 複数条件でのアクション実行が可能
      • 1個目の条件を満たした場合、そこで処理をやめるか次の条件に進むか選べるように

f:id:dackdive:20160603154333p:plain

  • 制限つき選択リスト(正式リリース)
    • 選択リストの選択肢にある値以外は API 経由でも登録できなくするやつ
  • Flow REST API
  • イベントモニタリング
    • Wave App として
    • 別途契約が必要
  • セッションベースの権限セット(開発者プレビュー)
    • 特定の種類のセッションでのみ有効な権限セットを割り当て

Apex

  • UI からテスト結果の確認(LEX のみ)
    • 開発者コンソールと同じ
  • getPopulatedFieldsAsMap()

f:id:dackdive:20160603154924p:plain

Visualforce

  • LEX での Visualforce の使用が GA に
    • 使えない機能もあり
    • まだスタイルが自動で当たるわけではない

Lightning Component

  • アクセスチェックエラーの強制
    • <aura:component access="global"> とかちゃんとつけようねという話

その他

  • LEX の IE11 のサポート終了
  • Chatter デスクトップ終了

ESLintでReactとES2015の構文チェック(eslint-config-airbnb)

ES2015の構文チェックと言えば ESLint ですね。
ESLint は "The pluggable linting utility" というだけあって、Rules と呼ばれる膨大なチェック項目の中から
自分がチェックしたい項目を取捨選択し、最終的に .eslintrc という設定ファイルを用意する必要があります。

ただ、さすがに一から自分でルールを構築するのは面倒なので、通常は Shareable Configs と呼ばれる機能を使い、他の人が大体いい感じにセットアップしたものを共有することができます。
eslint-config-airbnb もこの Shareable Configs の1つで、React に関する lint も含まれているのでとりあえずはここから始めるのが良さそうです。

インストールと設定

package.json は作成済みとします)

eslint-config-airbnb の README の通りに、必要なパッケージをインストールします。

$ npm install --save-dev eslint-config-airbnb eslint-plugin-import eslint-plugin-react eslint-plugin-jsx-a11y eslint

インストール後、設定ファイル .eslintrcextends: airbnb を追加します。

{
  "extends": "airbnb"
}


ESLint の実行

package.json に以下のように記述し、npm scripts として実行できるようにします。
(以下は、ソースコードsrc ディレクトリにある場合)

{
  "scripts": {
    "lint": "eslint src/**/*.js"
  },
  ...
}

ESLint を実行します。

$ npm run lint
> react-es6-tutorial@1.0.0 lint /Users/yamazaki/workspace/react/react-es6-tutorial
> eslint src/**/*.js


/Users/yamazaki/workspace/react/react-es6-tutorial/src/app.js
  5:7   error  'data' is defined but never used  no-unused-vars
  6:3   error  A space is required after '{'     object-curly-spacing
  ...

構文チェックに引っかかった箇所がずらーっと表示されます。


eslint-config-airbnb のカスタマイズ

デフォルトの設定を遵守してもいいですが、自分好みにカスタマイズしたいルールもあると思います。
たとえば、eslint-config-airbnb そのままでは comma-dangle というルールが有効になっているようです。
これは、オブジェクトリテラルの最後の要素にも , がついてないと警告するものです。

var foo = {
    bar: "baz",
    qux: "quux",  // ここにも , が必要
};

このルールを無効にしてみます。

ルールのカスタマイズは .eslintrcrules という項目を記述することで実現できます。

{
  "extends": "airbnb",
  "rules": {
    "comma-dangle": 0
  }
}

rules にはルール ID(一覧は ここ)と 0 ~ 2 までの値のペアを列挙します。
0 ~ 2 までの値はそれぞれ以下の意味を持ちます。

  • 0 または "off" : 無効
  • 1 または "warn" : 警告
  • 2 または "error" : エラー

Configuring Rules の項を参照)

警告とエラーの違いはよくわかってませんが。。。


おまけ:エディタから ESLint を実行する

npm scripts から実行すると src ディレクトリ内のファイルすべてがチェック対象になってしまい、警告が多いと結果を確認するのが大変です。
かといって、対象ファイルを指定するために毎回 package.json を修正するのも面倒です。

というわけで、エディタと ESLint を連携し、編集中のファイルに ESLint を実行できるようにしておきます。

順番は前後しますが、これについては Vim の設定方法を記事に書きました。

また、記事の最後に Atom の設定で参考になりそうな記事も載せています。


さらにおまけ:ESLint の parser オプションについて

たまに、.eslintrcparserbabel-eslint を指定しているのを見かけます。

{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "rules": {
    ...
  }
}

指定するべきなのかな、と思ったのですが、README の冒頭に

Note: You don't need to use babel-eslint if you are only using ES6/ES2015. ESLint actually supports ES6/ES7, JSX, and object rest/spread by default now.

と書かれているので、とりあえず ES2015 で React 書いてる分には必要なさそうという結論になりました。


リファレンス

eslint-config-airbnb 以外の Shareable Configs も紹介されてます。

また、eslint-config-airbnb は比較的厳しめと聞いてますが、コメント欄読むとそれでも十分でない項目もあるみたいです。

webpack-dev-serverの基本的な使い方とポイント

はじめに

(2017/08/10追記)

この記事では webpack-dev-server を独立したサーバーとして使う場合の方法です。
また webpack 1 系の情報になっており少々古いです。

最新の設定についてはこちらの GitHub リポジトリを参考にしてください。
https://github.com/zaki-yama/redux-express-template

(追記ここまで)

JavaScript のビルドに webpack を使っている場合、ローカルでの開発には webpack-dev-server を使うと便利です。
通常の webpack コマンドも --watch (または -w)オプションつきで実行することにより
ファイルの変更を検知して自動でリビルドを行うことが可能ですが、
webpack-dev-server は上記に加えて

  • ローカルサーバーも起動してくれる(中身は Node.js の Express サーバーらしい)
  • ファイルの変更を検知して自動ビルドした後、ブラウザも自動的にリロードしてくれる(Automatic Refresh)
  • ブラウザ全体のリロードではなく、編集したモジュールのみを更新する Hot Module Replacement という仕組みが使える(後述)

といった機能を備えているため、ローカルで開発する分にはこちらを使う方が便利です。

ここではその基本的な使い方と、個人的に気をつけたいと思った部分をポイントとしてまとめておこうと思います。

なお、ここでは webpack-dev-server や Hot Module Replacement がどういった仕組みで動いているのかについては言及しません。(私も理解していません。。。)
そういった話についてはこの記事が参考になりそうです。


(2017/06/15追記)

この記事では webpack-dev-server を独立したサーバーとして使う場合の方法です。Express に組み込む場合の手順はこちら。

(追記ここまで)

続きを読む