10
12

More than 3 years have passed since last update.

jestでテスト

Posted at

jestとは

Node.jsをテストするためのライブラリ
<公式ドキュメント> https://jestjs.io/docs/en/getting-started

※Node.jsのテストアプリとしては、他にもmocha(https://mochajs.org/ )が有名。

テストコードが必要な理由

・開発の時間短縮。コードを変更した後でも、テストコマンドを打つだけで自動的にテストしてくれる
・より信頼性の高い(バグの少ない)コーディングができる
・リファクタリングや機能の追加・削除が簡単にできる

アプリをテストするための準備

●jestのインストール

npm i jest

※npmでのjestのページ ( https://www.npmjs.com/package/jest )

●テスト用の環境を設定する
※本番用の環境がすでに「dev.env」にまとめられている場合

・ファイル構成

└── App
    ├── config           //環境を保存するフォルダ
    |      ├── dev.env  //本番用環境のための環境変数を格納しているファイル  
    |      └── test.env //テスト環境のための環境変数を格納しているファイル  

・test.envの設定

PORT=3010
MONGODB_URL=mongodb://127.0.0.1:27017/task-manager-api-test

※テスト用のデータベースと接続させるようにMongoDBの設定を記述する

●package.jsonの設定

"scripts": {
    "start": "node src/index.js",
    "dev": "env-cmd -f ./config/dev.env nodemon src/index.js",
    "test": "env-cmd -f ./config/test.env jest --watch"   //test時に動かす環境を記述。
  },
  "jest": {
    "testEnvironment": "node"  //jestで nodeのコードをテストすると記述
  },

※「scripts」に「test」を記述することで、ターミナルに「npm test」でテスト(ファイル名にtestと含まれているもの)を動かすようになる。

※「test」に「--watch」で、「npm test」後に、ターミナルでjestが開きっぱなしになる

expressをテストするためのnpmパッケージ

「super test」 https://www.npmjs.com/package/supertest

・テストコード

const app =require('./app')   //portをlistenする以外のアプリの処理を読み込み

request(app)
       .expect(...)   //アプリが立ち上がっていなくてもexptectでテストできる

→super testパッケージを用いると、アプリが立ち上がっていなくてもテストを行うことができる

通常のテスト

・testのためのファイル構成

└── App
    ├── test  //テストを保存するフォルダ
    |      └── fixture //テスト環境のための環境変数を格納しているファイル 
   |      ├── db.js  //テスト用データをデータベースに格納するためのファイル
    |          └── async.test.js //テストコードを記述するファイル

●通常のテスト
・first.test.js

test('テストケース名',() => { テストしたい関数 }) //正常なら処理完了するテスト

test('テストケース名', ()=> { 
  throw new Error ('エラー')   //正常ならエラーを返したいテスト項目
})

jestでは通常、上記の書き方でテストコードを書く。
「npm test」でテスト開始。ファイル名に「test」が含まれているテストファイルが実行される。

非同期処理のテスト

・async.test.js

test('Async test demo', (done) => {  //引数にdoneを設定
  setTimeout(() => {
    expect(1).toBe(2)
    done() //非同期処理(ここではsetTimeout)が終わるタイミングでdoneを呼び出す
  }, 2000)  
})


今回のテストでは、「setTimeout」をすると「1」が「2」になるかテストしている

2秒後にエラーが返る。

※「toBe」について: jest公式ドキュメント

非同期処理のテストは、非同期処理が終わった時点で引数doneを呼び出すように設定しないと、ちゃんとテストされない(非同期処理を待たずにテストをパスしてしまう)

●Promiseを使うコードのテスト

const add = (a, b) => {
  return new Promise ((resolve, reject) => {
    setTimeout(() => {
        if(a < 0 || b < 0){
          return reject('Number must be non-negative')
        }
      resolve(a + b)
    }, 2000)
  })
}

上記のコードをテストする場合
・promise.test.js


test('addは機能しているか', (done)=> {
  add(2, 3).then((sum) => { //thenを使ってチェインさせる
    expect(sum).toBe(5)
    done()
  })
})

async/awaitを使ってテストする場合

test('addは機能しているか、async/awaitで', async() => {
  const sum = await add(11, 22)
  expect(sum).toBe(33)
})

テストの前に行う処理・テストの後に行う処理を記述する

「Setup and Teardown」を用いる。

beforeEach(() => {
initializeCityDatabase();
});

afterEach(() => {
clearCityDatabase();
});

・beforeEach:テストの前に行う処理を記述する

・afterEach:テストの後に行う処理を記述する

例)テストの前に、テスト用データベース内の全ての項目を消す
・users.test.js

const User = require('../src/models/user')

const userOne = {  //テストデータ用のデータベースの中身
  neme:'aaa',
  password: '12345'
}

beforeEach(async() => {   //beforeEachは非同期処理
  await User.deleteMany()  //データベースの中身を削除
  await new User(userOne).save()  //空になったデータをデータベースに保存
})

ライブラリのmockを作成する

・jest公式ドキュメント
Mocking Node Modulesを参照

・mockライブラリを作成する場合のファイル構成

└── App
    ├── test  //テストを保存するフォルダ
    |      └── fixture //テスト環境のための環境変数を格納しているファイル 
   |    |  ├── db.js  //テスト用データをデータベースに格納するためのファイル
    |      |   └── test.js//テストコードを記述するファイル
       └── __mocks__  //モックファイルを記述
               └── sendgrid //モックを作成するAPI名
             └── test.js

・test.js


module.exports = {
  send(){

  }
}


今回はsendgridという、メール送信のためのライブラリ(https://sendgrid.com/docs/api-reference/ )のモックを作成している。

コード中に「sgMail.send()」でメール送信をする箇所があった場合、テスト環境では作成したモックのsendgridが実行されるため、「send()」の処理は上記のファイルに書かれた通りのもの(今回の場合は何もしないこと)になる。

10
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
12