# 2020年10月10日モブプロ#8 [MDの書き方](https://qiita.com/tbpgr/items/989c6badefff69377da7) モブプロのコンテンツは🤟がついています。 # 本日の目標 ひたすらテストコードを書いていく! # Jestの参考サイト - [Facebook製のJavaScriptテストツール「Jest」の逆引き使用例 - Qiita](https://qiita.com/chimame/items/e97883fd46b67529d59f) - [Getting Started - Jest](https://jestjs.io/docs/ja/getting-started) # テストコードを書いていこう🤟 - エンドポイントのテストはJestはできないので以下を使用する - https://www.npmjs.com/package/supertest ## テストの分類分け describeを使って、ファイル単位、メソッド単位にテストを分けて書いていく ```javascript= describe('routers/tasks.js', () => { describe('get method', () => { }) }) ``` ## GETメソッドのテストコードを書く ### Task全取得 ```javascript= describe('get method', () => { it('response', async () => { const response = await request(app).get('/tasks') expect(response.statusCode).toBe(200) }) }) ``` いい感じ。 ```shell= > jest Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.415 s ``` でも、なにかエラーが表示される。 ```shell= ● Cannot log after tests are done. Did you forget to wait for something async in your test? Attempted to log "Executing (default): ALTER TABLE `Tasks` CHANGE `title` `title` VARCHAR(255) NOT NULL;". at CustomConsole.log (node_modules/@jest/console/build/CustomConsole.js:185:10) at Sequelize.log (node_modules/sequelize/lib/sequelize.js:1171:15) at Query._logQuery (node_modules/sequelize/lib/dialects/abstract/query.js:352:22) at Query.run (node_modules/sequelize/lib/dialects/mysql/query.js:36:27) at node_modules/sequelize/lib/sequelize.js:619:28 at Function.sync (node_modules/sequelize/lib/model.js:1349:11) ``` APIサーバ起動時にコンソールログが出力されるが、そのログに対してテストしなくて大丈夫かどうかを尋ねるメッセージの模様。 本来は、ちゃんとテストするか、出力されないようにするなどの対応をするべきだが、一旦以下のオプションで無視する。 ```shell= jest --silent ``` ### レスポンスが配列かどうかのテスト ```javascript= expect(Array.isArray(response.body)).toBe(true) // => passed! ``` 上記を先程の`expect()`の下に追加。 `tobe(true)`は`toBeTruthy()`に置き換えることができる。 ```javascript= expect(Array.isArray(response.body)).toBeTruthy() // => passed! ``` ### ID指定での取得テスト ```javascript= it('response with id', async () =>{ const response = await request(app).get('/tasks/13') expect(response.statusCode).toBe(200) // IDはNumber型? expect(Number.isInteger(response.body.id)).toBeTruthy() // titleは合ってる? expect(response.body.title).toBe('test1') // doneはfalseかな? expect(response.body.done).toBeFalsy() }) ``` ### 存在しないIDのエラーテスト ```javascript= // id = 12は存在しないはず... it('response with unknown id', async () =>{ const response = await request(app).get('/tasks/12') expect(response.statusCode).toBe(404) }) ``` ## テストデータの追加 上記の書き方と汎用性がないのでテストデータを追加する。 ```javascript= const Task = require('../src/models/tasks') // テストデータを新規追加 const task = await Task.create({title:'test'}) const id = task.id ``` ## POSTメソッドのテストコードを書いていく ```javascript= describe('post method', () => { it('response with data', async () => { const data = {title: "test"} const response = await request(app).post('/tasks').send(data) expect(response.statusCode).toBe(201) }) }) ``` ### 失敗するようにしてみる ```javascript= it('response without data', async () => { const response = await request(app).post('/tasks') expect(response.statusCode).toBe(400) }) ``` エラーで落ちちゃう。 エラー処理を書いてなかった! ```javascript= // routers/tasks.js router.post('/tasks', async (req, res) => { const title = req.body.title try { const task = await Task.create({ title }) res.status(201).send(task) } catch(e) { res.status(400).send() } }) ``` エラー処理を追加してあげる。 ## DELETEメソッドのテストコードを書いていく ```javascript= describe('delete method', () => { it('response with id', async () => { const task = await Task.create({title:'test'}) const id = task.id const response = await request(app).delete(`/tasks/${id}`) // 削除完了している? expect(response.statusCode).toBe(200) // 中身消えてる? expect(response.body.id).toBeUndefined() }) // 存在しないIDで404が返ってくるか it('response with unknown id', async () => { const id = 0 const response = await request(app).delete(`/tasks/${id}`) expect(response.statusCode).toBe(404) }) }) ``` ## PATCHメソッドのテストコードを書いていく ```javascript= describe('patch method', () => { it('response with id and data', async () => { const task = await Task.create({title:'test'}) const id = task.id const data = { title:"test2",done:true} const response = await request(app).patch(`/tasks/${id}`).send(data) // 成功した? expect(response.statusCode).toBe(200) expect(response.body.id).toBe(id) expect(response.body.done).toBeTruthy() expect(response.body.title).toBe(data.title) }) }) ``` ### IDがなかった場合の処理 ```javascript= it('respose with unknown id', async ()=> { const id = 0 const data = { title:"test2",done:true} const response = await request(app).patch(`/tasks/${id}`).send(data) expect(response.statusCode).toBe(404) }) ``` ## テストコード記述時の注意💥 ### **テストコードは共通化しない!** どこで失敗したかわからなくなるため共通化はご法度。 コピペで記述しましょう。