そろそろもっとテストコード書いたほうが良いなーと思ったので、 モチベーションを上げるためにカバレッジを通知するようにしました。
↓こんな感じ
通知にはdanger-jsを使用しました。
カバレッジの通知は、こちらのプラグインでサクッと実装できます
danger用に以下のファイルを作成
■ dangerfile.ts
import { schedule } from 'danger'; import { istanbulCoverage } from 'danger-plugin-istanbul-coverage'; const successCoveRage = 80; schedule( istanbulCoverage({ reportFileSet: 'createdOrModified', customSuccessMessage: `テストカバレッジ${successCoveRage}%以上を達成しました`, customFailureMessage: `テストカバレッジが${successCoveRage}%以下です`, coveragePath: { path: './coverage/lcov.info', type: 'lcov' }, reportMode: 'warn', threshold: { statements: successCoveRage, branches: successCoveRage, functions: successCoveRage, lines: successCoveRage, }, }) );
これをGitHub Actionsで実行
■ .github/workflows/danger.yml
name: danger on: [pull_request] jobs: danger: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Cache node_modules PeperomiaNative uses: actions/cache@preview with: path: ~/.cache/yarn key: ${{ runner.os }}-PeperomiaNative-${{ hashFiles(format('{0}{1}', github.workspace, '/PeperomiaNative/yarn.lock')) }} restore-keys: ${{ runner.os }}-PeperomiaNative- - name: Install node_modules primitive if: steps.cache.outputs.cache-hit != 'true' run: yarn install working-directory: ./primitive - name: tsc primitive run: yarn tsc working-directory: ./primitive - name: Install node_modules PeperomiaNative if: steps.cache.outputs.cache-hit != 'true' run: yarn install working-directory: ./PeperomiaNative - name: test run: yarn test:coverage working-directory: ./PeperomiaNative - name: danger run: yarn danger:ci env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} working-directory: ./PeperomiaNative
これでpull requestを作成すると通知が飛んできます
まだカバレッジが80%以下なので、もろもろ修正して
カバレッジ100%になりました
テストコードの方は、こんな感じです
■ src/components/pages/ScheduleDetail/tests/Page.test.tsx
import React from 'react'; import { Alert } from 'react-native'; import { shallow, ShallowWrapper } from 'enzyme'; import Loading from '../../../molecules/ScheduleDetail/Loading'; import Card from '../../../molecules/ScheduleDetail/Card'; import Connected, { ScheduleDetailPage, ScheduleDetailType } from '../Page'; import { mockData } from './mockData'; describe('components/pages/ScheduleDetail/Page.tsx', () => { let wrapper: ShallowWrapper<ScheduleDetailType>; describe('Connected', () => { const propsData = () => ({ ...mockData, loading: false, onDismiss: jest.fn(), onDelete: jest.fn(), onCreateScheduleDetail: jest.fn(), }); it('正常に表示されている', () => { wrapper = shallow(<Connected {...propsData()} />); expect(wrapper).toMatchSnapshot(); }); }); describe('ScheduleDetailPage', () => { const showActionSheetWithOptions = jest.fn(); const onCreateScheduleDetail = jest.fn(); const onDelete = jest.fn(); const propsData = () => ({ ...mockData, loading: false, onDismiss: jest.fn(), onDelete, onCreateScheduleDetail, showActionSheetWithOptions, }); it('正常に表示されている', () => { wrapper = shallow(<ScheduleDetailPage {...propsData()} />); expect(wrapper).toMatchSnapshot(); }); it('Loadingが表示されている', () => { wrapper = shallow(<ScheduleDetailPage {...propsData()} loading />); expect(wrapper.find(Loading).exists()).toBeTruthy(); }); describe('onOpenActionSheet', () => { wrapper = shallow(<ScheduleDetailPage {...propsData()} />); wrapper .find(Card) .props() .onOpenActionSheet(); it('編集', () => { showActionSheetWithOptions.mock.calls[0][1](0); expect(onCreateScheduleDetail.mock.calls.length).toBe(1); }); it('削除', () => { const alertMock = jest.fn(); jest.spyOn(Alert, 'alert').mockImplementation(alertMock); showActionSheetWithOptions.mock.calls[0][1](1); alertMock.mock.calls[0][2][1].onPress(); expect(onDelete.mock.calls.length).toBe(1); }); }); }); });
今回のpull request
■ Dangerを導入する
https://github.com/wheatandcat/Peperomia/pull/478
■ jest-expo、enzyme導入
https://github.com/wheatandcat/Peperomia/pull/494/files
■ ScheduleDetail/Page.tsxにuseActionSheetを対応する
https://github.com/wheatandcat/Peperomia/pull/498