読者です 読者をやめる 読者になる 読者になる

Atomのパッケージを作る(4) spec編

f:id:uraway:20151215173245p:plain
参考:http://jasmine.github.io/1.3/introduction.html

specs

AtomではJasmiseをspecフレームワークとして使っています。必須ではありませんが、新機能にはspecをつけるべきでしょう。Atomのテストに関するフライトマニュアルを訳しながら、実際にspecを書いてみます。

必要なもの

新しくspecを作る

コアパッケージのspecがそれぞれAtom specspackage specs(markdown-preview)のようにGitHubにあるので大変参考になります。

specファイルを作る

specディレクトリにsample-spec.coffeeのように、末尾が-specのファイルを作ります。

describe メソッド

describeメソッドは記述と関数を引数に取ります。もし記述が行動を説明するものならwhenから始まり、ユニット(ひとまとまりの)テストならメソッド名から始まります。

describe "when a test is written", ->
  # contents
describe "Editor::moveUp", ->
  # contents

it メソッド

itメソッドも記述と関数を引数に取ります。記述フローをitメソッドで作りましょう。例えば、this should workの記述はit this should workとなりうまく読めませんが、should workの記述はit should workとなるので良さそうです。

describe "when a test is written", ->
  it "has some expectations that should pass", ->
    # Expectations

Expectations

Jasmine documentation about Expectations

シンプルな例

describe "when a test is written", ->
  it "has some expectations that should pass", ->
    expect("apples").toEqual("apples")
    expect("oranges").not.toEqual("apples")

非同期のspec

Promises

これを使うとAtomでは楽。AtomwaitsForPromise関数を使うことができます。

describe "when we open a file", ->
  it "should be opend in an editor", ->
    waitsForPromise ->
      atom.workspace.open('c.coffee').then (editor) ->
        expect(editor.getPath()).toContain 'c.coffee'

このメソッドdescribe it beforeEach afterEach関数で使うことができます。

describe "when we open a file", ->
  beforeEach ->
    waitsForPromise ->
      atom.workspace.open 'c.coffee'

    it "should be opened in an editor", ->
      expect(atom.workspace.getActiveTextEditor().getPath()).toCtoContain 'c.coffee'

複数のpromisesを待つ必要があるならそれぞれに新しいwaitsForPromise関数を使います。

describe "waiting for the package to load", ->

  beforeEach ->
    waitsForPromise ->
      atom.workspace.open('sample.js')
    waitsForPromise ->
      atom.packages.activatePackage('tabs')
    waitsForPromise ->
      atom.packages.activatePackage('tree-view')

  it "should have waited long enough", ->
    expect(atom.packages.isPackageActive('tabs')).toBe true
    exoect(atom.packages.isPackageActive('tree-view')).toBe true

非同期のコールバック関数

specは非同期関数にwaitsForruns関数を使うことができます。

describe "fs.readdir(path, cb)", ->
  it "is async", ->
    spy = jasmine.createSpy('fs.readdirSpy')

    fs.readdir('/tmp/example', spy)
    waitsFor ->
      spy.callCount > 0
    runs ->
      exp = [null, ['example.coffee']]
      expect(spy.mostRecentCall.args).toEqual exp
      exoect(spy).toHaveBeenCalledWith(null, ['example.coffee'])

Jasmine documentation about asynchronous tests

specの実行

window:run-package-specs: specディレクトリにあるすべてのspecを実行
window:run-all-specs: Atomコアのspecと、すべての初期パッケージspecを実行

制限されたspecのサブセットを実行するにはfdescribefitメソッドを使います。ひとつあるいは幾つかのspecにフォーカスすることが可能です。

describe "when a test is written", ->
  fit "has some expectations that should pass", ->
    expect("apples").toEqual("apples")
    expect("oranges").not.toEqual("apples")

CI環境での実行

Travis CI For Your Packages
AppVeyor CI For Your Packages

これを参考に次回specを実際に書いてみます。続く!!