ここで私のユニットテストの方法について考えました。私はこれに改善の余地がたくさんあることを認めて最初になるでしょう!
まず、私は次のコードを持っている私のserver.coffee
ファイルに:私は実行時にMeteor.settings [「テスト」]は私が行うことができ、定義されている場合
Meteor.startup ->
return unless Meteor.settings["test"]
require = __meteor_bootstrap__.require
require("coffee-script")
fs = require("fs")
path = require("path")
Mocha = require("mocha")
mocha = new Mocha()
files = fs.readdirSync("tests")
basePath = fs.realpathSync("tests")
for file in files
continue unless file.match(/\.coffee$/) or file.match(/\.js$/)
continue if file[0] == "."
filePath = path.join(basePath, file)
continue unless fs.statSync(filePath).isFile()
mocha.addFile(filePath)
mocha.run()
すべてこのコードの最初にのみ実行されます私のテストは現地で行われていますが、実際には生産には当てはまりません。次に、 "tests"ディレクトリでjavascriptまたはcoffeescriptファイルを探します(私の実装ではサブディレクトリは検索されませんが、追加するのは簡単でしょう)。mocha
インスタンスに追加します。ここでは、アサーションライブラリと組み合わせて、優れたmochaのjavascriptテストライブラリを使用しています。
このコードはすべてMeteor.startup
コールの中にラップされているため、単体テストはサーバーの起動時に実行されます。 Meteorはコードを変更するたびに自動的にテストを再実行するので、これは特に便利です。データベースを分離してXHRを実行しないという決定のため、私のテストは数ミリ秒で実行されるため、これはあまり迷惑ではありません。テスト自分自身のために
、私はアサーションライブラリに引っ張るために
chai = require("chai")
should = chai.should()
を行う必要があります。しかし、解決すべきいくつかの難しい問題がまだあります。まず、Meteorのメソッド呼び出しは、ファイバーでラップされていないと失敗します。私は現在、この問題に非常に良い解決策を持っていないが、私はモカのit
機能を置き換えるためにitShould
機能を作成し、ファイバ内の試験体を包む:テストのために、
# A version of mocha's "it" function which wraps the test body in a Fiber.
itShould = (desc, fn) ->
it(("should " + desc), (done) -> (Fiber ->
fn()
done()).run())
次のアップが問題です私のコレクションをモックコレクションに置き換えています。コレクションをグローバル変数に入れるという標準的な流行のプラクティスに従えば、これは非常に困難です。ただし、グローバルオブジェクト上にコレクションを作成すると、それを行うことができます。 myApp.Collection = new Meteor.Collection("name")
でコレクションを作るだけです。次に、あなたのテストで、あなたがコレクションからbefore
機能のモックを持つことができます。
realCollection = null
before ->
realCollection = myApp.Collection
myApp.Collection = new Meteor.Collection(null)
after ->
myApp.Collection = realCollection
この方法は、あなたのコレクションは、テスト実行の継続のために嘲笑されていますが、あなたと対話することができますので、それを復元していますアプリは正常です同様の方法で模擬することも可能です。たとえば、グローバルMeteor.userId()
関数は、クライアントが開始した要求に対してのみ機能します。私は実際に彼らがこの問題へのよりよい解決策を提供できるかどうかを確認するために流星に対してa bugを提出してきましたが、今の私はテストのために私自身のバージョンとの機能を交換しています:このアプローチは、いくつかのために働く
realUserIdFn = null
before ->
realUserIdFn = Meteor.userId
Meteor.userId = -> "123456"
after ->
Meteor.userId = realUserIdFn
メテオの一部ですが、すべてではありません。たとえば、私はthis.setUserId
を呼び出すメソッドをテストする方法を見つけていません。なぜなら、その動作を模倣する良い方法はないと思うからです。しかし、全体的には、このアプローチは私のために働いています...私はコードを変更すると自動的にテストを再実行できることが大好きで、単体でテストを実行するのが一般的には良い考えです。また、サーバー上のテストをブロックすることができ、コールバックチェーンを使用しないで簡単にテストを行うことができます。テストは次のようになります:
describe "the newWidget method", ->
itShould "make a new widget in the Widgets collection", ->
widgetId = Meteor.call("newWidget", {awesome: true})
widget = myApp.Widgets.findOne(widgetId)
widget.awesome.should.be.true
私はこれを理解していないかもしれませんが、このコードはブラウザで動作するようですね。その場合、メソッドを単独でテストするのはかなり難しいと思います。何か特別なことが起こっていない限り、あなたのメソッド呼び出しはXHRやデータベースの書き込みや作業をするでしょうか? –