メインコンテンツにスキップ

ビルドとテスト

今回は my_first_package.moveテストコードを追加して、ローカルで動作を確認する方法を学びます。難しくありません。同じファイルにテスト関数を追加して、手元ですぐに確認できます。


前提条件


なぜテストを書くの?

ブロックチェーンにデプロイしたコントラクトは、基本的に書き換えられません(ただしSuiはパッケージのアップグレードをサポートしており、これについては後のレッスンで扱います)。デプロイ前にバグを見つけるために、ローカルでテストを実行することが重要です。

Move には 組み込みのテスト機能があり、#[test] アノテーションを使うだけでテスト関数を定義できます。コントラクトをデプロイせずに、手元で何度でも実行できます。


テストコードを追加しよう

sources/my_first_package.move を開いて、ファイルの末尾(モジュールの閉じ括弧の前)に以下のテストコードを追加します。

sources/my_first_package.move
module my_first_package::counter {
/// カウンターオブジェクト
public struct Counter has key {
id: UID,
value: u64,
}

/// カウンターを作成して送信者に転送
entry fun create(ctx: &mut TxContext) {
let counter = Counter {
id: object::new(ctx),
value: 0,
};
transfer::transfer(counter, ctx.sender());
}

/// カウンターの値を1増やす
entry fun increment(counter: &mut Counter) {
counter.value = counter.value + 1;
}

// === テスト ===

#[test]
fun test_increment() {
// テスト用のダミーコンテキストを作成
let mut ctx = tx_context::dummy();

// Counter オブジェクトを直接作成(同じモジュール内なので非公開フィールドにアクセスできる)
let mut counter = Counter {
id: object::new(&mut ctx),
value: 0,
};

// increment を実行
increment(&mut counter);

// 値が 1 になっていることを確認
assert!(counter.value == 1, 0);

// テスト終了時にオブジェクトを後処理する
let Counter { id, value: _ } = counter;
object::delete(id);
}
}

テストコードのポイント

#[test] アノテーション

#[test] を付けた関数は、sui move test を実行したときだけ動きます。通常のビルドには含まれません。

tx_context::dummy()

テスト用のダミーコンテキストを作ります。本番では Sui ネットワークがコンテキストを作りますが、テストではこのダミーを使います。

assert!(条件, エラーコード)

条件が false の場合にテストを失敗させます。assert!(counter.value == 1, 0) は「value が 1 でなければエラー」という意味です。

後処理(分解代入 + object::delete

Move では、has key を持つオブジェクトをそのままスコープの外に捨てることはできません。テスト内では object::delete(id) を使って、最後に明示的に削除します。

同じモジュール内だからアクセスできる

テスト関数はコントラクトと同じモジュール内に書いているので、value などの非公開フィールドに直接アクセスできます。別モジュールからテストする場合は、アクセサ関数や test_scenario を使う必要があります。


試してみよう

2つの方法から好きな方を選んでください。

Option A: Move Playground

ローカル環境不要。上のテストコードを Playground に貼り付けて、Test ボタンをクリックするとブラウザ上で sui move test を実行できます。

my_first_package
Move.toml
sources
my_first_package.move
Move.toml
README.md
Console
Build ready.

Option B: VSCode + CLI

Move.toml[environments] 設定は L14 で行っています。まだの場合は ビルドで確認しよう を参照してください。

1. ビルドを実行する

プロジェクトのルートディレクトリ(Move.toml があるフォルダ)で実行してください。

sui move build

成功すると以下のように表示されます:

INCLUDING DEPENDENCY MoveStdlib
INCLUDING DEPENDENCY Sui
BUILDING my_first_package

BUILDING my_first_package まで進めば、ビルド自体は成功です。

エラーが出た場合は、テストコードの構文を見直してみてください。VSCode の Sui Extension があればリアルタイムでエラーが表示されます。

2. テストを実行する

ビルドが通ったら、テストを実行します。

sui move test

テストが成功すると、以下のような出力が表示されます:

INCLUDING DEPENDENCY MoveStdlib
INCLUDING DEPENDENCY Sui
BUILDING my_first_package
Running Move unit tests
[ PASS ] my_first_package::counter::test_increment
Test result: OK. Total tests: 1; passed: 1; failed: 0

[ PASS ] と表示されていれば成功です!increment 関数が正しく動いていることがローカルで確認できました。

assert! の条件が満たされない場合、以下のように表示されます:

[ FAIL    ] my_first_package::counter::test_increment
Test result: FAILED. Total tests: 1; passed: 0; failed: 1

この場合は increment 関数のロジックや assert! の条件を見直してみましょう。


成功の確認

以下ができれば、このレッスンは完了です:

  • my_first_package.move にテスト関数 test_increment を追加できた
  • エラーなくコンパイルできた(Playground または sui move build
  • sui move test[ PASS ] が表示された(Playground の Test ボタンまたは CLI)

このレッスンでやったこと

  • #[test] アノテーションでテスト関数を定義した
  • tx_context::dummy() でテスト用コンテキストを作成した
  • assert! で期待する値を検証した
  • sui move buildsui move test でコントラクトをローカル検証した