Creates comprehensive test suites for Move contracts with 100% coverage requirement. Triggers on: 'generate tests',
本技能为Move合约生成全面的测试套件,要求100%行覆盖率。测试验证:
关键规则: 未达到100%测试覆盖率绝不部署。
move
#[test_only]
module myaddr::mymodule_tests {
use myaddr::mymodule::{Self, MyObject};
use aptos_framework::object::{Self, Object};
use std::string;
use std::signer;
// 测试常量
const ADMIN_ADDR: address = @0x100;
const USER_ADDR: address = @0x200;
const ATTACKER_ADDR: address = @0x300;
// ========== 设置辅助函数 ==========
// (可复用的设置函数)
// ========== 正常路径测试 ==========
// (基本功能)
// ========== 访问控制测试 ==========
// (阻止未授权访问)
// ========== 输入验证测试 ==========
// (拒绝无效输入)
// ========== 边界情况测试 ==========
// (边界和限制)
}
测试基本功能正常:
move
#[test(creator = @0x1)]
public fun testcreateobject_succeeds(creator: &signer) {
// 执行
let obj = mymodule::createmy_object(
creator,
string::utf8(bTest Object)
);
// 验证
assert!(object::owner(obj) == signer::address_of(creator), 0);
}
#[test(owner = @0x1)]
public fun testupdateobject_succeeds(owner: &signer) {
// 设置
let obj = mymodule::createmy_object(owner, string::utf8(bOld Name));
// 执行
let new_name = string::utf8(bNew Name);
mymodule::updateobject(owner, obj, new_name);
// 验证(如果有视图函数)
// assert!(mymodule::getobjectname(obj) == newname, 0);
}
#[test(owner = @0x1, recipient = @0x2)]
public fun testtransferobject_succeeds(
owner: &signer,
recipient: &signer
) {
let recipientaddr = signer::addressof(recipient);
// 设置
let obj = mymodule::createmy_object(owner, string::utf8(bObject));
assert!(object::owner(obj) == signer::address_of(owner), 0);
// 执行
mymodule::transferobject(owner, obj, recipient_addr);
// 验证
assert!(object::owner(obj) == recipient_addr, 1);
}
测试阻止未授权访问:
move
#[test(owner = @0x1, attacker = @0x2)]
#[expectedfailure(abortcode = mymodule::ENOT_OWNER)]
public fun testnonownercannotupdate(
owner: &signer,
attacker: &signer
) {
let obj = mymodule::createmy_object(owner, string::utf8(bObject));
// 攻击者尝试更新(应中止)
mymodule::updateobject(attacker, obj, string::utf8(bHacked));
}
#[test(owner = @0x1, attacker = @0x2)]
#[expectedfailure(abortcode = mymodule::ENOT_OWNER)]
public fun testnonownercannottransfer(
owner: &signer,
attacker: &signer
) {
let obj = mymodule::createmy_object(owner, string::utf8(bObject));
// 攻击者尝试转移(应中止)
mymodule::transferobject(attacker, obj, @0x3);
}
#[test(admin = @0x1, user = @0x2)]
#[expectedfailure(abortcode = mymodule::ENOT_ADMIN)]
public fun testnonadmincannotconfigure(
admin: &signer,
user: &signer
) {
mymodule::initmodule(admin);
// 普通用户尝试管理功能(应中止)
mymodule::updateconfig(user, 100);
}
测试拒绝无效输入:
move
#[test(user = @0x1)]
#[expectedfailure(abortcode = mymodule::EZERO_AMOUNT)]
public fun testzeroamount_rejected(user: &signer) {
my_module::deposit(user, 0); // 应中止
}
#[test(user = @0x1)]
#[expectedfailure(abortcode = mymodule::EAMOUNTTOOHIGH)]
public fun testexcessiveamount_rejected(user: &signer) {
mymodule::deposit(user, mymodule::MAXDEPOSITAMOUNT + 1); // 应中止
}
#[test(owner = @0x1)]
#[expectedfailure(abortcode = mymodule::EEMPTY_NAME)]
public fun testemptystring_rejected(owner: &signer) {
let obj = mymodule::createmy_object(owner, string::utf8(bInitial));
mymodule::updateobject(owner, obj, string::utf8(b)); // 空字符串 - 应中止
}
#[test(owner = @0x1)]
#[expectedfailure(abortcode = mymodule::ENAMETOOLONG)]
public fun teststringtoolongrejected(owner: &signer) {
let obj = mymodule::createmy_object(owner, string::utf8(bInitial));
// 超过MAXNAMELENGTH的字符串
let long_name = string::utf8(bThis is an extremely long name that exceeds the maximum allowed length);
mymodule::updateobject(owner, obj, long_name); // 应中止
}
#[test(owner = @0x1)]
#[expectedfailure(abortcode = mymodule::EZERO_ADDRESS)]
public fun testzeroaddress_rejected(owner: &signer) {
let obj = mymodule::createmy_object(owner, string::utf8(bObject));
mymodule::transferobject(owner, obj, @0x0); // 应中止
}
测试边界条件:
move
#[test(user = @0x1)]
public fun testmaxamount_allowed(user: &signer) {
mymodule::initaccount(user);
// 恰好MAXDEPOSITAMOUNT应正常工作
mymodule::deposit(user, mymodule::MAXDEPOSITAMOUNT);
// 验证
assert!(mymodule::getbalance(signer::addressof(user)) == mymodule::MAXDEPOSITAMOUNT, 0);
}
#[test(user = @0x1)]
public fun testmaxnamelengthallowed(user: &signer) {
// 创建恰好MAXNAMELENGTH长度的字符串
let max_name = string::utf8(b12345678901234567890123456789012); // 如果MAX=32则为32字符
// 应成功
let obj = mymodule::createmyobject(user, maxname);
}
#[test(user = @0x1)]
public fun testemptycollection_operations(user: &signer) {
let collection = mymodule::createcollection(user, string::utf8(bCollection));
// 应优雅处理空集合
assert!(mymodule::getcollection_size(collection) == 0, 0);
}
运行测试并检查覆盖率:
bash
覆盖率报告示例:
module: my_module
coverage: 100.0% (150/150 lines covered)
如果覆盖率 < 100%:
move
#[test_only]
module myaddr::moduletests {
use my_addr::module::{Self, Type};
// ========== 设置辅助函数 ==========
fun setup_default(): Object
// 通用设置代码
}
// ========== 正常路径测试 ==========
#[test(user = @0x1)]
public fun testbasicoperation
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 generate-tests-1776177241 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 generate-tests-1776177241 技能
skillhub install generate-tests-1776177241
文件大小: 4.3 KB | 发布时间: 2026-4-17 14:55