そろそろもっとテストコード書いたほうが良いなーと思ったので、 モチベーションを上げるためにカバレッジを通知するようにしました。
↓こんな感じ

通知には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