mocha + @firebase/testingでハマった時にはタイムアウト時間を見直す
Firebaseで開発をしていると、FirestoreのルールやCloud Functionsとの連携など、細々とした設定を安全にテストしたくなりますよね。
そういった用途のために、FirebaseではFirestoreやCloud Functionsのエミュレータが用意されています。
また、上記のエミュレータをテスティングフレームワークから叩くためのヘルパーとして、 @firebase/testing
というNode.js向けライブラリも提供されています。
実用の仕方はこちらのSOの回答がわかりやすかったです。
なんか動かない
さて、これは良いツールを知ったと思い、mochaの中で動かすことにしました。前述の記事の内容を組み合わせて、次のようなテストコードを書いてみました。
import assert = require("assert");
import * as firebase from "@firebase/testing";
import "mocha";
const FIRESTORE_PROJECT_ID = "my-project";
function authedApp(auth?: object) {
return firebase.initializeTestApp({ projectId: FIRESTORE_PROJECT_ID, auth }).firestore();
}
describe("hoge", () => {
beforeEach(async () => {
await firebase.clearFirestoreData({ projectId: FIRESTORE_PROJECT_ID });
});
afterEach(async () => {
await Promise.all(firebase.apps().map(app => app.delete()));
});
const COLLECTION_NAME = "myCollection";
it("fuga", async () => {
const db = authedApp();
// Manually add item to collection
const ref = await db.collection(COLLECTION_NAME).add({hello: 'World!'});
// Fetch item by id
const resp = await db.collection(COLLECTION_NAME).doc(ref.id).get();
assert(resp.exists);
assert.deepEqual(resp.data(), { hello: 'World!' });
});
})
これを実行すると、次のような結果になりました。
hoge
1) "before each" hook for "fuga"
0 passing (10s)
1 failing
1) hoge
"before each" hook for "fuga":
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/path/to/hoge.test.ts)
fuga
テストが始まる前の beforeEach
がタイムアウトして落ちているようです。サンプルでいうと、↓のデータベースをクリアしている部分ですね。
beforeEach(async () => {
await firebase.clearFirestoreData({ projectId: FIRESTORE_PROJECT_ID });
});
clearFirestoreData
が止まってしまったのだと思い、しばらくソースコードを読んでいたりしたのですが、エミュレータ向けのgRPCクライアントの初期化の行で終わるということまでしかわからず、途方にくれていました。
タイムアウトを延ばせばよかった
mocha先生は「2秒も待ったのに結果が出ないじゃないの! きぃぃぃ!!!!」とブチ切れておられました。
Error: Timeout of 2000ms exceeded.
私もそこに引っ張られて「そうだよな……2秒もかけてダメってことは、たぶんどこかで処理が止まったんだよな……」という前提で調査を進めていましたが、ふとこのIssueが mocha --timeout=10000
を設定しているのを見て、「あれ、本当に2秒以上かかっているのでは?」と思い直しました。
10秒で済むとは思えなかったので、雑に --timeout=30000
で実行してみます。また、 beforeEach
がどのくらいかかっているのかを調べるべく、次のように計測コードを仕込んでみました。
beforeEach(async () => {
const start = Date.now();
await firebase.clearFirestoreData({ projectId: FIRESTORE_PROJECT_ID });
console.log(`before each time: ${Date.now() - start}`);
});
その結果がこちらになります。
hoge
before each time: 10089
✓ fuga (10227ms)
1 passing (20s)
やったー通ったー🎉
結局、初期化もテスト自体も10秒以上かかっていました。テスト内容にもよりますが、少なくとも15000ms程度のタイムアウトは設定しておいたほうがよさそうです。
まとめ
冷静に考えてみると、Firebaseのローカルエミュレータへのアクセスを伴うということはE2Eテストなので、時間がかかるのは当然といえば当然でした。
@firebase/testing
さん、実装を疑ってごめんな……
Author And Source
この問題について(mocha + @firebase/testingでハマった時にはタイムアウト時間を見直す), 我々は、より多くの情報をここで見つけました https://qiita.com/Nkzn/items/ea333216280adac81a49著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .