Help us understand the problem. What is going on with this article?

【Vue.js】【TDD】ブラウザだけでVueテストを書きましょう

More than 1 year has passed since last update.

基本的に大きなVue.jsアプリケーションを開発するとVue-cliで新しいプロジェクトを作成して、Babel、Jest、Webpackなどを入れます。複雑ですね。でもツールは全部JavaScriptなので、ブラウザだけでも使えます。

この記事で、Node.js、Webpackなどの複雑なツールなしでvue-test-utilsを使ってTDDで簡単なアプリケーションを作ります。ブラウザとスクリプトタグだけで書きます。 

何を作る?

これは、MUST-DOアプリケーションです。TODOのようなアプリケーションですが、TODOを入れられないし、削除できないのでMUST-DOです。

ソースコードはここindex.htmlだけです。

Vueとテストを書くには必要なものは:

  1. Vue
  2. Vue-test-utils
  3. テストランナー (Mocha.jsを使います)

始めます。

検証は?

簡単なアプリケーションなので複雑な検証ライブラリーを使わないです。その代わりに、この関数を使います。

function assert(actual, expected) {
  if (actual != expected) {
    throw Error("やばい")
  }
}
assert(1, 2) // => false
assert("A", "A") // => true

このテンプレートで始めます。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <script src="https://cdn.rawgit.com/vuejs/vue/dev/dist/vue.min.js"></script>
  <script src="https://cdn.rawgit.com/vuejs/vue/dev/packages/vue-template-compiler/browser.js"></script>
  <script src="https://cdn.rawgit.com/vuejs/vue-test-utils/dev/packages/test-utils/dist/vue-test-utils.iife.js"></script>
  <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" />
  <script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
  <script>mocha.setup('bdd')</script>

</head>
<body>
  <div id="mocha"></div>

  <script>
    mocha.run()
  </script>
</body>
</html>

scriptが5個くらいがあります。

  1. Vue
  2. Vue template compiler (vue-test-utilsがこれを使う)
  3. vue test utils (Vueコンポーネントを簡単にテスト)
  4. mocha.js (テストランナー)
  5. mocha.css (Mocha.jsの結果をいい感じにレンダー)

条件

2つのコンポーネントに分けます。

  1. MustDoList

    • MustDoItemをレンダーする
    • mustdos変数を管理する
  2. MustDoItem

    • idtextをレンダーする

MustDoItemから!

MustDoItem

最初のテストを書きましょう。

<script>
function assert(actual, expected) {
  if (actual != expected) {
    throw Error("やばい")
  }
}

const { shallowMount } = VueTestUtils

describe("MustDoItem", () => {
  it("idとtextをレンダーする", () => {
    const wrapper = shallowMount(MustDoItem)

    assert(wrapper.find(".id").text(), "1")
    assert(wrapper.find(".text").text(), "テストを書く")
  })
})

mocha.run()
</script>

そしてページをリフレッシュして:

image.png

どうなりました?

ReferenceError: MustDoItem is not defined

じゃ、作りましょう。

<script>
function assert(actual, expected) {
  if (actual != expected) {
    throw Error("やばい")
  }
}

const MustDoItem = Vue.component('must-do-item', {
  template: "<div></div>"
})

const { shallowMount } = VueTestUtils

describe("TodoItem", () => {
  it("idとtextをレンダーする", () => {
    const wrapper = shallowMount(MustDoItem)

    assert(wrapper.find(".id").text(), "1")
    assert(wrapper.find(".text").text(), "テストを書く")
  })
})

mocha.run()
</script>

image.png

Error: [vue-test-utils]: find did not return .id,
cannot call text() on empty Wrapper

class="id"が必要そうです。

const MustDoItem = Vue.component('must-do-item', {
  template: `
  <div>
    <div class="id"></div>
    <div class="text"></div>
  </div>`
})

image.png

やばいまで進みました。idtextをレンダーしましょう。MustDoListからpropsとして受け取ります。

const MustDoItem = Vue.component('must-do-item', {
  props: {
    id: {
      type: Number,
      required: true
    },

    text: {
      type: String,
      required: true
    }
  },
  template: `
  <div>
    <div class="id">{{ id }}</div>
    <div class="text">{{ text }}</div>
  </div>`
})

まだやばいです。テストも更新しないといけません:

describe("TodoItem", () => {
  it("idとtextをレンダーする", () => {
    const wrapper = shallowMount(MustDoItem, {
      propsData: {
        id: 1,
        text: "テストを書く"
      }
    })

    assert(wrapper.find(".id").text(), "1")
    assert(wrapper.find(".text").text(), "テストを書く")
  })
})

image.png

NOTやばい!!

MustDoList

MustDoListは:

  • mustdos配列をループして、
  • MustDoItemをレンダーする

テストと簡単なコンポーネントを書きましょう。

const MustDoList = Vue.component('must-do-list', {
  template: `
  `
})

describe("MustDoList", () => {
  it("MustdoItemを3つレンダーする", () => {
    const wrapper = shallowMount(MustDoList, {
      data() {
        return {
          mustdos: [
            { id: 1, text: "テストを書く" },
            { id: 2, text: "コードを書く" },
            { id: 3, text: "Qiitaに投稿する" },
          ]
        }
      }
    })

    assert(wrapper.findAll(".must-do").length, 3)
  })
})

image.png

またやばい。MustDoItemをレンダーしましょう。

image.png

Great!

最後に、MustDoItemを使ってみましょう。

<script>

// ...

const MustDoList = Vue.component('must-do-list', {
  data() {
    return {
      mustdos: mustdos
    }
  },

  // ...
})

// ...

const mustdos =  [
  { id: 1, text: "テストを書く" },
  { id: 2, text: "コードを書く" },
  { id: 3, text: "Qiitaに投稿する" },
]

document.addEventListener("DOMContentLoaded", () => {
  new Vue({
    el: "#app",
    template: `
      <must-do-list>
      </must-do-list>
    `
  })
})

</script>


<div style="margin-left: 50px">
  <div id="app"></div>
</div>

image.png

完了です。

まとめ

ツールは楽しいけど、たまにシンプルがいいですね。このindex.htmlを使って色々なテストを書いてみてください。vue-test-utilsのドキュメントはこちらです

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away