フルマラソンに初参加

6年前、友人に誘われて参加した第1回富士山マラソン。河口湖を1周(18キロくらい)でしたが、ヘトヘトになっていたものでした。ブログを探してみたら、当時の記事がありました。

tydk27.hatenadiary.com

今年に入ってから、10キロやハーフのマラソン大会に参加していたので、思い切ってフルマラソンへの参加を決めました。そう、思い出の富士山マラソンへ。

当日朝、河口湖は朝靄で真っ白になっていたものの、スタート時間が近づくと靄は晴れて青空が見えていました。

スタートして数キロ、富士山が目の前にドーンと出てくるとランナーから歓声が。こういうの、なんか楽しい。

沿道の応援に助けられ、ボランティアの方々の支援に助けられ、いろんな人たちの助けを得ながらゴールに向かう。マラソン大会に出るといつも泣きそうになります。応援してくれた人、本当にありがとうございました。

30キロを過ぎて、脚へのダメージを少しづつ感じ始め、35キロくらいから呼吸も辛くなってきました。ラスト3キロは意地ですね、必死です。

タイムはギリギリでサブ5(5時間切り)を達成。前半はもっとペースを上げれたような気がする、など反省点もありますが、一先ず目標は達成できたので良かったかなと思います。

帰るまでがマラソン大会です。クラッチペダルを踏む脚が、痛い。

Vue.jsとVuexとユニットテスト

どこもかしこも混雑していることがわかっているので、連休前半は家からほとんど出ることがありませんでした。

早速本題。

component内のボタンがクリックされたらstateが変更される、けどstateが変更されるだけで描画には影響がない、といった場合にはテストをどう書けばいいのでしょうか。いろいろと試したところ、なんとなくまとまってきたので整理してみます。

ここでテストする必要があるものは、簡単に分けてみると以下の2つになるのではないかと思います。

  • ボタンをクリックするとmethod(もしくはaction)が呼ばれる
  • stateが変更される

まずは後者ですが、Vuexにおいてstateを変更するにはmutationをcommitするしかないので、mutationのテストとしてしまえばいいはず。さっそく書いてみます。mochaをフレームワークに、アサーションにはchaiを使っています。

import { mutations } from 'mutations'
import * as types from 'mutation-types'

describe('test for mutations', () => {
  it('do CHANGE_STATE', () => {
    const state = {
      hogepiyo: {}
    }

    const hogepiyoData = {
      hoge: 'hogehoge',
      piyo: 'piyopiyo'
    }

    mutations[types.CHANGE_STATE](state, hogepiyoData)

    assert.strictEqual(state.hogepiyo, hogepiyoData)
  })
})

残ったほうについては、componentをマウントしてクリックイベントを発火させればテストできそう。method内の処理は見る必要がないので、sinonを使ってスタブにしておきます。

import Vuex from 'vuex'
import { shallow, createLocalVue } from '@vue/test-utils'

import { state } from 'state'
import App from 'App.vue'

const localVue = createLocalVue()
localVue.use(Vuex)

describe('test for App.vue', () => {
  let store

  beforeEach(() => {
    store = new Vuex.Store({
      state
    })
  })

  it('call submit', () => {
    const wrapper = shallow(App, { store, localVue })
    const clickMethodStub = sinon.stub()

    wrapper.setMethods({ submit: clickMethodStub })
    wrapper.find('.btn-submit').trigger('click')

    assert.strictEqual(clickMethodStub.called, true)
  })
})

こんなものでしょうか。今回の場合、mutationのテストはさて置き、componentのテストは不要な気もします。どこまでテストするのか、は個々人の好みによるところもあるのでなんとも言えませんが。

Babel7事始め

最近のBebelがよくわかりません、という人向けに書いてみます。

7系

現時点で7系はBeta版となっています。公式Docは6系について書かれているので、7系を使ってみたい人には何の参考にもなりません。というか、インストールするパッケージ名がそもそも違います。 7系では以下のパッケージとプリセットから始めることになります。

  • @babel/core
  • @babel/preset-env

scoped packages

見慣れない命名規則に一部の人は面食らうと思いますが、見慣れないだけで標準仕様です。 プリフィックスの @名前空間のようなものです。その名前空間/ 下にパッケージ名やプラグイン名を付けるというような感じです。

  • babel-cli -> @babel/cli
  • babel-core -> @babel/core
  • babel-preset-env -> @babel/preset-env

es20xx

かつて大正義だったプラグインのbabel-preset-es20xxは非推奨となりました。yarn add babel-preset-es2015 babel-preset-es2016 などという鬱陶しい作業は不要になったのです。代わりにbabel-preset-envを使いましょう。preset-envの使い方は多く出回っているので省略しますが、必要なときだけpolyfillを追加してくれるという超便利オプション 'useBuiltins': 'usage' は、以下のQiita記事が参考になります。

babel-preset-env 2.0のuseBuiltInsを使ってpolyfillする - Qiita

ECMAScript Proposal Stages

プラグインはbabel-preset-stage-xでまとめて導入するのが楽です。が、使いもしないプラグインを読み込むのは無駄だし、管理という面から見ても微妙です。これからは必要なプラグインのみをインストールするようにしましょう。なお、object-rest-spreadなど、よく使うであろうプラグインはpreset-envに含まれているので要注意です。

その他

提案段階にあるプラグイン命名規則が変更になって、他と差別化されて一目でわかるようになりました。また、es2015といった不要な年表記はなくなりました。スッキリですね。

  • babel-plugin-transform-class-properties -> @babel/plugin-proposal-class-properties
  • babel-plugin-transform-es2015-classes -> @babel/plugin-transform-classes

Webpackを使う場合は、babel-loaderも7系に対応したものを使います。

  • babel-loader@8.0.0-beta.0

地味に嬉しい点として、babelrcが .babelrc.js といった感じにjsで書けます。いろいろ弄れるようになるので捗りますね。

詳細仕様は公式で確認を。公式は正義なり。