短い結論
- 実現は可能
- サーバーのログが抑制できないと、ちょっと使えない
- プロセスが残るがイマイチ
背景
APIサーバーの起動とテストの実行が別のコマンドだとテストの実行が面倒です。
例
例えばsyamoと言うアプリケーションは、次のコマンドでサーバーを起動します。
npm start
別のターミナルでテストを実行します。
npm test
1コマンドにして、1ターミナルで実行したい思いがあります。
作戦
node-foremanを使う作戦です。
node-foremanは、Procfileに記述した複数のプロセスを起動できます。
実行
準備
Procfileを用意します。
web: npm start
test: npm test
非常にシンプルです。
実行
syamoのテストコードでは、リクエスト送信先を3000番ポート固定しています。
3000番ポートを指定して、サーバーを起動します。
node_modules/foreman/nf.js start - p 3000
結果
サーバーのログとテスト結果が混ざって残念な感じです。
[OKAY] Loaded ENV .env File as KEY=VALUE Format
[OKAY] Trimming display Output to 60 Columns
10:00:10 test.1 | > syamo@0.0.2 test /Users/shigerunakajima/syamo
10:00:10 test.1 | > mocha --require espower-babel/guess -c
10:00:10 web.1 | > syamo@0.0.2 start /Users/shigerunakajima/syamo
10:00:10 web.1 | > babel-node app.js
10:00:12 test.1 |
10:00:12 test.1 | An authentication
10:00:12 web.1 | Tue, 16 Feb 2016 01:00:12 GMT request {
10:00:12 web.1 | "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
10:00:12 web.1 | "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
10:00:12 web.1 | "ref": "refs/heads/master",
10:00:12 web.1 | "user_id": 4,
10:00:12 web.1 | "user_name": "John Smith",
10:00:12 web.1 | "project_id": 15,
10:00:12 web.1 | "repository": {
10:00:12 web.1 | "name": "Diaspora",
10:00:12 web.1 | "url": "git@localhost:diaspora.git",
10:00:12 web.1 | "description": "",
10:00:12 web.1 | "homepage": "http://localhost/diaspora"
10:00:12 web.1 | },
10:00:12 web.1 | "commits": [
10:00:12 web.1 | {
10:00:12 web.1 | "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
10:00:12 web.1 | "message": "Update Catalan translation to e38cb41.",
10:00:12 web.1 | "timestamp": "2011-12-12T14:27:31+02:00",
10:00:12 web.1 | "url": "http://localhost/diaspora/commits/b6568db1bc1d…
10:00:12 web.1 | "author": {
10:00:12 web.1 | "name": "Jordi Mallach",
10:00:12 web.1 | "email": "jordi@softcatala.org"
10:00:12 web.1 | }
10:00:12 web.1 | },
10:00:12 web.1 | {
10:00:12 web.1 | "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
10:00:12 web.1 | "message": "fixed readme & 'hoge'",
10:00:12 web.1 | "timestamp": "2012-01-03T23:36:29+02:00",
10:00:12 web.1 | "url": "http://localhost/diaspora/commits/da1560886d4f…
10:00:12 web.1 | "author": {
10:00:12 web.1 | "name": "GitLab dev user",
10:00:12 web.1 | "email": "gitlabdev@dv6700.(none)"
10:00:12 web.1 | }
10:00:12 web.1 | }
10:00:12 web.1 | ],
10:00:12 web.1 | "total_commits_count": 4
10:00:12 web.1 | }
10:00:12 web.1 | Tue, 16 Feb 2016 01:00:12 GMT result ChatWork NG ,Error: For…
10:00:12 web.1 | Tue, 16 Feb 2016 01:00:12 GMT result OK, objectKind : push
10:00:12 test.1 | ✓ is errer by chatroom. (602ms)
10:00:12 test.1 | Issue
10:00:12 web.1 | Tue, 16 Feb 2016 01:00:12 GMT request {
10:00:12 web.1 | "object_kind": "issue",
10:00:12 web.1 | "user": {
10:00:12 web.1 | "name": "shigeru.nakajima",
10:00:12 web.1 | "username": "shigeru.nakajima",
10:00:12 web.1 | "avatar_url": "https://secure.gravatar.com/avatar/3a1f43…
10:00:12 web.1 | },
10:00:12 web.1 | "object_attributes": {
10:00:12 web.1 | "id": 2624,
10:00:12 web.1 | "title": "a",
10:00:12 web.1 | "assignee_id": null,
10:00:12 web.1 | "author_id": 6,
10:00:12 web.1 | "project_id": 65,
10:00:12 web.1 | "created_at": "2015-07-21 10:35:22 UTC",
10:00:12 web.1 | "updated_at": "Tue Feb 16 2016 10:00:11 GMT+0900 (JST)",
10:00:12 web.1 | "position": 0,
10:00:12 web.1 | "branch_name": null,
10:00:12 web.1 | "description": "a\r\nb",
10:00:12 web.1 | "milestone_id": null,
10:00:12 web.1 | "state": "opened",
10:00:12 web.1 | "iid": 4,
10:00:12 web.1 | "url": "https://developer.luxiar.jp/shigeru.nakajima/cha…
10:00:12 web.1 | "action": "open"
10:00:12 web.1 | }
10:00:12 web.1 | }
10:00:13 web.1 | Tue, 16 Feb 2016 01:00:13 GMT result OK, objectKind : issue
10:00:13 test.1 | ✓ is ok. (1189ms)
10:00:13 web.1 | Tue, 16 Feb 2016 01:00:13 GMT request {
10:00:13 web.1 | "object_kind": "issue",
10:00:13 web.1 | "user": {
10:00:13 web.1 | "name": "shigeru.nakajima",
10:00:13 web.1 | "username": "shigeru.nakajima",
10:00:13 web.1 | "avatar_url": "https://secure.gravatar.com/avatar/3a1f43…
10:00:13 web.1 | },
10:00:13 web.1 | "object_attributes": {
10:00:13 web.1 | "id": 2624,
10:00:13 web.1 | "title": "a",
10:00:13 web.1 | "assignee_id": null,
10:00:13 web.1 | "author_id": 6,
10:00:13 web.1 | "project_id": 65,
10:00:13 web.1 | "created_at": "2015-07-21 10:35:22 UTC",
10:00:13 web.1 | "updated_at": "Tue Feb 16 2016 10:00:11 GMT+0900 (JST)",
10:00:13 web.1 | "position": 0,
10:00:13 web.1 | "branch_name": null,
10:00:13 web.1 | "description": "a\r\nb",
10:00:13 web.1 | "milestone_id": null,
10:00:13 web.1 | "state": "opened",
10:00:13 web.1 | "iid": 4,
10:00:13 web.1 | "url": "https://developer.luxiar.jp/shigeru.nakajima/cha…
10:00:13 web.1 | "action": "open"
10:00:13 web.1 | }
10:00:13 web.1 | }
10:00:13 web.1 | Tue, 16 Feb 2016 01:00:13 GMT result Ignore, because same no…
✓ is ignored by duplicate.
10:00:13 web.1 | Tue, 16 Feb 2016 01:00:13 GMT request {
10:00:13 web.1 | "object_kind": "issue",
10:00:13 web.1 | "user": {
10:00:13 web.1 | "name": "shigeru.nakajima",
10:00:13 web.1 | "username": "shigeru.nakajima",
10:00:13 web.1 | "avatar_url": "https://secure.gravatar.com/avatar/3a1f43…
10:00:13 web.1 | },
10:00:13 web.1 | "object_attributes": {
10:00:13 web.1 | "id": 2624,
10:00:13 web.1 | "title": "a",
10:00:13 web.1 | "assignee_id": null,
10:00:13 web.1 | "author_id": 6,
10:00:13 web.1 | "project_id": 65,
10:00:13 web.1 | "created_at": "2015-07-21 10:35:22 UTC",
10:00:13 web.1 | "updated_at": "Tue Feb 16 2016 10:00:11 GMT+0900 (JST)",
10:00:13 web.1 | "position": 0,
10:00:13 web.1 | "branch_name": null,
10:00:13 web.1 | "description": "a\r\nb",
10:00:13 web.1 | "milestone_id": null,
10:00:13 web.1 | "state": "opened",
10:00:13 web.1 | "iid": 4,
10:00:13 web.1 | "url": "https://developer.luxiar.jp/shigeru.nakajima/cha…
10:00:13 web.1 | "action": "open"
10:00:13 web.1 | }
10:00:13 web.1 | }
10:00:14 web.1 | Tue, 16 Feb 2016 01:00:14 GMT result OK, objectKind : issue
✓ is not ignored that is sent to other chatroom. (647ms…
10:00:14 web.1 | Tue, 16 Feb 2016 01:00:14 GMT request {
10:00:14 web.1 | "object_kind": "issue",
10:00:14 web.1 | "user": {
10:00:14 web.1 | "name": "shigeru.nakajima",
10:00:14 web.1 | "username": "shigeru.nakajima",
10:00:14 web.1 | "avatar_url": "https://secure.gravatar.com/avatar/3a1f43…
10:00:14 web.1 | },
10:00:14 web.1 | "object_attributes": {
10:00:14 web.1 | "action": "update"
10:00:14 web.1 | }
10:00:14 web.1 | }
10:00:14 web.1 | Tue, 16 Feb 2016 01:00:14 GMT result Ignore, Update issue is…
10:00:14 web.1 | Tue, 16 Feb 2016 01:00:14 GMT request {
10:00:14 web.1 | "object_kind": "issue",
10:00:14 web.1 | "user": {
10:00:14 web.1 | "name": "shigeru.nakajima",
10:00:14 web.1 | "username": "shigeru.nakajima",
10:00:14 web.1 | "avatar_url": "https://secure.gravatar.com/avatar/3a1f43…
10:00:14 web.1 | },
10:00:14 web.1 | "object_attributes": {
10:00:14 web.1 | "action": "close"
10:00:14 web.1 | }
10:00:14 web.1 | }
10:00:14 web.1 | Tue, 16 Feb 2016 01:00:14 GMT result Ignore, A closisg issue…
✓ is ignored by update action.
✓ is ignored by close action.
10:00:14 test.1 | MR
10:00:14 web.1 | Tue, 16 Feb 2016 01:00:14 GMT request {
10:00:14 web.1 | "object_kind": "merge_request",
10:00:14 web.1 | "object_attributes": {
10:00:14 web.1 | "id": 445,
10:00:14 web.1 | "target_branch": "master",
10:00:14 web.1 | "source_branch": "ms-viewport",
10:00:14 web.1 | "source_project_id": 14,
10:00:14 web.1 | "author_id": 2,
10:00:14 web.1 | "assignee_id": 2,
10:00:14 web.1 | "title": "MS-Viewport",
10:00:14 web.1 | "created_at": "2013-12-03T17:23:34Z",
10:00:14 web.1 | "updated_at": "2013-12-03T17:23:34Z",
10:00:14 web.1 | "st_commits": null,
10:00:14 web.1 | "st_diffs": null,
10:00:14 web.1 | "milestone_id": null,
10:00:14 web.1 | "state": "opened",
10:00:14 web.1 | "merge_status": "can_be_merged",
10:00:14 web.1 | "target_project_id": 62,
10:00:14 web.1 | "iid": 18,
10:00:14 web.1 | "description": " abc & 'hoge' "
10:00:14 web.1 | }
10:00:14 web.1 | }
10:00:15 web.1 | Tue, 16 Feb 2016 01:00:15 GMT result OK, objectKind : merge_…
10:00:15 test.1 | ✓ is ok. (651ms)
10:00:15 web.1 | Tue, 16 Feb 2016 01:00:15 GMT request {
10:00:15 web.1 | "object_kind": "merge_request",
10:00:15 web.1 | "object_attributes": {
10:00:15 web.1 | "id": 445,
10:00:15 web.1 | "target_branch": "master",
10:00:15 web.1 | "source_branch": "ms-viewport",
10:00:15 web.1 | "source_project_id": 14,
10:00:15 web.1 | "author_id": 2,
10:00:15 web.1 | "assignee_id": 2,
10:00:15 web.1 | "title": "MS-Viewport",
10:00:15 web.1 | "created_at": "2013-12-03T17:23:34Z",
10:00:15 web.1 | "updated_at": "2013-12-03T17:23:34Z",
10:00:15 web.1 | "st_commits": null,
10:00:15 web.1 | "st_diffs": null,
10:00:15 web.1 | "milestone_id": null,
10:00:15 web.1 | "state": "opened",
10:00:15 web.1 | "merge_status": "unchecked",
10:00:15 web.1 | "target_project_id": 62,
10:00:15 web.1 | "iid": 18,
10:00:15 web.1 | "description": " abc & 'hoge' "
10:00:15 web.1 | }
10:00:15 web.1 | }
10:00:15 web.1 | Tue, 16 Feb 2016 01:00:15 GMT result OK, objectKind : merge_…
10:00:15 test.1 | ✓ is through that is unchecked. (685ms)
10:00:15 web.1 | Tue, 16 Feb 2016 01:00:15 GMT request {
10:00:15 web.1 | "object_kind": "merge_request",
10:00:15 web.1 | "object_attributes": {
10:00:15 web.1 | "id": 445,
10:00:15 web.1 | "target_branch": "master",
10:00:15 web.1 | "source_branch": "ms-viewport",
10:00:15 web.1 | "source_project_id": 14,
10:00:15 web.1 | "author_id": 2,
10:00:15 web.1 | "assignee_id": 2,
10:00:15 web.1 | "title": "MS-Viewport",
10:00:15 web.1 | "created_at": "2013-12-03T17:23:34Z",
10:00:15 web.1 | "updated_at": "2013-12-03T17:23:34Z",
10:00:15 web.1 | "st_commits": null,
10:00:15 web.1 | "st_diffs": null,
10:00:15 web.1 | "milestone_id": null,
10:00:15 web.1 | "state": "merged",
10:00:15 web.1 | "merge_status": "can_be_merged",
10:00:15 web.1 | "target_project_id": 62,
10:00:15 web.1 | "iid": 18,
10:00:15 web.1 | "description": " abc & 'hoge' "
10:00:15 web.1 | }
10:00:15 web.1 | }
10:00:15 web.1 | Tue, 16 Feb 2016 01:00:15 GMT result Ignore, MRs are notifie…
✓ is ignored thats status is merged.
10:00:15 web.1 | Tue, 16 Feb 2016 01:00:15 GMT request {
10:00:15 web.1 | "object_kind": "merge_request",
10:00:15 web.1 | "object_attributes": {
10:00:15 web.1 | "id": 445,
10:00:15 web.1 | "target_branch": "master",
10:00:15 web.1 | "source_branch": "ms-viewport",
10:00:15 web.1 | "source_project_id": 14,
10:00:15 web.1 | "author_id": 2,
10:00:15 web.1 | "assignee_id": 2,
10:00:15 web.1 | "title": "MS-Viewport",
10:00:15 web.1 | "created_at": "2013-12-03T17:23:34Z",
10:00:15 web.1 | "updated_at": "2013-12-03T17:23:34Z",
10:00:15 web.1 | "st_commits": null,
10:00:15 web.1 | "st_diffs": null,
10:00:15 web.1 | "milestone_id": null,
10:00:15 web.1 | "state": "opened",
10:00:15 web.1 | "merge_status": "can_be_merged",
10:00:15 web.1 | "target_project_id": 14,
10:00:15 web.1 | "iid": 18,
10:00:15 web.1 | "description": " abc & 'hoge' "
10:00:15 web.1 | }
10:00:15 web.1 | }
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT result Gitlab404Error: 404 Not…
10:00:16 web.1 | at Gitlab.RESTFulClient.handleResult (/Users/shigerunaka…
10:00:16 web.1 | at /Users/shigerunakajima/syamo/node_modules/node-gitlab…
10:00:16 web.1 | at done (/Users/shigerunakajima/syamo/node_modules/node-…
10:00:16 web.1 | at /Users/shigerunakajima/syamo/node_modules/node-gitlab…
10:00:16 web.1 | at decodeContent (/Users/shigerunakajima/syamo/node_modu…
10:00:16 web.1 | at IncomingMessage.<anonymous> (/Users/shigerunakajima/s…
10:00:16 web.1 | at emitNone (events.js:85:20)
10:00:16 web.1 | at IncomingMessage.emit (events.js:179:7)
10:00:16 web.1 | at endReadableNT (_stream_readable.js:906:12)
10:00:16 web.1 | at nextTickCallbackWith2Args (node.js:475:9)
10:00:16 web.1 | at process._tickDomainCallback (node.js:430:17)
10:00:16 test.1 | ✓ is error unless any information from Gitlab API. (290m…
10:00:16 test.1 | Push
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT request {
10:00:16 web.1 | "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
10:00:16 web.1 | "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
10:00:16 web.1 | "ref": "refs/heads/master",
10:00:16 web.1 | "user_id": 4,
10:00:16 web.1 | "user_name": "John Smith",
10:00:16 web.1 | "project_id": 15,
10:00:16 web.1 | "repository": {
10:00:16 web.1 | "name": "Diaspora",
10:00:16 web.1 | "url": "git@localhost:diaspora.git",
10:00:16 web.1 | "description": "",
10:00:16 web.1 | "homepage": "http://localhost/diaspora"
10:00:16 web.1 | },
10:00:16 web.1 | "commits": [
10:00:16 web.1 | {
10:00:16 web.1 | "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
10:00:16 web.1 | "message": "Update Catalan translation to e38cb41.",
10:00:16 web.1 | "timestamp": "2011-12-12T14:27:31+02:00",
10:00:16 web.1 | "url": "http://localhost/diaspora/commits/b6568db1bc1d…
10:00:16 web.1 | "author": {
10:00:16 web.1 | "name": "Jordi Mallach",
10:00:16 web.1 | "email": "jordi@softcatala.org"
10:00:16 web.1 | }
10:00:16 web.1 | },
10:00:16 web.1 | {
10:00:16 web.1 | "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
10:00:16 web.1 | "message": "fixed readme & 'hoge'",
10:00:16 web.1 | "timestamp": "2012-01-03T23:36:29+02:00",
10:00:16 web.1 | "url": "http://localhost/diaspora/commits/da1560886d4f…
10:00:16 web.1 | "author": {
10:00:16 web.1 | "name": "GitLab dev user",
10:00:16 web.1 | "email": "gitlabdev@dv6700.(none)"
10:00:16 web.1 | }
10:00:16 web.1 | }
10:00:16 web.1 | ],
10:00:16 web.1 | "total_commits_count": 4
10:00:16 web.1 | }
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT result OK, objectKind : merge_…
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT result OK, objectKind : push
10:00:16 test.1 | ✓ is ok. (524ms)
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT request {
10:00:16 web.1 | "before": "0000000000000000000000000000000000000000",
10:00:16 web.1 | "after": "9b298340f13114aaf2b1990c95f4c6370ac8e44d",
10:00:16 web.1 | "ref": "refs/heads/add_issue_info",
10:00:16 web.1 | "user_id": 6,
10:00:16 web.1 | "user_name": "shigeru.nakajima",
10:00:16 web.1 | "project_id": 65,
10:00:16 web.1 | "repository": {
10:00:16 web.1 | "name": "chabot",
10:00:16 web.1 | "url": "git@developer.luxiar.jp:shigeru.nakajima/chabot.…
10:00:16 web.1 | "description": "gitlabにpushされたらchatworkに書き込むアプリを作ります。\r\…
10:00:16 web.1 | "homepage": "https://developer.luxiar.jp/shigeru.nakajim…
10:00:16 web.1 | },
10:00:16 web.1 | "commits": [],
10:00:16 web.1 | "total_commits_count": 0
10:00:16 web.1 | }
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT result Ignore, No commit push …
10:00:16 test.1 | ✓ is ignored by total_commits_count 0
10:00:16 test.1 | A template
10:00:16 web.1 | Tue, 16 Feb 2016 01:00:16 GMT request {
10:00:16 web.1 | "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
10:00:16 web.1 | "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
10:00:16 web.1 | "ref": "refs/heads/master",
10:00:16 web.1 | "user_id": 4,
10:00:16 web.1 | "user_name": "John Smith",
10:00:16 web.1 | "project_id": 15,
10:00:16 web.1 | "repository": {
10:00:16 web.1 | "name": "Diaspora",
10:00:16 web.1 | "url": "git@localhost:diaspora.git",
10:00:16 web.1 | "description": "",
10:00:16 web.1 | "homepage": "http://localhost/diaspora"
10:00:16 web.1 | },
10:00:16 web.1 | "commits": [
10:00:16 web.1 | {
10:00:16 web.1 | "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
10:00:16 web.1 | "message": "Update Catalan translation to e38cb41.",
10:00:16 web.1 | "timestamp": "2011-12-12T14:27:31+02:00",
10:00:16 web.1 | "url": "http://localhost/diaspora/commits/b6568db1bc1d…
10:00:16 web.1 | "author": {
10:00:16 web.1 | "name": "Jordi Mallach",
10:00:16 web.1 | "email": "jordi@softcatala.org"
10:00:16 web.1 | }
10:00:16 web.1 | },
10:00:16 web.1 | {
10:00:16 web.1 | "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
10:00:16 web.1 | "message": "fixed readme & 'hoge'",
10:00:16 web.1 | "timestamp": "2012-01-03T23:36:29+02:00",
10:00:16 web.1 | "url": "http://localhost/diaspora/commits/da1560886d4f…
10:00:16 web.1 | "author": {
10:00:16 web.1 | "name": "GitLab dev user",
10:00:16 web.1 | "email": "gitlabdev@dv6700.(none)"
10:00:16 web.1 | }
10:00:16 web.1 | }
10:00:16 web.1 | ],
10:00:16 web.1 | "total_commits_count": 4
10:00:16 web.1 | }
10:00:17 web.1 | Tue, 16 Feb 2016 01:00:17 GMT result OK, objectKind : push
✓ is used for the chatroom. (471ms)
10:00:17 test.1 | 13 passing (5s)
[DONE] Killing all processes with signal null
10:00:17 test.1 Exited Successfully
syamoはdebugを使っています。
環境変数でサーバーのログ出力を制御できます。
サーバーのログを抑制すると
[OKAY] Loaded ENV .env File as KEY=VALUE Format
[OKAY] Trimming display Output to 155 Columns
10:18:08 web.1 | > syamo@0.0.2 start /Users/shigerunakajima/syamo
10:18:08 web.1 | > babel-node app.js
10:18:08 test.1 | > syamo@0.0.2 test /Users/shigerunakajima/syamo
10:18:08 test.1 | > mocha --require espower-babel/guess -c
10:18:09 test.1 |
10:18:09 test.1 | An authentication
10:18:10 test.1 | ✓ is errer by chatroom. (338ms)
10:18:10 test.1 | Issue
10:18:10 test.1 | ✓ is ok. (554ms)
10:18:10 test.1 | ✓ is ignored by duplicate.
10:18:11 test.1 | ✓ is not ignored that is sent to other chatroom. (410ms)
10:18:11 test.1 | ✓ is ignored by update action.
10:18:11 test.1 | ✓ is ignored by close action.
10:18:11 test.1 | MR
10:18:11 test.1 | ✓ is ok. (498ms)
10:18:12 test.1 | ✓ is through that is unchecked. (358ms)
10:18:12 test.1 | ✓ is ignored thats status is merged.
10:18:12 test.1 | ✓ is error unless any information from Gitlab API. (73ms)
10:18:12 test.1 | Push
10:18:12 test.1 | ✓ is ok. (291ms)
10:18:12 test.1 | ✓ is ignored by total_commits_count 0
10:18:12 test.1 | A template
10:18:12 test.1 | ✓ is used for the chatroom. (270ms)
10:18:12 test.1 | 13 passing (3s)
[DONE] Killing all processes with signal null
10:18:12 test.1 Exited Successfully
良い感じです。
テスト完了時にプロセスが残るのがイマイチです。
補足
テストコードの出力に色をつけるには、mochaに-cオプションをつけます。