Move和Aptos的单元测试和函数调用。
在我们开始动手对Resource进行增删改查等操作之前,我们有必要先熟悉Move和Aptos的单元测试和函数调用。否则,我们无法保障程序的质量。
模块化、模块和脚本、Move单元测试、Aptos单元测试、函数调用、脚本调用
什么是模块化?对搞过工程项目的来讲,模块化并不陌生。模块化就是把功能相似的代码都放在一起,要用的时候能快速找到。
在Java web项目里,可以创建Component、Service、Controller、Repository等文件夹来实现模块化。
在Python项目里,一个.py文件就是一个模块。
在Move项目里,用Module
关键字来表示模块。而用Script脚本表示传统语言(python、java、c等)中main
函数的概念。因为一个程序只能有一个main函数。所以,单个Script脚本文件中的函数数量不能超过一个,这是再自然不过的事情。
Move has two different types of programs: Modules and Scripts. Modules are libraries that define struct types along with functions that operate on these types. Scripts are executable entrypoints similar to a main function in a conventional language. ---引自《Move Book》
Script脚本可以理解为main函数,在脚本里可以进行模块函数调用。
//sources/debug_script.move
script {
use std::debug;
const ONE: u64 = 1;
// bool literals (true, false)
// u64 literals (e.g., 10, 58)
// address literals (e.g., 0x12, 0x0000000000000000000000000000000f)
// hexadecimal strings (e.g., 'x"0012"' will parse as the vector<u8> value [00, 12])
// ASCII strings (e.g., 'b"hi"' will parse as the vector<u8> value [68, 69])
fun debug_script(x:u64 , y:bool ,addr:address) {
let sum = x + ONE;
debug::print(&sum);
debug::print(&y);
debug::print(&addr);
}
}
控制台输入move sandbox run sources/debug_script.move --args 33 true 0xf
。
通过使用--args
向脚本main函数传参。执行结果如下:
ouhuang@LAPTOP-HM465BTT:~/learn_move$ move sandbox run sources/debug_script.move --args 33 true 0xf
[debug] 34
[debug] true
[debug] 0000000000000000000000000000000F
注意!script脚本的特点
module Test{...}
模块嵌套在address 0x4{...}
里,这种写法表示Test模块经publish后会被放到账户0x4的名下。所以,才可以使用0x4::Test::函数名
这种形式进行调用。
// sources/Test.move
module 0x4::Test {
use std::signer;
use std::debug;
struct Resource has key { i: u64 }
public fun publish(account: &signer) {
move_to(account, Resource { i: 10 });
}
//Comments must be written in English, not in Chinese
public fun write(account: &signer, i: u64) acquires Resource {
if (!exists<Resource>(signer::address_of(account))){
debug::print(&b"not exists");
move_to(account, Resource { i: 11 });
}else{
borrow_global_mut<Resource>(signer::address_of(account)).i = i;
debug::print(&borrow_global_mut<Resource>(signer::address_of(account)).i);
}
}
public fun unpublish(account: &signer) acquires Resource {
let Resource { i: _ } = move_from(signer::address_of(account));
}
#[test(account = @0xf)]
fun test_publish(account: signer) {
publish(&account);
}
#[test(account = @0xf)]
fun test_write(account: signer) acquires Resource {
publish(&account);
write(&account, 333);
}
}
使用move build
编译sources下的move代码。
ouhuang@LAPTOP-HM465BTT:~/learn_move$ move build
INCLUDING DEPENDENCY MoveNursery
INCLUDING DEPENDENCY MoveStdlib
BUILDING learn_move
在沙盒环境使用move sandbox publish -v
发布字节码到0x4名下。
move sandbox publish -v
ouhuang@LAPTOP-HM465BTT:~/learn_move$ move sandbox publish -v
Found 1 modules
Updating an existing module 00000000000000000000000000000004::Test (wrote 354 bytes)
Wrote 354 bytes of module ID's and code
检查0x4地址下是否保存Test模块。
ouhuang@LAPTOP-HM465BTT:~/learn_move$ ls storage/0x00000000000000000000000000000004/modules
Test.mv
在Move语言里,编写单元测试函数需要注意以下几点:
以上两点参考自《Move Book》:https://diem.github.io/move/unit-testing.html
Only parameters with a type of signer are supported as test parameters. If a non-signer parameter is supplied, the test will result in an error when run.
使用move test
执行单元测试函数。
let value : u64 = 444;
#[test(account = @0xf , i = @value)]
fun test_write(account: signer,i: u64) acquires Resource {
write(&account,i);
}
//错误 只能传递signer参数
#[test(account = @0xf)]
fun test_write(account: signer) acquires Resource {
write(&account, 33);
}
//错误 每个测试结束后,会清除相关的上下文.也就是说每个
测试是独立的。write的前提需要先执行publish。
#[test(account = @0xf)]
fun test_write(account: signer) acquires Resource {
publish(&account);
write(&account, 33);
}
// 正确 执行结果如下所示:
ouhuang@LAPTOP-HM465BTT:~/learn_move$ move test
INCLUDING DEPENDENCY MoveNursery
INCLUDING DEPENDENCY MoveStdlib
BUILDING learn_move
Running Move unit tests
[ PASS ] 0x4::Test::test_publish
[debug] 335
[ PASS ] 0x4::Test::test_write
Test result: OK. Total tests: 2; passed: 2; failed: 0
编写脚本,调用0x4名下的Test模块的publish函数。
//sources/test_script.move
script {
use std::debug;
use 0x4::Test;
fun debug_script(account: signer) {
Test::publish(&account);
Test::write(&account, 333);
debug::print(&b"Success!");
}
}
move sandbox run sources/test_script.move --signers 0xf -v --dry-run
在这条命令中,如果去掉--dry-run
参数执行,会立即提交结果。
ouhuang@LAPTOP-HM465BTT:~/learn_move$ move sandbox run sources/test_script.move --signers 0xf -v --dry-run
[debug] 333
[debug] (&) [83, 117, 99, 99, 101, 115, 115, 33]
Changed resource(s) under 1 address(es):
Changed 1 resource(s) under address 0000000000000000000000000000000F:
Added type 0x4::Test::Resource: [77, 1, 0, 0, 0, 0, 0, 0] (wrote 40 bytes)
key 0x4::Test::Resource {
i: 333
}
Wrote 40 bytes of resource ID's and data
Discarding changes; re-run without --dry-run if you would like to keep them.
Aptos是基于Move语言的智能合约框架,链上的合约是要被调用的,用户可以直接调用被entry
关键字修饰的module中的函数。
set_message is a script function allowing it to be called directly by transactions.
在Aptos框架下,单元测试函数写法和move的写法相同,唯一不同的是,单元测试执行的命令不同。
move项目是move test
。在aptos框架下是aptos move test --package-dir .
。
ouhuang@LAPTOP-HM465BTT:~/learn_move$ aptos move test --package-dir .
INCLUDING DEPENDENCY MoveNursery
INCLUDING DEPENDENCY MoveStdlib
BUILDING learn_move
Running Move unit tests
[ PASS ] 0x4::Test::test_publish
[debug] 335
[ PASS ] 0x4::Test::test_write
Test result: OK. Total tests: 2; passed: 2; failed: 0
{
"Result": "Success"
}
ouhuang@LAPTOP-HM465BTT:~/learn_move$ move test
INCLUDING DEPENDENCY MoveNursery
INCLUDING DEPENDENCY MoveStdlib
BUILDING learn_move
Running Move unit tests
[ PASS ] 0x4::Test::test_publish
[debug] 335
[ PASS ] 0x4::Test::test_write
Test result: OK. Total tests: 2; passed: 2; failed: 0
经过aptos move publish
后的合约会部署在Aptos链上,对链上合约的函数调用如果会改变状态,则被叫做发起交易。这个概念和Solidity是一样的。调用函数的方式有以下三种:
例:python sdk地址:https://aptos.dev/sdks/python-sdk
//合约编译
sudo aptos move compile --package-dir contract/sources/
//合约测试
sudo aptos move test --package-dir contract/
//合约发布
sudo aptos move publish --package-dir .
//函数调用:在终端,使用命令调用某个地址下的函数。
sudo aptos move run --function-id fbd4140a63e8fe7d6e9e25aff78e11876b1b6c21bc8d34b51cbfff40ca03164b::Test2::publish
至此,我们对Move项目和Aptos项目的单元测试及函数调用的研究就暂时告一段落。接下来是对Resource的操作教程。相信很快我们就能发现自己的ERC-20合约。^_^
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!