Sui Move - Unit Test 看这里 (Test Annotations)

  • Mindfrog
  • 更新于 2024-05-06 01:03
  • 阅读 215

发现很多初学者搞不清楚如何在Sui-Move里面写测试,现有的中文教程写的也不是特别清楚,但是这部分对于开发者来说又特别重要,所以花点时间来写一下,希望能帮助到有需要的小伙伴。

Let's Testing - Test Annotations

主要会分为两部分来讲解:

  1. Test Annotation主要讲一下关于测试注释的基本用法和一些个小例子。
  2. Test Scenario主要讲一下如何使用test_scenario 进行复杂的测试,辅以一些例子尽量让朋友们掌握并且可以运用到项目当中。

1 - Intro to Test Annotations

单元测试是一种软件测试方法,它通过对软件中的最小可测试 单元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>)]** 这指定测试预计会失败,并在指定位置出现气体耗尽错误。

这里就不多赘述了,感兴趣的小伙伴可以去Sui官方网站查询相关文档学习。
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Mindfrog
Mindfrog
0x6e43...Ff69
写一句话让别人不了解你