自己紹介
- 筑井 友啓 Tsukui Tomohiro
- ecbo株式会社(2018/4 ~ )
- 「ecbo cloak」というアプリをリリースしました
- twitter @two2q
Goal
明日にでもjest使ってくれたら嬉しいです
#jestいいよ
かなりDXが高く、すぐにTDD出来る
jest とは
react-nativeならjestすぐに使えるよ
react-nativeのバージョンが0.38以上であれば、react-native init
時にjestがセットアップされています。
"scripts": {
"test": "jest"
},
"jest": {
"preset": "react-native"
}
jestすぐに使えるよ
$ yarn test
参考 https://jestjs.io/docs/ja/tutorial-react-native
no configとはいえ
なんだかんだ設定は必要な時もある
eslint 使っている場合
eslintエラーが出ているのでeslint-plugin-jestを追加してください。
$ yarn add --dev eslint eslint-plugin-jest
{
"plugins": ["jest"]
}
TypeScript
ts-jestのインストールがてっとり早い
jestの基本
methodは標準的なものを取り揃えています
describe(name, fn) と test(name, fn, timeout)
describe
: いくつかのテストをまとめるブロックを作ります。
test
: 実際にテストを書くブロックです。期待値との比較などを行います。it(name, fn, timeout)
も同じです。
const myBeverage = {
delicious: true,
sour: false,
};
describe('my beverage', () => {
test('is delicious', () => {
expect(myBeverage.delicious).toBeTruthy();
});
test('is not sour', () => {
expect(myBeverage.sour).toBeFalsy();
});
});
非同期のテストについての注意
非同期関数をテストする際には、 return
をしてあげないと絶対に success
になってしまう。
// targetFn.js
const targetFn = async () => { } // do something
// targetFn.spec.js
test('test async', () => {
return targetFn().then((result) => {
expect(result).toBe('expected')
})
}
他にもasync () => { await ... } や (done) => { ... done() }
でもテスト可能です。
参考: https://jestjs.io/docs/en/tutorial-async
おすすめなMethod
describe.each(table)(name, fn, timeout)
同じtestを複数のデータセットで回したい時に利用します。
describe.each`
a | b | expected
${1} | ${1} | ${2}
${1} | ${2} | ${3}
${2} | ${1} | ${3}
`('$a + $b', ({a, b, expected}) => {
test(`returns ${expected}`, () => {
expect(a + b).toBe(expected);
});
test(`returned value not be greater than ${expected}`, () => {
expect(a + b).not.toBeGreaterThan(expected);
});
test(`returned value not be less than ${expected}`, () => {
expect(a + b).not.toBeLessThan(expected);
});
});
最近書いたコード
const baseDateString = '2019-02-26T18:30:00.000';
describe.each`
language | expected
${'en'} | ${'02/26 6:30 PM'}
${'ja'} | ${'02/26 18:30'}
${'zh-Hant'} | ${'02/26 18:30'}
`('localizedDateTime with $language', ({ language, expected }) => {
it(`should return ${expected}`, () => {
i18n.changeMomentLocale(language);
const result = dateTimeExpression.localizedDateTime(moment(baseDateString));
expect(result).toEqual(expected);
});
});
見通しよく、データセットの追加も容易に!
参照: https://jestjs.io/docs/en/api#describeeachtable-name-fn-timeout
おすすめな実行オプション その1
--watch
#--watch
変更されたファイルを検知して、関連するテストを実行してくれます。
個人的にメインな使い方です。高いDXでTDDを実現してくれます。
一度実行すればjestがファイルを監視してくれる
おすすめな使い方
- 先にテスト対象のファイルの
[spec|test].js
を用意し、ある程度describeも書いておきます。 - エディタのterminalで
$ jest --watch
します。 - 全てのテストがerrorになります。
- テストがパスするまで実装してください。
主な利用シーン
- ducks層の実装
- form validationの実装
- utils系の実装
- Component内の複雑なfunctionの実装
=> ピュアなjsでいける部分については基本的にjestで先に仕様をまとめてから実装します。
おすすめな実行オプション その2
--coverage
jest --coverage
カバレッジを計測してくれます。ソース全体のカバレッジではなく、あくまでもjestで実行されたファイルのみを計測します。
カバレッジが重要ではないのですが、no configで実行出来るという点がかなり素敵かな、と思っています。
実行してみた
おすすめな使い方
悦に浸ったり、githubにバッジをつけてみてください。jest-coverage-badges
API通信部分のテスト
nockでサーバーのモックを作る
$ yarn add nock
指定したリクエストを上書きしてモックデータを返却してくれます。一度レスポンスの型を決めてしまえばAPI通信部分のテストをサーバーなしで実行出来るようになります。
具体的には
import nock from 'nock';
nock('http://www.example.com')
.get('/hogehoge')
.reply(200, { foo: 'bar' })
こうする事で、http://www.example.com
へのrequestが全てinterceptされるようになり、/hogehoge
へのget
リクエストにはstatus200と共に {foo: 'bar'}
が返却されるということを意味します。
なお、jestにも標準でmockが用意されているのですが、モジュールのモックになってしまうのでダミーデータを返却するクライアントのモックを用意する必要があります。その点nockは一手間減るという印象があります。
snapshot テストについて
初回snapshotテスト実行時に.snap
形式でスナップショットを生成し、以降のテストではそのスナップショットとコンポーネントを比較して変更があればエラーとして検知するものです。
import renderer from "react-test-renderer";
import App from "../App";
// 省略
it("renders the loading screen", async () => {
const tree = renderer.create(<App />).toJSON();
expect(tree).toMatchSnapshot();
});
コンポーネントの品質についてはstorybookの方が今の所効果あります
- そもそも変更が多いのでsnapshotの恩恵が少ない(影響範囲がわかるのはよかった)
- 実際に操作をさせないとバグかどうかの判断がつきにくい
-
@storybook/addon-knobs
を整備してあげてデザイナーさんに触ってもらった方が結局早い
TODO E2Eテスト
こんな感じで、色々jestのキャッチアップをしながらコードを書いています。
なぜ書くのか
ひどいデグレは防げるかもしれない
- 障害対応で疲弊する事が減るかもしれない
- 修正に対する恐怖が減る、下手なオンボーディングよりも安心する
過去の自分が書いた負債で後任が爆死しない
- specさえあれば負債の負債度が減る
- 恨みを買わなくて済むので平和になる
- ここクソだけどspecあるからひとまず安心する、とか言われる
わざわざ端末触らなくても実装出来る
- 端末の起動よりもjestの方がはるかに早いので少し早く帰れる
- 端末をフリフリしてどっかに飛ばすリスクが減る
思い切ったリファクタも結構出来る
- もちろん程度にもよるが、ないよりははるかにマシ
コードレビューのフィードバック対応も早い
- 指摘内容はそれに対応するspecを添えればレビュアーにとってもわかりやすい
- フィードバック修正後のテスト工数の削減
基本的にいい事しかないし、健全な働きが出来る
テストは福利厚生と言ってもいいのではないだろうか?
ひとまず福利厚生に書いてみた
Wantedlyより抜粋