- Developers(開発者ガイド)概要
- 開発の事前準備
- 必須となるRust Crate(クレート)
- Writing On-Chain Code
- Getting Started with Rust
- Getting Started with AssemblyScript
- 基本的なスマートコントラクトをRustで書く方法
- スマートコントラクトのテスト
- スマートコントラクトのアップグレードとメンテナンス
- スマートコントラクトの呼び出し
- コントラクトとセッションコード
- セッションコードの書き方
- セッションコードのテスト
- コントラクトによるイベント発行を有効に
- コントラクトハッシュとパッケージハッシュの使い分け
- Casperスマートコントラクトのベストプラクティス
- Casper JSON-RPC API
- DAppsのビルド
- SDKクライアントライブラリ
- dApp Technology Stack
- ReactのFront-endテンプレート
- URefのアクセス権限とセキュリティへの考慮
- トランザクションへの署名
- スペキュラティブ(推測的)実行によるガス・コストの見積もり
- NCTLを使ったローカルネットワーク設定
- NCTLを使ったスマートコントラクトのテスト
- イベントの監視と消費
- CLIを使ったBlockchainとのやり取り
セッションコードのテスト
このセクションでは、ユニットテストのフレームワークを使用したセッションコードのテスト方法について説明しています。このチュートリアルを始められる前に、セッションコードの書き方をご確認いただき事前準備を終えておいてください。
Cargo.tomlでの依存関係の定義
testsディレクトリにあるCargo.tomlのサンプルファイルには、テストフレームワークの依存関係が含まれています。テスト用の依存関係を指定し、クレートバージョンをアップデートします。依存関係は、各プロジェクトによって変わることがあります。これらは、このプロジェクトに必要な基本的な依存関係です。
[dev-dependencies]
casper-engine-test-support = { version = "2.2.0", features = ["test-support"] }
casper-execution-engine = "2.0.0"
casper-types = "1.5.0"- casper-execution-engine – Wasmの実行を有効にする実行エンジンの機能をインポートします。各ノードには、実行エンジンのインスタンスが含まれており、テストフレームワークがこの動作をシミュレートします。
- casper-engine-test-support – テストを書き、実行エンジンのインスタンスとやり取りをするインターフェイスを提供するヘルプのクレートです。
- casper-types – Casperネットワーク用のCasperクレートが共有する型
テストの書き方
サンプルセッションコード用のテストは、tests/src/integration-tests.rs ファイル内に置かれています。
このファイルには、空の mainメソッドが含まれているため、テストプログラムは初期化されます。ここに書かれてあるように,代わりに #![no_main] の注釈をファイルの頭に使用します。
fn main() {
panic!("Execute \"cargo test\" to test the contract, not \"cargo run\".");
}#[cfg(test)] の属性は、デバックやリリース時ではなく、cargoテストを呼び出す時のみテストコードのコンパイルと実行をRustのコンパイラーに伝えます。全てのテスト機能は、グルーピングメカニズムを示すmod tests 内に組み込まれます。
#[cfg(test)]
mod tests {
// The entire test program resides here
}必要なパッケージのインポート
次に、テストを実行するために必要なパッケージをインポートします。サンプルテストは、これらのパッケージを使用します。
use casper_engine_test_support::{
ExecuteRequestBuilder, InMemoryWasmTestBuilder, DEFAULT_ACCOUNT_ADDR,
DEFAULT_RUN_GENESIS_REQUEST,
};
use casper_types::account::AccountHash;
use casper_types::{runtime_args, RuntimeArgs};定数の定義
ランタイム引数の名前は、定数として定義されます。これらの定数を定義するには、元々のコントラクトのクラスのものと全く同じ名前の使用が必須となります。セッションコードで指定された引数が、それを読み取ります。お使いのセッションコードが異なる引数をとった場合、ここで定数として定義することになります。
const ASSOCIATED_ACCOUNT_HASH: AccountHash = AccountHash::new([1u8; 32]); // hash of the associated account
const ASSOCIATED_ACCOUNT: &str = "deployment-account"; // the associated account argument
const CONTRACT_WASM: &str = "contract.wasm"; // file to pass to the instance of the EEテスト関数の作成
このステップでは、コントラクトのテストを行うプログラムをビルドします。test関数の本体は、セットアップやコードの実行、アサーションを用いた結果の確認と典型的なものを実行します。各test関数は、#[test] の属性を持つ注釈となります。
#[test]
fn <unit-test-name>{
// Test function implementation
}このユニットテストは、セッションコードテストの実施例として最適です。大まかには、テストは以下のプロセスに沿っています。
1. 実行エンジンのインスタンスとInMemoryWasmTestBuilderを初期化します。
let mut builder = InMemoryWasmTestBuilder::default();2. ジェネシス処理を実行します。
builder.run_genesis(&*DEFAULT_RUN_GENESIS_REQUEST).commit();3. test-specificロジックを実行します。この例では、セッションコードを実行するアカウントとそのアソシエイトキーの情報を取得します。全ての詳細を確認したい場合は、GitHubを参照ください。
4. 実行引数を取得します。これは、コントラクトにて定義したものと同じであるはずです。
5. 処理されるセッションコードをセットアップする実行リクエストを作成します。この例では、CONTRACT_WASM がセッションコードです。
let execute_request =
ExecuteRequestBuilder::standard(*DEFAULT_ACCOUNT_ADDR, CONTRACT_WASM, runtime_args)
.build();6. 実行エンジンを呼び出し、セッションコードを処理します。
builder.exec(execute_request).expect_success().commit();7. 出力された結果が想定していたものと合致しているかを確認します。この例では、アソシエイトキーを確認します。
assert!(associated_keys.contains_key(&ASSOCIATED_ACCOUNT_HASH));テストの実行
この例では、Makefileを使ってtestsを実行します。
make test内部では、Makefile が tests/wasm フォルダーを生成し、Wasmをそのフォルダーにコピーし cargo test でテストを実行します。
mkdir -p tests/wasm
cp contract/target/wasm32-unknown-unknown/release/contract.wasm tests/wasm
cd tests && cargo test他サンプル
カウンターユニットテストでは、セッションコードを用いてコントラクトを呼び出しています。コードによって、セッションコードやセッションコードWasm、実行引数に対する支払いを行うアカウントをロードします。そして、コードが実行エンジンを呼び出し、セッションコードを処理します。
// Use session code to increment the counter.
let session_code_request = ExecuteRequestBuilder::standard(
*DEFAULT_ACCOUNT_ADDR,
COUNTER_CALL_WASM,
runtime_args! {
CONTRACT_KEY => contract_v1_hash
},
)
.build();
builder.exec(session_code_request)
.expect_success()
.commit();認証ステップは、以下のようなものです。
let incremented_count = builder
.query(None, count_key, &[])
.expect("should be stored value.")
.as_cl_value()
.expect("should be cl value.")
.clone()
.into_t::<i32>()
.expect("should be i32.");
assert_eq!(incremented_count, 1);詳細については、GitHubリポジトリのcasper-nodeをご確認ください。
Video Walkthrough
下記のビデオでは、アカウント設定用のサンプルセッションコードのテストについて簡単に説明しています。