发现很多初学者搞不清楚如何在Sui-Move里面写测试,现有的中文教程写的也不是特别清楚,但是这部分对于开发者来说又特别重要,所以花点时间来写一下,希望能帮助到有需要的小伙伴。
主要会分为两部分来讲解:
- Test Annotation主要讲一下关于测试注释的基本用法和一些个小例子。
- Test Scenario主要讲一下如何使用test_scenario 进行复杂的测试,辅以一些例子尽量让朋友们掌握并且可以运用到项目当中。
单元测试是一种软件测试方法,它通过对软件中的最小可测试 单元unit 进行检查和验证,以确保它们正常运行。这些最小单位通常是代码中的函数、方法或类。
- 在Move语言中单元测试分别通过以下三种注释来使用:
- #[test] 让注释方法变成仅用于测试;
- #[test_only] 将模块或模块成员(use、function、struct或const)注释为仅用于测试的代码。
- #[expected_failure] 希望被注释的测试方法执行的结果为失败。
- 调用测试方法的命令为
Sui move test
。 注意,#[test] 注释只能对不带参数的方法有效:#[test] // 执行Sui move test 后会打印 5 fun this_is_a_test() { let x:u8 = 5; debug::print(&x); }
#[test] //执行会报错,因为方法需要参数
fun this_is_not_correct (arg: u8){
debug::print(&arg);
}
## 2 - Example for Test Annotations
> 我们来制作一个简单的例子,熟悉Annotation的用法。
module letstesting::test_annotations {
//我们先引用一下debug,后续会用到他的print函数
use std::debug;
//我们定义一个常量,用来表示一种错误
const ECoinIsZero: u64 = 0;
//我们定义一个结构体Coin,他有一个名为value的u8字段,给予他drop能力方便后续的测试操作。
public struct Coin has drop {
value: u8,
}
//定义一个方法,传入一个Coin的引用
public fun make_sure_coin_is_not_zero(coin: &Coin) {
//调用debug::pirint 打印出传入Coin的信息
debug::print(coin);
//使用assert! 判断如果传入Coin的value不大于0,那么就抛出ECoinIsZero的错误
assert!(coin.value > 0 , ECoinIsZero);
}
//[test_only] 注释的方法只有在被[test]标注的方法调用时才会运行,
#[test_only]
fun make_coin_zero(coin:&mut Coin){
coin.value = 0;
}
// 这个测试方法会正常通过 Pass
#[test]
fun test_make_sure_coin_is_not_zero() {
//声明一个coin变量value为1
let coin = Coin { value: 1 };
//因为coin value 为1,方法不会抛出错误,测试Pass
make_sure_coin_is_not_zero(&coin);
}
//这个测试方法会正常通过 Pass
#[test]
//定义了一个具体的错误类型,指向ECoinIsZero
#[expected_failure(abort_code = ECoinIsZero)]
fun make_coin_zero_test() {
let mut coin = Coin { value: 1 };
//执行之前定义的[test_only]方法,把Coin的Value改为0
make_coin_zero(&mut coin);
//运行这个方法会抛出错误ECoinisZero,符合我们测试的要求也就是我们希望方法抛出ECoinIsZero,所以测试通过Pass
make_sure_coin_is_not_zero(&coin);
}
//定义一个抛出错误EAnotherError的方法
public fun another_error() {
abort EAnotherError;
}
//这个测试方法不会通过 FAIL
#[test]
//因为这里我们指定的错误是ECoinIsZero,但是抛出的错误是EAnotherError
#[expected_failure(abort_code = ECoinIsZero)]
fun another_error_test() {
another_error();
}
}
使用` Sui move test ` ,测试方法会从下往上运行,将会打印如下信息:
Running Move unit tests [ FAIL ] 0x0::test_annotations::another_error_test [debug] 0x0::test_annotations::Coin { value: 0 } [ PASS ] 0x0::test_annotations::make_coin_zero_test [debug] 0x0::test_annotations::Coin { value: 1 } [ PASS ] 0x0::test_annotations::test_make_sure_coin_is_not_zero
///这部分会告知测试出错的具体原因 Test failures:
Failures in 0x0::test_annotations:
//出错的具体方法
┌── another_error_test ──────
│ error[E11001]: test failure
│ ┌─ .\sources\test_annotations.move:17:9
│ │
│ 16 │ public fun another_error() {
│ │ ------------- In this function in 0x0::test_annotations
│ 17 │ abort EAnotherError
│ │ ^^^^^^^^^^^^^^^^^^^ Test did not error as expected. Expected test to abort with code 0 originating in the module 0000000000000000000000000000000000000000000000000000000000000000::test_annotations but instead it aborted with code 1 originating in the module 0000000000000000000000000000000000000000000000000000000000000000::test_annotations rooted here
│
│
│ stack trace
│ test_annotations::another_error_test(.\sources\test_annotations.move:43)
│
└──────────────────
Test result: FAILED. Total tests: 3; passed: 2; failed: 1
## 3 - End
掌握了以上知识后,关于测试Annotation的部分基本就算是够用了,当然还有其他的用法,例如:
- **\#[ expected_failure(arithmetic_error, location = \<location>)]** 这指定测试预计会因算术错误而失败(例如整数溢出、除以零等)
- **\#[ expected_failure(out_of_gas, location = \<location>)]** 这指定测试预计会失败,并在指定位置出现Gas耗尽错误。
这里就不多赘述了,感兴趣的小伙伴可以去Sui官方网站查询相关文档学习。
## 立即加入国内最牛逼的Move学习社区,搜索公众号:**HOH水分子**
![991c4c16f77d136253542d726bd79a5.jpg](https://img.learnblockchain.cn/attachments/2024/11/fWJalvOM67371315de130.jpg)
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!