0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cadence Testing Framework

Last updated at Posted at 2024-10-19


Cadence テストフレームワークは、Cadence プログラムのテストを Cadence で記述する便利な方法を提供します。 この機能は、組み込みの`Test`スマートコントラクトによって提供されます。

Tip💡
テストフレームワークは、Flow CLI などのオフチェーンでのみ使用できます。

テストは、Cadence スクリプトの形式で記述する必要があります。 テストスクリプトには、testプレフィックスで始まるテスト関数、テストの前に必ず実行されるsetup関数、すべてのテストケースの最後に必ず実行されるtearDown関数、各テストケースの前に実行されるbeforeEach関数、各テストケースの後に実行されるafterEach関数を含めることができます。 上記の 4 つの関数はすべてオプションです。

// `setup`関数はその他のテストケースの前に常に実行される。テスト全体で使われるようなものを初期化するために使うことができる。
access(all)
fun setup() {
}

// `beforeEach` 関数は各テストケースの前に実行されます。
access(all)
fun beforeEach() {
}

// `afterEach` 関数は各テストケースの後に実行されます。
access(all)
fun afterEach() {
}

// 「test」という接頭辞で始まるものが有効なテスト関数です。
access(all)
fun testSomething() {
}

access(all)
fun testAnotherThing() {
}

access(all)
fun testMoreThings() {
}

// テスト関数には、引数や戻り値を指定することはできません。
access(all)
fun testInvalidSignature(message: String): Bool {
}

// すべてのテストケースの最後に必ず実行される `tearDown` 関数。
access(all)
fun tearDown() {
}

Test Standard Library

テストフレームワークは、組み込みの Testスマートコントラクトをインポートすることで使用できます。

import Test

Assertions

Test.assert

view fun assert(_ condition: Bool, message: String)

与えられた条件が偽の場合にテストケースを失敗させ、その理由を説明するメッセージを報告する。 message 引数はオプションである。

Test.fail

view fun fail(message: String)

テストケースを即座に失敗させ、その理由を説明するメッセージを表示します。
メッセージ引数はオプションです。

import Test

access(all)
fun testExample() {
    let array = [1, 2, 3]

    if array.length != 0 {
        Test.fail(message: "Array length is not 0")
    }
}

Test.expect

fun expect(_ value: AnyStruct, _ matcher: Matcher)

expect関数は、値をマッチャー(matchersのセクション参照)に対してテストし、一致しない場合はテストに失敗します。

import Test

access(all)
fun testExample() {
    let array = [1, 2, 3]

    Test.expect(array.length, Test.equal(3))
}

Test.assertEqual

fun assertEqual(_ expected: AnyStruct, _ actual: AnyStruct)

assertEqual関数は、与えられた値が等しくない場合にテストケースを失敗させ、2つの値がどのように異なるかを説明するメッセージを表示します。

import Test

access(all)
struct Foo {

    access(all)
    let answer: Int

    init(answer: Int) {
        self.answer = answer
    }
}

access(all)
fun testExample() {
    Test.assertEqual("this string", "this string")
    Test.assertEqual(21, 21)
    Test.assertEqual(true, true)
    Test.assertEqual([1, 2, 3], [1, 2, 3])
    Test.assertEqual(
        {1: true, 2: false, 3: true},
        {1: true, 2: false, 3: true}
    )

    let address1 = Address(0xf8d6e0586b0a20c7)
    let address2 = Address(0xf8d6e0586b0a20c7)
    Test.assertEqual(address1, address2)

    let foo1 = Foo(answer: 42)
    let foo2 = Foo(answer: 42)

    Test.assertEqual(foo1, foo2)

    let number1: Int64 = 100
    let number2: UInt64 = 100
    // Note that the two values need to have exactly the same type,
    // and not just value, otherwise the assertion fails:
    // assertion failed: not equal: expected: 100, actual: 100
    Test.assertEqual(number1, number2)
}

Test.expectFailure

fun expectFailure(_ functionWrapper: ((): Void), errorMessageSubstring: String)

expectFailure関数は、関数呼び出しをクロージャでラップし、指定したエラーメッセージ部分を含むエラーメッセージで失敗することを期待します。

import Test

access(all)
struct Foo {
    access(self)
    let answer: UInt8

    init(answer: UInt8) {
        self.answer = answer
    }

    access(all)
    fun correctAnswer(_ input: UInt8): Bool {
        if self.answer != input {
            panic("wrong answer!")
        }
        return true
    }
}

access(all)
fun testExample() {
    let foo = Foo(answer: 42)

    Test.expectFailure(fun(): Void {
        foo.correctAnswer(43)
    }, errorMessageSubstring: "wrong answer!")
}

`

Matchers

Matchersとは、テスト関数と関連ユーティリティ機能から構成されるオブジェクトです。
access(all)
struct Matcher {

    access(all)
    let test: fun(AnyStruct): Bool

    access(all)
    init(test: fun(AnyStruct): Bool) {
        self.test = test
    }

    /// Combine this matcher with the given matcher.
    /// Returns a new matcher that succeeds if this and the given matcher succeed.
    ///
    access(all)
    fun and(_ other: Matcher): Matcher {
        return Matcher(test: fun (value: AnyStruct): Bool {
            return self.test(value) && other.test(value)
        })
    }

    /// Combine this matcher with the given matcher.
    /// Returns a new matcher that succeeds if this or the given matcher succeeds.
    ///
    access(all)
    fun or(_ other: Matcher): Matcher {
        return Matcher(test: fun (value: AnyStruct): Bool {
            return self.test(value) || other.test(value)
        })
    }
}

test関数は値の評価基準を定義し、その値が関数で定義されたテスト基準に適合しているかどうかを示すブール値を返します。

andおよびor関数を使用して、このマッチャーを別のマッチャーと組み合わせて、複数のテスト基準を持つ新しいマッチャーを作成することができます。andメソッドは、このマッチャーと指定されたマッチャーの両方が成功した場合に成功する新しいマッチャーを返します。orメソッドは、このマッチャーまたは指定されたマッチャーの少なくとも一方が成功した場合に成功する新しいマッチャーを返します。

汎用的な型を持つテスト関数を受け入れるマッチャーは、newMatcher関数を使用して作成できます。

view fun newMatcher<T: AnyStruct>(_ test: fun(T): Bool): Test.Matcher

型パラメータTAnyStruct型にバインドされます。これもオプションです。

例えば、与えられた整数値が負であるかどうかをチェックするマッチャーは、以下のように定義できます。

import Test

access(all)
fun testExample() {
    let isNegative = Test.newMatcher(fun (_ value: Int): Bool {
        return value < 0
    })

    Test.expect(-15, isNegative)
    // Alternatively, we can use `Test.assert` and the matcher's `test` function.
    Test.assert(isNegative.test(-15), message: "number is not negative")
}

access(all)
fun testCustomMatcherUntyped() {
    let matcher = Test.newMatcher(fun (_ value: AnyStruct): Bool {
        if !value.getType().isSubtype(of: Type<Int>()) {
            return false
        }

        return (value as! Int) > 5
    })

    Test.expect(8, matcher)
}

access(all)
fun testCustomMatcherTyped() {
    let matcher = Test.newMatcher<Int>(fun (_ value: Int): Bool {
        return value == 7
    })

    Test.expect(7, matcher)
}

(他にもあります。詳しくは翻訳元の原文へ)
翻訳元->https://cadence-lang.org/docs/testing-framework


Previous << Measuring Time In Cadence

Flow BlockchainのCadence version1.0ドキュメント (Cadence Testing Framework)

Next >> スマートコントラクトによるdApp開発に関した技術情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?