この前の続き。
まず、StoryBookを使えるようにする。Vueで使う場合はバージョンによって色々やり方があるっぽくて、情報が錯綜しがちで凄いハマル。今現在(2018/11/24)ではこの感じでやればいけそう。
あと、StoryBookでコンポーネント単位の確認用ページを作り、それを使ってビジュアルリグレッションテストをやれるようにする。これは公式のココに書いてあるやり方で基本はやるんだけど、Vueだと動かなかったのでちょっと変える。ついでに、Jestでコンポーネントの単体テスト出来るようにする。
今回のサンプルの最終系は下記にあげてます。作り方の全容も下記に記載してます。あー、あとCentOS7です。
https://github.com/n79s/vue-cli-storybook-sample
動かすためのポイントだけ記載。
まずVue CLI3でプロジェクト作るインストール。
vue create vue-cli-storybook-sample #手動セッティングで作る↓ Vue CLI v3.1.3 ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, Linter, Unit ? Pick a linter / formatter config: Prettier ? Pick additional lint features: Lint on save ? Pick a unit testing solution: Jest ? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files ? Save this as a preset for future projects? (y/N) #上記の構成で作った場合 #Unitテストは↓のディレクトリで作る tests/unit/****.spec.js #Unitテスト実行は↓ npm run test:unit
で、StoryBookは↓の感じでインストール。WebPackの設定がどうのこうのって昔はあったんだけど、今現在ではさくっと動く。
#https://storybook.js.org/basics/guide-vue/
npm install --save-dev @storybook/vue
npm install --save-dev babel-core babel-loader babel-preset-vue
#package.jsonに下記を追記
{
.....
"scripts": {
"storybook": "start-storybook -p 9001 -c .storybook"
}
.....
}
#.storybookディレクトリを作って設定ファイルを作る
mkdir .storybook
#.storybook/config.js
import { configure } from '@storybook/vue';
import Vue from 'vue';
function loadStories() {
require('../stories');
const req = require.context('../stories', true, /\.stories\.js$/);
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
#storybookの実行
npm run storybook
そしたら、ビジュアルリグレッションテストできるようにする。
#必要なパッケージのインストール
npm install --save-dev jest puppeteer jest-puppeteer jest-image-snapshot start-server-and-test
#jest.config.js
module.exports = {
moduleFileExtensions: ['js','jsx','json','vue'],
preset: 'jest-puppeteer',
testRegex: './*\\.test\\.js$',
setupTestFrameworkScriptFile: './tests/setupVisualTests.js',
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.js$': 'babel-jest',
},
transformIgnorePatterns: ['/node_modules/'],
};
#package.jsonに下記を追記
.....
"scripts": {
"jest:visual": "jest --clearCache && vue-cli-service test:unit -c jest.config-visual.js",
"test:visual": "start-server-and-test storybook http-get://localhost:9001 jest:visual",
"jest:visual-update": "jest --clearCache && vue-cli-service test:unit -c jest.config-visual.js --updateSnapshot",
"test:visual-update": "start-server-and-test storybook http-get://localhost:9001 jest:visual-update"
}
.....
で、はまったポイント。
まず、VueCLI3はjestを直で実行するのはサポートしてないから「vue-cli-service test:unit」を使えって、GitHubのIssueに書いてあった(どのIssueだったか見つけられなくなった・・・)。色んなサイトで見てるとだいたい「jest -c ****」みたいなコマンドでやる形になってるので、ここを「vue-cli-service test:unit -c ******」に変えないとだめ。
あと、StoryBookの公式に書いてあるjest.config.jsの記載だと動かないのと、VueCLI3で作られてるjest.config.jsでもダメだった。↓の内容にする
#jest.config.js
module.exports = {
moduleFileExtensions: ['js','jsx','json','vue'],
preset: 'jest-puppeteer',
testRegex: './*\\.test\\.js$',
setupTestFrameworkScriptFile: './tests/setupVisualTests.js',
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.js$': 'babel-jest',
},
transformIgnorePatterns: ['/node_modules/'],
};
一番、はまったのが、「transform」のとこ。jsをbabel-jestでやるように記載しないとダメっぽい。VueCLI3のIssueに上がってた。ただ、まだ解決してないっぽい。何個か解決策がこのissueに書いてあるんだけど、解決するかは人(環境)によるっぽいですね。ちなみに、これをやってないとテスト実行したときに「SyntaxError: Unexpected token import」がでる。jsファイルをbabelで変換出来てないって事なんかな?あと、transformIgnorePatternsでnode_modulesを除外する設定入れておかないとダメになることもある様子。
issueに書いてある解決策はだいたい↓の感じ。
#transformは↓のどれか。js使えるようにするとの、パスがうまく出来てないかのどっちかかな '^.+\\.js$': 'babel-jest', '^.+\\.(js|jsx)?$': 'babel-jest' '^.+\\.(js|jsx)?$': '<rootDir>/node_modules/babel-jest' #transformIgnorePatternsは↓のどっちか transformIgnorePatterns: ['/node_modules/'] transformIgnorePatterns: ['<rootDir>/node_modules/'] #あとはnode_modules一回消してnpm installし直すとか rm -rf node_modules && npm cache clean --force && npm install #キャッシュをクリアするとか "test:unit": "jest --clearCache && vue-cli-service test:unit
自分は通常の単体テストとは分けてjest.config.js作って指定している。あと、jest.config.jsに「preset: 'jest-puppeteer',」入れてないと動かない。あーあと、スナップショットを更新するコマンドは「"jest:visual-update": "jest --clearCache && vue-cli-service test:unit -c jest.config-visual.js --updateSnapshot",」でやる。単体テスト側のスナップショットの更新は↓のコマンド
#単体テスト側のスナップショットの更新は↓(途中の--は間違ってるわけじゃない) npm run test:unit -- --updateSnapshot
「--」重ねるのがはまった。
次はStoryBookのアドオンを調整するんだけど、StoryBookのReadmeではまった。「webpack.config.js」で最終的に↓の感じにする。
const path = require('path');
module.exports = (storybookBaseConfig, configType, defaultConfig) => {
defaultConfig.module.rules.push({
test: [/\.stories\.js$/, /index\.js$/],
loaders: [require.resolve('@storybook/addon-storysource/loader')],
include: [path.resolve(__dirname, '../stories')],
enforce: 'pre',
});
defaultConfig.module.rules.push({
resourceQuery: /blockType=docs/,
use: [
'storybook-readme/env/vue/docs-loader',
'html-loader',
'markdown-loader',
],
});
return defaultConfig;
};
で、ビジュアルリグレッションできるようにしたんだけど、自分はコンポーネントはシステム本体とは別プロジェクトにしてやってる。Vuexとか絡むとロジックをかなり書かないといけないので。見た目の変更箇所だけ確認できるようにしたい。SotryBookでその辺は定義して、StoryBookのページを丸ごとGetしてやるだけにする感じ。
普通のe2eのテストでは無く、あくまでも単体テストの一環としてやる感じ。e2eのテストはSeleniumでやる。Chrome拡張で操作記録とってそのまま動かせるので。ただし、操作記録のスクリプトは長い期間保守することを考えるとさすがにイケてないので、調整は必要(要素の指定の仕方とか)。
参考サイト
storybook系
- https://storybook.js.org/basics/guide-vue/
- https://storybook.js.org/addons/introduction/
- https://storybook.js.org/testing/automated-visual-testing/
vue-test-utils系
- https://vue-test-utils.vuejs.org/ja/guides/testing-single-file-components-with-jest.html
- https://vue-test-utils.vuejs.org/ja/guides/getting-started.html
- https://vue-test-utils.vuejs.org/ja/guides/common-tips.html