注意
この記事は、2014年の段階でNode.jsの開発時にデバッグ~継続的インテグレーションが行えるようにするために必要な情報をまとめていました。
その後、2020年08月にnode v12.18.3を対象に調査しなおしました。
Node.jsのインストール方法
ここから、インストーラなりソースなり取得してインストールする。
Windows,Macはインストーラが存在している。
Windowsの場合、VS2008や、VS2012などの複数のVisualStudioが混在している環境だとnpm installが失敗することがあった。
その場合は、環境変数を調整してVisualStudioのバージョンを指定して動作するようにしておくこと。
Node.jsのデバッグ方法(2020年)
ローカルのデバッグ
Visual Studio Codeでアプリケーションのあるフォルダを開いて実行すると、デバッグが可能
chromeを用いてリモートデバッグを行う方法
事前準備
下記の拡張機能をChromeにインストールする。
デバッグ方法
1. デバッグ対象のアプリケーションの起動方法
$ node --inspect=0.0.0.0 hello-world.js
Debugger listening on ws://0.0.0.0:9229/4d491e82-cd7a-4e4c-8ac0-914d14ab95d5
For help, see: https://nodejs.org/en/docs/inspector
Server running at http://192.168.0.100:3000/
デバッグ対象のホストのアドレスとポートを入力後、「Open DevTools」を開く
3. Chromeでデバッグが行えるようになる。
メモリの使用状況の例
Chromeの開発者ツールのメモリタブから調べることができる。
なお、かって存在したnode-webkit-agentについてはv0.12では使用できない。
https://github.com/c4milo/node-webkit-agent/issues/78
ガベージコレクションを実行する方法
Node.jsは世代別のガベージコレクションなので、解放したつもりでもメモリが残っている場合がある。そのときは、任意のタイミングでガベージコレクトを行ったあと、メモリのスナップショットを確認する。
ガベージコレクションを確実に走らせたい場合は以下のような処理が必要である。
まず、プログラム中でガベージクレクタを実行したい箇所に次のコードを埋め込む。
if(global.gc) {
global.gc();
}
gcを使用するにはアプリを起動する際に--expose_gcを指定すること。
node --expose_gc server.js
console.logによるオブジェクトの出力
Console.logを用いることでオブジェクトをコンソールに出力することができるが、この際、一部の内容しか表示されない場合がある。
この場合はutilモジュールを用いることですべての内容を表示させることができる。
const util = require('util');
console.log(util.inspect(obj,false,null));
静的解析
実際にプログラムを実行しないで、リスクのある記述方法を検知することができる。
これらの処理はJenkinsなどで定期的に実行するとよい。
eslintによる静的解析
2020年のnpmのトレンドとしてはeslintが優勢のようである。
https://www.npmtrends.com/jslint-vs-jshint-vs-jscs-vs-eslint
eslintについては以下のページを参照
https://eslint.org/
eslintをコマンドラインから使用する
1. 下記の通りインストールを行う。
npm install eslint --save-dev
※eslintをグローバルにインストールすることも可能ですが、これはお勧めされていません。
https://eslint.org/docs/user-guide/getting-started
2.解析対象のプロジェクトのpackage.jsonが存在することを確認する
存在しない場合は以下のコマンドで作成する。
npm init -y
3.eslintの設定ファイルを作成する。
npx eslint --init
上記のコマンドを実行することで対話形式で設定を行い.eslintrc.{js,yml,json}が作成される。
4.ファイルまたはフォルダを指定することで対象のファイルを解析できる。
npx eslint ~/nodejs/prj
その他の説明については下記を参照
コマンドラインの説明
https://eslint.org/docs/user-guide/command-line-interface
設定ファイルの説明
https://eslint.org/docs/user-guide/configuring
eslintをJenkinsで利用する
1.Warning Next Generationプラグインをインスト―ルする
2.ジョブの設定を行う
2.1 ビルド中に下記のコマンドを実行して静的解析の結果をXMLに保存する
cd c:\dev\node\
call npx eslint -f checkstyle c:\dev\node\sample.js > %WORKSPACE%\result.xml || type nul>nul
静的解析の警告が発生した場合eslintは1を返す。Jenkinsはバッチ実行中のコマンドが0以外を返すと中断されるため「|| type nul>nul」でエラーコードをクリアする。
2.2 ビルド後の処理を設定する
「ビルド後の処理」で「Record comppiler warnings and static analysis results」を選択する。
作成されたXMLをReport file patternに指定する。
**gjslintによる静的解析 (2014年時点の情報)**
gjslintのインストール方法
gjslintはPythonで動作するので、Pythonがインストールされていることが前提になる。
(1)easy_installを使用できるようにする。
wget http://peak.telecommunity.com/dist/ez_setup.py
python ez_setup.py
(2)gjslintをインストールする
easy_install http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz
gjslintの使用方法
使用例:
gjslint --disable 110,1 -r src
--disable コンマ区切りで無視するエラーを指定できる。
-r ディレクトリを再帰的に操作できる。
closure-linter-wrapperによるXML出力
gslintのみでは検査結果をXMLとして保存することはできない。XMLとして出力できないと、jenkinsによる定期ビルドに組み込むことができない。
これを行うためにはclosure-linter-wrapperが必要である。
https://github.com/jmendiara/node-closure-linter-wrapper
(1)closure-linter-wrapperのインストール
npm install -g closure-linter-wrapper
(2)次のようなtest.jsファイルを作成する。
var argv = process.argv;
var gjslint = require('closure-linter-wrapper').gjslint;
var flagsArray = [
'--nostrict',
'--nojsdoc',
'--disable 14'
];
console.log(argv[2] + 'src/*.js');
gjslint({
src: [
argv[2] + 'src/*.js'
],
flags: flagsArray
,reporter: {
name: 'gjslint_xml',
dest: argv[2] + 'gjslint.xml'
}
},
function (err, result) {
}
);
この例では引数でしたフォルダのsrc以下を解析してgjslint.xmlに出力する。
あまりに大量のデータを一気にgjslint関数に渡すと正常にXMLが作成されないので注意すること。
Jenkinsによるgjslintの集計
Jenkinsによりgjslintを定期的に実行し、その結果を集計することができる。
(1) jslintの結果を集計できるようにViolationsを入手する
Jenkinsの管理 > プラグインマネージャで利用可能タブから「Violations」を指定してインストールする。
(2) Jenkinsでシェルスクリプトを実行するようにして先に作成したclosure-linter-wrapperを使用するスクリプトを実行する
NODE_PATH=/usr/local/lib/node_modules
export NODE_PATH
node ${WORKSPACE}/test.js ${WORKSPACE}/
es6-platoによるコードメトリックスの収集
es6-platoを用いることで、ソースコードの行数や複雑度を計測できる。
https://github.com/the-simian/es6-plato
1.インストール方法
npm install --save-dev es6-plato
2.スクリプトから実行する
node_modules\.bin\es6-plato -r -d 出力フォルダ 解析対象のフォルダ
Complexityが高いものがバグを発生しやすいので、テストケースの数や、リファクタリングの目安として監視する。
これもjenkinsで日々作成するといい。
単体テストの自動化
ここではnode.jsでのテストの自動化について記述する。ここではサーバーサイドの単体テストの自動化についてのみ記載するものとする。
単体テストを自動化する場合、以下の機能が必要になる。
- テスト用フレームワーク
- モック・フェイク
- カバレッジの計測
テスト用フレームワーク
Mochaは、Node.jsとブラウザーで実行される機能豊富なJavaScriptテストフレームワークであり、非同期テストをシンプルで楽しいものにします。
注意:2020年時点でjestにトレンド的に抜かれたようです
https://www.npmtrends.com/jest-vs-jasmine-vs-mocha-vs-qunit-vs-ava-vs-chai-vs-expect.js-vs-should-vs-power-assert
インストール方法
プロジェクトフォルダにインストールを行う。
npm install --save-dev mocha
テストコードの記述例
testフォルダにテストコードを記載する。
var assert = require('assert');
describe('sample', function () {
it('syncOK', function () {
assert.equal(2+2, 4);
});
it('syncNG', function () {
assert.equal(2+2, 3);
});
it('asyncOK', function(done) {
setTimeout(function() {
assert.equal(2+2, 4);
done();
}, 15);
});
it('asyncNg', function(done) {
setTimeout(function() {
done('ng message');
}, 15);
});
});
実行例
下記のコマンドでtestフォルダ中のテストスクリプトを全て実行する。
npx mocha
Jenkinsとの連携方法
JUnit Reporter for Mochaを使用することでJUnitでのレポートを使用できる。
https://github.com/michaelleeallen/mocha-junit-reporter
npm install mocha-junit-reporter --save-dev
以下のコマンドを実行するとtest-result.xmlが作成される。
mocha --reporter mocha-junit-reporter
Windowsの場合は処理をとめないように以下のような処理を記載することになる。
cd c:\dev\node\
call npx mocha --reporter mocha-junit-reporter --reporter-options mochaFile=%WORKSPACE%\test_result.xml || type nul>nul
ワークスペースにxmlを格納する場合は「--reporter-options mochaFile=ファイルパス」を利用する。
ビルド後の処理に「JUnitテスト結果の集計」を利用する。
モック・フェイク
モックやフェイクを使用することで依存している部品をテスト用に差し替えて実行することが可能になる。
このモックやフェイクの機能はSinon.jsでサポートされている。
Sinon.js
https://sinonjs.org/
インストール
npm install sinon --save-dev
モック対象の関数が以下の通り存在したとする。
"use strict";
module.exports = {
add: ( num1, num2 ) => {
return num1 + num2;
}
};
この関数をsinonを使用して偽装した例は以下のとおり。
var assert = require('assert');
var calc = require('../calc');
var sinon = require('sinon');
describe('test3.', function () {
afterEach(() => {
// Restore the default sandbox here
sinon.restore();
});
it('stubの例.', function () {
assert.equal(calc.add(1,3), 4);
// スタブに置き換える
sinon.stub(calc, 'add').callsFake(function(x,y) {
console.log('stub function');
return x*2 + y * 2;
});
assert.equal(calc.add(1,3), 8);
});
});
時刻の偽装例
現在時刻を偽装する場合は[https://sinonjs.org/releases/v9.0.3/fake-timers/ sinon.useFakeTimers]を使用する。
現在時刻を1999/1/1 12:30:00(JST)にする場合
it('現在時刻の偽装の例', function () {
sinon.useFakeTimers({
now : new Date(1999, 0, 1, 12, 30, 00)
});
assert.equal((new Date()).getFullYear(), 1999);
console.log(new Date());
});
カバレッジの計測
Istanbulを使用することで、カバレッジを取得することができます。
Istanbul
https://istanbul.js.org/
インストール方法*
node.jsのプロジェクトにIstanbulをインストールするには下記のコマンドを実行する。
npm install --save-dev nyc
実行例
下記のコマンドでテストコードの実行と、カバレッジの計測が行える。
npx nyc mocha
または以下のコマンドでhtml形式のレポートが作成可能
npx nyc --reporter=html mocha