Yumeville

Hello Testチュートリアル

Hello Testチュートリアル

Hello Testチュートリアルへようこそ。

今回は、Holochainアプリをテストする方法を学びましょう。このチュートリアルは、前回のHello Holoチュートリアルの続きなので、Hello Holoをやられていないのであればまずはそちらから始めましょう。

テストは、高品質なアプリを構築する上で重要なプロセスですが、それに加えて読者のアプリがどのように使用されるのかを考えるためのものでもあります。

テスト方法を理解しよう

hc initを前回のチュートリアルで実行したとき、Holochainはすでにいくつかのテストを生成していました。

テストはJavaScriptで記述されており、HolochainテストフレームワークDioramaTapeと呼ばれるツールを使用しています。読者はこれをNode.jsという、ターミナルでJavaScriptを実行することができるランタイムを使ってテストします。

まず最初にcc_tuts/test/index.jsをお好みのテキストエディターで開きましょう。この中のコードに注目してください。

まずは、テストを行うために必要なライブラリをインポートしています。

const path = require(‘path’)
const tape = require(‘tape’)

const { Diorama, tapeExecutor, backwardCompatibilityMiddleware } = require(‘@holochain/diorama’)

これはエラーを全てログに出力するツールでPromiseが失敗し、そのエラーを扱うハンドリングロジックがない場合に通知をします。Promiseは複雑な非同期コードを単純化する手法であり、Dioramaもこれを多岐にわたり使用しています。

process.on(‘unhandledRejection’, error => {
  console.error(‘got unhandledRejection:’, error);
});

次に見当たるのがコンパイルされたDNAへのパスです。

const dnaPath = path.join(__dirname, “../dist/cc_tuts.dna.json”)
const dna = Diorama.dna(dnaPath, ‘cc_tuts’)

次に、テストシナリオを設定しています。

これにより、AliceとBobという2人のエージェント(ユーザー)が作成されます。

const diorama = new Diorama({
  instances: {
    alice: dna,
    bob: dna,
},
  bridges: [],
  debugLog: false,
  executor: tapeExecutor(require(‘tape’)),
  middleware: backwardCompatibilityMiddleware,
})

これは、Holochainがmy_entry struct(構造体)とそれに対応するZome関数に基づいて生成したテストです。Hello Holoチュートリアルで我々はmy_entryのstructとそれに基づく関数を削除したので、こちらのテストも削除しましょう。

次のセクションを削除してください。

diorama.registerScenario(“description of example test”, async (s, t, { alice }) => {
  // Make a call to a Zome function
  // indicating the function, and passing it an input
const addr = await alice.call(“my_zome”, “create_my_entry”, {“entry” : {“content”:“sample content”}})
const result = await alice.call(“my_zome”, “get_my_entry”, {“address”: addr.Ok})

// check for equality of the actual and expected results
  t.deepEqual(result, { Ok: { App: [ ‘my_entry’, ‘{“content”:”sample content”}’ ] } })
})

次の行は、読者が作成したテストを実行します。

diorama.run()

テストシナリオを作成しよう

テストは、シナリオを作成することにより編成されています。これらのシナリオは、ユーザーがアプリを操作するときに実行する一連のアクションだと考えてください。

我々が作るテストでは、Aliceというユーザーに前回作ったhello_holoのzome関数を呼び出させましょう。このテストを実行したときにHello Holoという値が結果として返されればテスト成功です。

diorama.run()の真上の行に下記のコードを入力してください。

hello_holo()が正しい値を返しているのかを見極めるテストシナリオを入力しましょう。alice.callの”hello”は前回作ったZomeの名前で”hello_holo”が呼び出したい関数の名前です。{}は引数を入力する場所ですがhello_holoはパラメータがないので空になります。t.ok(result.Ok)で、hello_holo関数を呼び出した際に返される値がRustのresult型のOk()であることを確認します。同じでOk()であれば、テスト成功です。又、最後に結果の値が”hello_holo”に等しいかも確認します。

diorama.registerScenario(“Test hello holo”, async (s, t, { alice }) => {
    const result = await alice.call(“hello”, “hello_holo”, {});
    t.ok(result.Ok);
    t.deepEqual(result, { Ok: ‘Hello Holo’ })
})

今のところこのようなコードになっているはずです。

コードのチェック

const path = require(‘path’);
const tape = require(‘tape’);

const { Diorama, tapeExecutor, backwardCompatibilityMiddleware } = require(‘@holochain/diorama’);

process.on(‘unhandledRejection’, error => {
  console.error(‘got unhandledRejection:’, error);
});

const dnaPath = path.join(__dirname, “../dist/cc_tuts.dna.json”);
const dna = Diorama.dna(dnaPath, ‘cc_tuts’);

const diorama = new Diorama({
  instances: {
     alice: dna,
     bob: dna,
},
  bridges: [],
  debugLog: false,
  executor: tapeExecutor(require(‘tape’)),
  middleware: backwardCompatibilityMiddleware,
});

diorama.registerScenario(“Test hello holo”, async (s, t, { alice }) => {
  const result = await alice.call(“hello”, “hello_holo”, {});
  t.ok(result.Ok);
  t.deepEqual(result, { Ok: ‘Hello Holo’ });
});
diorama.run();

さあhello_heloディレクトリに入って、次のコマンドを実行しましょう。

nix-shellで実行

hc test

これにより、作成したテストシナリオがコンパイルおよび実行されます。かなりの出力が出てきます。

最終的にうまくいった場合は、最後に次のように表示されます:

# tests 2
# pass 2

# ok