FullStackOpen Part4-a Structure of backend application, introduction to testing

Project Structure

Node.jsのベストプラクティスとしては以下のようなプロジェクト構造になる

├── index.js
├── app.js
├── build
│   └── ...
├── controllers
│   └── notes.js
├── models
│   └── note.js
├── package-lock.json
├── package.json
├── utils
│   ├── config.js
│   ├── logger.js
│   └── middleware.js  

ロギング機能をあちこちに書くのはいい習慣ではないため、専用のモジュール(utils/logger.js)に割り当てる
infoとerrrorに分け、重大度別にする

const info = (...params) => {
  console.log(...params)
}

const error = (...params) => {
  console.error(...params)
}

module.exports = {
  info, error
}

詳細は元のコースを参照

大きな変更点

  • loggerやconfigやエラーハンドラーなどのミドルウェアをutilフォルダに別モジュールとして分離

  • ルートハンドラー(notes.js)はcontrollerフォルダとして分けている
    ルートハンドラーをモジュールとして取り扱うことで、テストしやすいなど様々なメリットがある
    const notesRouter = require('express').Router()
    //…
    module.exports = notesRouter

  • note.js(s無し)はモデル提供オンリーとして変更

  • app.jsとindex.jsを分離
    app.js中でmongooseの接続を担当
    その他ミドルウェアの使用、ルータの使用、エラーハンドラーの使用を実装

  • index.jsはapp.jsをインポートしてサーバーをリッスンさせるだけ

Note on exports

exportsにエクスポートしたものには2通りの使い方がある

  1. ドットでアクセス
    const logger = require('./utils/logger')
    logger.info('message')
    logger.error('error message')

  2. Destructureして各関数に直接アクセス
    const { info, error } = require('./utils/logger')
    info('message')
    error('error message')

Testing Node applications

アプリケーション開発の重要な要素であるテストについての話
jest
を使う
npm install --save-dev jest

package.jsonに追加

{
  //...
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "build:ui": "rm -rf build && cd ../frontend/ && npm run build && cp -r build ../backend",
    "deploy": "fly deploy",
    "deploy:full": "npm run build:ui && npm run deploy",
    "logs:prod": "fly logs",
    "lint": "eslint .",
    "test": "jest --verbose"
  },
  //...
}
{
 //...
 "jest": {
   "testEnvironment": "node"
 }
}

テスト作成は以下のような構造で
テスト用ファイルは<function>.test.jsという拡張子で作成
test('test name', () => {expect(result).toBe('正しい値')}

const reverse = require('../utils/for_testing').reverse

test('reverse of a', () => {
  const result = reverse('a')

  expect(result).toBe('a')
})

test('reverse of react', () => {
  const result = reverse('react')

  expect(result).toBe('tcaer')
})

test('reverse of releveler', () => {
  const result = reverse('releveler')

  expect(result).toBe('releveler')
})

describe関数を使うとすっきりした形で書くことができる

const average = require('../utils/for_testing').average

describe('average', () => {
  test('of one value is the value itself', () => {
    expect(average([1])).toBe(1)
  })

  test('of many is calculated right', () => {
    expect(average([1, 2, 3, 4, 5, 6])).toBe(3.5)
  })

  test('of empty array is zero', () => {
    expect(average([])).toBe(0)
  })
})


この記事が気に入ったらサポートをしてみませんか?