vueでtestメモ
インストール
vue cliを使い、vueプロジェクトにTestツールをインストール
vue add unit-jest・jestとというJS用テストツールと、Vue Test UtileというVue用のツールがインストールされる。
VS Code
VS Codeで拡張を入れる。
- Jest Snippets
- Jest Runner
- Jest
・Jsetを入れると保存すると自動でテストが走る。
・Jest Runnerを入れるとテストの上部にRunとDebugというボタンが出るので、テストを一つ単位で実行できる。
・console.logデバッグより、デバッガーで値を見たほうがテストの場合早い。
フォルダ配置
・同じテスト対象と同じフォルダに__tests__という名前を付けてテストを配置する。というのがデファクトになっているようだ。
components
__tests__
Todo.spec.js // テストコード
Todo.vue // テスト対象import Todo from "../Todo.vue"; // テスト対象を読み込むtest書き方
descriveでテストのまとまりを作る。itまたはtestという関数でテストを実行する。
・describeはネストできる。
・エディタにスニペットを入れておいたらdescと打つと出る。
describe('関数名とか', () => {
it('条件と結果とか', () => {
...
})
it("この時(when)、この場合、こういう結果が返る",() => {
...
let acutal = ... // actual 実際上の
expect(actual).toBe(true) // expect かなりの確信と理由をもって予期する
})
})検証
とにかくexpectで包んで、条件を書く。=== ならtoBe()、toEqual、=== trueならtoBeTruthy() などなどなど。好きな書き方ができるhttps://jestjs.io/docs/ja/expect
https://qiita.com/t-toyota/items/93cce73004b9f765cfcf
expect(a).toEqual(1);
expect(wrapper).not.toBeNull();事前処理、事後処理
describe内でBeforeAllやBeforeEachなどの関数を使って、複数のテストの事前処理、事後処理をまとめることができる。
describe( ...., () => {
// beforeAllは、配下のテスト群の前に一回だけ
let wrapper;
beforeAll(() => {
wrapper = mount(AAAComponent, {localVue});
});
// beforeEachは、配下のテストが実行される前に毎度一回ずつ
// afterEachは配下のテスト実行された後に一回ずつ
afterEach(() => {
...mockClear();
});
it(...関数のモック
jest.fn()でモック用の関数を生成できる。
このモック用関数は、返す値を設定できたり、呼ばれた回数や引数が何だったか検証することができる。参考: https://jestjs.io/docs/ja/mock-functions
let f = jest.fn(); // モック関数を作る
// 関数が呼ばれたかわかる。
expect(f.mock.calls.length).toBe(0);
// vueのテストではvue test utilのvueコンポーネント内にモックする機能を使って、埋め込むことが多い。
let wrapper = mount(AAA , { mocks: {f} })
importのモック
以下のようなコードがあるとする。
import { API } from "@aws-amplify/api";
...
let res = await API.graphql(...)この場合jest.mock()でimportをモックすることができる。
jest.mock("@aws-amplify/api", () => {
return { API: { graphql: jest.fn() } };
});
// jest.mockはdescribeやitの前に行う
describe(..
// テスト内からjest.mock内の関数にアクセスしたいならテスト内でもimportを書く。
import { API } from "@aws-amplify/api";
jest.mock("@aws-amplify/api", () => {
return { API: { graphql: jest.fn() } };
});
...
// jest.fnのcall数
expect(API.graphql.mock.calls.length).toBe(1);fetchのモック https://www.leighhalliday.com/mock-fetch-jest
vueコンポーネント(.vue)をテストする場合
ここから Vue Test Utileの機能
とにかくcreateLocalVueでlocalVueを作って、mountかshallowMountでマウントしてwrapperを作る。
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Todo from '@/Todo.vue'
const localVue = createLocalVue(); // 何もuseとかしていないクリーンなVue
describe('...', () => {
it('...', () => {
const wrapper = shallowMount(Todo,{localVue}) // wrapperを作る。
...
})
})・mountは普通のマウント、shallowMountは子コンポーネントがスタブに置き換えられるマウント。
・wrapperはvue componentをラップしたもので、vueに便利関数が備わったもの。
・localVueはvue.use(…)みたいな読み込みをしていないクリーンなvue
vue test utilを使った場合
text
htmlに文字列が含まれているか。text
expect(wrapper.text()).toMatch("aaa")setValue
inputに値をセットする。
・setValueはinputに値をセットしてイベントを起こしてmodelに通知する
let input = wrapper.findComponent({ ref: "userNameInput" }).find("input");
input.setValue("aaa");methodsのテスト
・methodsは.vmから生やせる。
・wrapper.vmを使うとプロパティとmethodsにアクセスできる
wrapper.vm.doSomeWork()methodsはwrapperからもモックを設定できる。
let init = jest.fn();
let wrapper = mount(AAAComponent, {localVue,methods : {init}}・非推奨のエラーが出るが、以下書くことで出ないようにできる。
import { config } from '@vue/test-utils'
config.showDeprecationWarnings = falseデータ
// マウントするときにセット
mount(Component, {
data(){
return { count : 0}
}
})
// setDataなどでもセットできる。メモ:watchは起動しない
await wrapper.setData({ count: 10 })
wrapper.vm.count // vmからアクセスできる
// データを設定して画面に表示されるかのテスト。
it("...", async () => {
await wrapper.setData({ siteName: "aaa" }); // 画面に反映されるのを待つため await する。
expect(wrapper.find("#siteName").text()).toMatch("aaa");
});プロパティ
// マウントするときにpropsDataにセットする方法
mount(Component, {
propsData: {
foo: 'some value'
}
})
// setPropsでセットできる。
await wrapper.setProps({ foo: 'bar' })
wrapper.vm.foo
// または
wrapper.props().fooemitが起動したかのテスト
expect(wrapper.emitted("event名")).toBeTruthy(); // 起動していたら {event名 : 中身} が返る のでtoBeTruthyでチェックできる
created() mounted()等のモック
簡単のなのは中の関数をモックする方法しかないっぽい。
// こういうコードがあったとして
created(){
init()
}
// 埋め込む
let init = jest.fn();
let wrapper = mount( AAAComponent , { mocks : {init} })$rootなど親コンポーネントのモック
parentComponentに設定する
const Parent = {
data() {
return {
value : 1
};
},
};
wrapper = mount(Target, {
localVue,
parentComponent: Parent,
});componentの検索
import Bar from './Bar.vue'
expect(wrapper.findComponent(Bar).exists()).toBe(true);<router-lin>のスタブ
https://vue-test-utils.vuejs.org/api/components/#routerlinkstub
import { mount, RouterLinkStub } from '@vue/test-utils'
const wrapper = mount(Component, {
stubs: {
RouterLink: RouterLinkStub
}
})
expect(wrapper.find(RouterLinkStub).props().to).toBe('/some/path')vue パターン
基本形
import { createLocalVue, mount } from "@vue/test-utils";
import AAA from "../AAA.vue";
let localVue = createLocalVue();
describe("AAA", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(AAA, {
localVue,
});
});
describe("test", () => {
it("test", () => {
expect(wrapper).not.toBeNull();
});
});
});Parentを含む
import { createLocalVue, mount } from "@vue/test-utils";
import Badge from "../Badge.vue";
let localVue = createLocalVue();
const Parent = {
data() {
return {};
},
};
describe("Badge", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(Badge, {
localVue,
parentComponent: Parent,
});
});
describe("test", () => {
it("test", () => {
expect(wrapper).not.toBeNull();
});
});
});
routerとstore をモック
// push
const $router = { push: jest.fn() };
// state user
const $store = { state: { user: { attributes: {} } } };
// state getters
let $store = {
getters: { isSignIn: jest.fn(() => true) },
};
...
// mockの仕方
let wrapper = mount(..., {... , mocks : { $router, $store } }
// apiをモック
import { API } from "@aws-amplify/api";
jest.mock("@aws-amplify/api", () => {
return { API: { graphql: jest.fn({}) } };
});
import { Auth } from "@aws-amplify/auth";
jest.mock("@aws-amplify/auth", () => {
return { Auth: { updateUserAttributes: jest.fn() } };
});
mock.calls.countのパターン
const $router = { push: jest.fn() };
import { Auth } from "@aws-amplify/auth";
jest.mock("@aws-amplify/auth", () => {
return { Auth: { updateUserAttributes: jest.fn() } };
});
const $store = { state: { user: { attributes: {} } } };
describe("UserNameSettingForm", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(UserNameSettingForm, {
localVue,
mocks: {
$router,
$store,
},
});
});
.....
it(....
await wrapper.setData({ userName: "" });
await wrapper.vm.$nextTick();
await wrapper.find("button").trigger("click");
expect(Auth.updateUserAttributes.mock.calls.length).toBe(1);
expect($router.push.mock.calls.length).toBe(1);その他
子コンポーネントが読み込まれていない、などとエラーが出た場合、子コンポーネントをモックする。
jest.mock("@/AAA.vue",() => ({
name: "AAA",
render: h => h("div")
}))methodsを使うとdeprecatedとエラーが出るので、以下のコードで抑制する。
import { config } from '@vue/test-utils'
config.showDeprecationWarnings = false


ディスカッション
コメント一覧
Saw 7700bet777 advertised somewhere. Gave it a quick look. Pretty much what you’d expect. Worth a shot if you’re bored. Head over to 7700bet777.
Hey everyone, wondering if Plus777 is the real deal? Gotta do your homework before you drop any cash. Always check reviews and security measures! Read up on plus777legitornot before you play.